操作系统与网络 2019-4-19

该博客围绕直播项目展开,介绍了添加新文件,如在对话框添加按钮、用FFMPEG处理音视频并编码为mp4;更改错误,包括设置字符集和修改字符串操作;完成DlgMain对话框和TCPKernel类;还阐述了开始直播按钮的响应函数实现及为服务器端添加相关函数等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.添加部分新文件

1.1 给 DlgMain 对话框上添加两个按钮: 开始直播 按钮和 停止直播 按钮

1.2 本次直播项目中使用的是 FFMPEG 来处理视频,视频是通过 h264 进行编码的(进行编码的原因是每一帧图像较大,每秒想发送25帧图像,因此占用的网络资源较大,需要编码进行减小占用的网络资源)

1.3 本次直播项目中使用的是 WSAAPI 获取音频,并将音频进行 aac 编码

1.4 将图像与音频都进行编码之后将这两个编码为 mp4 文件,这其中涉及到 时间戳的对齐

1.5 将下载的文件放到项目中,将 dll 文件放到 Debug 目录下

1.6 添加一个新的筛选器 FFMPEG ,用来放 FFMPEG 相关的文件

1.7 添加库目录: …/lib;

1.8 添加附加依赖项,将下列语句添加到 附加依赖项 中

SDL2main.lib
SDL2.lib
avcodec.lib
avdevice.lib
avfilter.lib
swscale.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib

2.更改错误

2.1 新添加的文件需要 附加包含目录 : …/;

2.2 将项目的字符集更改为 Unicode (因为FFMPEG的默认编码形式为 Unicode)

2.3 将所有有关字符串操作的更改为 Unicode 相关的,将所有 strcpy_s 全部改为 WideCharToMultiByte ,将所有字符串全部改为 TCHAR

// strcpy_s(ssr.m_szName, sizeof(ssr.m_szName), m_name);
WideCharToMultiByte(CP_ACP, 0, m_name, -1, ssr.m_szName, sizeof(ssr.m_szName), 0, 0);

2.4 查看自己的摄像头的名称,在 Myffmpeg.cpp 中更改过来

void Myffmpeg::Factory(bool desk,bool camera,bool audio,bool microphone)
{
	if(desk == true && m_pDesktop == NULL)
	{
		m_pDesktop = new MyCollectDesktop(this);
		m_pDesktop->Initial();
	}
	if(audio == true && m_pAudio == NULL)
	{
		m_pAudio = new CCollectAudio(this);
		m_pAudio->Initial();
	}
	if(camera == true && m_pCamera == NULL)
	{
		m_pCamera = new CCollectCamera(_T("video=Lenovo EasyCamera"));
		m_pCamera->Start();
	}
}

3.完成DlgMain对话框

3.1 在对话框上添加三个check控件: 摄像头、桌面、声卡;添加一个 设置参数 按钮;

3.2 给三个check控件添加三个变量,类型都是 value BOOL 型: m_b_camera 、 m_b_desktop 、 m_b_voice ;

3.3 在 DlgMain 类中添加一个 FFMPEG 类对象,用来获取摄像头数据: Myffmpeg m_ffmpeg ;

3.4 在 设置参数 按钮中,获取控件上选中的check信息,使用ffmpeg调用工厂模式;

  • 1.我这里由于直接使用了新建对话框上面的按钮,因此这里的函数名为 OnBnClickedOk ,应该为 OnBnClickedButton 这种类型,请大家自己修改;
void CDlgMain::OnBnClickedOk()
{
	UpdateData(TRUE);

	// 使用 工厂模式 
	m_ffmpeg.Factory(m_b_desktop, m_b_camera, m_b_voice);
}

3.5 添加一个 开始直播 按钮

  • 1.在这个按钮中我们需要用 m_ffmpeg 对象来调用其中的 SetStart 函数;
void CDlgMain::OnBnClickedButton1()
{
	m_ffmpeg.SetStart(m_b_desktop, m_b_camera, m_b_voice);
}

3.6 在项目目录下新建一个 TempFile 文件夹,用来存储生成的 mp4 文件

3.7 注释掉 MyCollectDesktop::CollectDesktop 中的 ((TCPKernel*)theApp.m_p_kernel)->SendFileData(szPath,szFileName) 这行代码,即可将摄像头显示到对话框上

4.完成 TCPKernel 类

4.1 给 TCPKernel 类添加一个 SendFileData 函数,用来发送文件信息,这个函数已经被写好了,直接使用(也需自己看一遍,理解一下)

bool TCPKernel::SendFileData(char* szpath, char* szFileName)
{
	FILE *pFile = NULL;
	fopen_s(&pFile,szpath,"rb");
	if(pFile == NULL)
		return false;
	fseek(pFile,0,SEEK_END);
	int nFileSize = ftell(pFile);
	fseek(pFile,0,SEEK_SET);
	//发送文件信息(文件大小)

	STRU_UPLOADFILE su;
	su.m_n_type = _DEF_PROTOCOL_STREAMINFO_RQ;
	WideCharToMultiByte(CP_ACP,0,((CDlgMain*)theApp.m_pMainWnd)->m_name,-1,su.m_sz_name,sizeof(su.m_sz_name),0,0);
	strcpy_s(su.m_sz_content,sizeof(su.m_sz_content),szFileName);
	su.m_n_len = nFileSize;
	SendData((char*)&su,sizeof(su));
	//读文件内容并发送
	while(1)
	{
		su.m_n_type = _DEF_PROTOCOL_STREAMCONNECT_RQ;
		su.m_n_len = fread_s(su.m_sz_content,sizeof(su.m_sz_content),sizeof(char),sizeof(su.m_sz_content),pFile);
		if(su.m_n_len==0)
		{
			break;
		}
		SendData((char*)&su,sizeof(su));
	}

	fclose(pFile);
	return true;
}

4.2 在 PackDef.h 中添加一个结构体声明,这个结构体用来存放发送的文件的信息

#define MAX_CONTENTNUM 300

struct STRU_UPLOADFILE
{
	PackType m_n_type;
	char m_sz_name[DEF_SIZE];
	char m_sz_content[MAX_CONTENTNUM];
	int m_n_len;
}

4.3 将之前注释掉的 MyCollectDesktop::CollectDesktop 里的 ((TCPKernel*)theApp.m_p_kernel)->SendFileData(szPath,szFileName) 取消注释

5.继续 开始直播 按钮

5.1 完成按钮响应函数

  • 1.首先使用 m_ffmpeg 对象调用 SetStart 函数(之前已写);
  • 2.定义一个 开始传送 的结构体对象;
  • 3.给这个结构体赋值;
  • 4.使用 Kernel 进行发送数据包;
void CDlgMain::OnBnClickedButton1()
{
	m_ffmpeg.SetStart(m_b_desktop, m_b_camera, m_b_voice);

	STRU_STARTTRANSFER_RQ ssr;
	ssr.m_nType = _DEF_PROTOCOL_STARTTRANSFER_RQ;

	WideCharToMultiByte(CP_ACP, 0, m_name, -1, ssr.m_szName, sizeof(ssr.m_szName), 0, 0);

	theApp.m_p_kernel->SendData((char*)&ssr, sizeof(ssr));
}

5.2 给服务器端添加四个函数: StartTransferRq 、 StreamInfoRq 、 StreamContentRq 、 SelectAuthor 函数;

bool TCPKernel::StartTransferRq(SOCKET sock,char* szbuf)
{
	return true;
}

bool TCPKernel::StreamInfoRq(SOCKET sock,char* szbuf)
{
	return true;
}

bool TCPKernel::StreamContentRq(SOCKET sock,char* szbuf)
{
	return true;
}

bool TCPKernel::SelectAuthorRq(SOCKET sock,char* szbuf)
{
	return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值