C/C++调用ffmpeg格式化字符串 动态读取音频设备 常见问题

最近写了一个屏幕录屏软件,主要是调用ffmpeg来实现录屏,因为是用的VS2015,遇到了不少字符转码的问题,特此记录一下。
①CStdioFile读取txt文本时中文乱码,需要一个CharToUTF8(str)函数

void CharToUTF8(CString &str)
{
	char *szBuf = new char[str.GetLength() + 1];//注意“+1”,char字符要求结束符,而CString没有
	memset(szBuf, '\0', str.GetLength());


	int i;
	for (i = 0; i < str.GetLength(); i++)
	{
		szBuf[i] = (char)str.GetAt(i);
	}
	szBuf[i] = '\0';//结束符。否则会在末尾产生乱码。

	int nLen;
	WCHAR *ptch;
	CString strOut;
	if (szBuf == NULL)
	{
		return;
	}
	nLen = MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, NULL, 0);//获得需要的宽字符字节数
	ptch = new WCHAR[nLen];
	memset(ptch, '\0', nLen);
	MultiByteToWideChar(CP_UTF8, 0, szBuf, -1, ptch, nLen);
	//str.Format(_T("%s"), ptch);
	str = ptch;
	if (NULL != ptch)
		delete[] ptch;
	ptch = NULL;


	if (NULL != szBuf)
		delete[]szBuf;
	szBuf = NULL;
	return;
}

②读取完txt后,通过字符串截取获取录音设备名

bool getdevinfo()
{
	CString strFile = L"devinfo.txt";
	CStdioFile infile;

	infile.Open(strFile, CFile::modeRead);

	CString str;
	while (infile.ReadString(str))
	{
		CharToUTF8(str);

		if (!(str.Find(L"dshow") == -1))
		{

			if (!(str.Find(L"麦克风") == -1))
			{
				int pos = str.Find(L"\"");
				str=str.Right(str.GetLength()-pos-1);
				pos = str.ReverseFind('\"');
				str = str.Left(pos);
				p_audioname = str;
				
			}

		}

	}
	infile.Close();
	return false;
}

③录音设备名此时需要动态给到ffmpeg的avformat_open_input函数,可以这样做

static char *dup_wchar_to_utf8(wchar_t *w)
{
	char *s = NULL;
	int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
	s = (char *)av_malloc(l);
	if (s)
		WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
	return s;
}
//查找输入方式
	CString p_audioname;//通过读取txt动态给到p_audioname
	AVInputFormat *pAudioInputFmt = av_find_input_format("dshow");
	//以Direct Show的方式打开设备,并将 输入方式 关联到格式上下文
	wchar_t w[200]=L"";
	wsprintf(w, L"audio=%s",p_audioname.GetBuffer());
	char * psDevName=dup_wchar_to_utf8(w);
	if (avformat_open_input(&pFormatCtx_Audio, psDevName, pAudioInputFmt, NULL) < 0)
	{
		AfxMessageBox(L"Couldn't open input stream.(无法打开音频输入流)");
		return -1;
	}

④mfc的控件“按钮”点击开始录制的话,需要新建一个线程,不然会一直锁在录像的死循环中

UINT startrec(LPVOID  lParam)
{
	
	getdevinfo();
	
	av_register_all();
	avdevice_register_all();
	//下面就是常规的录视频和录音频
	//此处省略
}

void CLLScreenRecDlg::OnBnClickedButton1()
{
	isclickstop = false;
	
	AfxBeginThread(startrec, (LPVOID)this);
	
	GetDlgItem(IDC_BUTTON1)->EnableWindow(false);
	GetDlgItem(IDC_BUTTON2)->EnableWindow(true);
	GetDlgItem(IDC_STATIC)->SetWindowTextW(L"正在录制中......");
	
}

可能还有更简单的方法,先记录一下,最起码亲测成功了。。。
讲道理win32宽字符挺恶心人的,各种编码转来转去。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++可以通过调用FFmpeg库来实现音视频处理。下面是一个简单的示例代码,演示了如何使用FFmpegC++中进行音频解码和视频解码: ```cpp #include <iostream> #include <string> extern "C" { #include <libavformat/avformat.h> #include <libswscale/swscale.h> } int main() { // 注册所有的FFmpeg组件 av_register_all(); // 打开输入文件 AVFormatContext* formatContext = nullptr; if (avformat_open_input(&formatContext, "input.mp4", nullptr, nullptr) != 0) { std::cerr << "无法打开输入文件" << std::endl; return -1; } // 获取流信息 if (avformat_find_stream_info(formatContext, nullptr) < 0) { std::cerr << "无法获取流信息" << std::endl; return -1; } // 查找第一个视频流 int videoStreamIndex = -1; for (unsigned int i = 0; i < formatContext->nb_streams; ++i) { if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } } if (videoStreamIndex == -1) { std::cerr << "找不到视频流" << std::endl; return -1; } // 获取视频解码器 AVCodecParameters* codecParameters = formatContext->streams[videoStreamIndex]->codecpar; AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id); if (codec == nullptr) { std::cerr << "找不到解码器" << std::endl; return -1; } // 创建解码器上下文 AVCodecContext* codecContext = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) { std::cerr << "无法创建解码器上下文" << std::endl; return -1; } // 打开解码器 if (avcodec_open2(codecContext, codec, nullptr) < 0) { std::cerr << "无法打开解码器" << std::endl; return -1; } // 创建帧对象 AVFrame* frame = av_frame_alloc(); // 读取视频帧 AVPacket packet; while (av_read_frame(formatContext, &packet) >= 0) { if (packet.stream_index == videoStreamIndex) { // 解码视频帧 avcodec_send_packet(codecContext, &packet); while (avcodec_receive_frame(codecContext, frame) == 0) { // 在这里可以对视频帧进行处理 } } av_packet_unref(&packet); } // 清理资源 av_frame_free(&frame); avcodec_free_context(&codecContext); avformat_close_input(&formatContext); return 0; } ``` 这段代码使用了FFmpeg库来打开一个视频文件,查找视频流,获取解码器并解码视频帧。你可以根据需要在代码中添加额外的处理逻辑。请确保你已经正确地安装并链接了FFmpeg库,并将输入文件名更改为你实际的视频文件路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值