开发工具VS2013
ffmpeg版本:4.3win32
实现功能:调用avcodec_open2初始化AVCodecContext,用于编码音频数据。
问题描述:调用avformat_open_input打开笔记本电脑的音频设备,如果正确打开音频设备avcodec_open2返回-22错误,如果未打开音频设备avcodec_open2返回0。avcodec_open2返回-22错误时,控制输出“COM must not be in STA mode”错误提示信息。
代码如下:
void test(){
avdevice_register_all();
// 初始化avformat_open_input
AVInputFormat *iInputFmt = av_find_input_format("dshow");
AVFormatContext *iFmtCtx(NULL);
std::string name = "EasyAudio";
int inputRet = avformat_open_input(&iFmtCtx, name.c_str(), iInputFmt, NULL);
// 初始化avcodec_open2相关形参
AVFormatContext *oFmtCtx(NULL);
int ret = avformat_alloc_output_context2(&oFmtCtx, NULL, NULL, "test.mp3");
ret = avio_open(&oFmtCtx->pb, "test.mp3", AVIO_FLAG_READ_WRITE);
AVCodec *tCodec = avcodec_find_encoder(AV_CODEC_ID_MP3);
AVCodecContext *tCodecCtx = avcodec_alloc_context3(tCodec);
tCodecCtx->codec_id = oFmtCtx->oformat->audio_codec;
tCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
tCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
tCodecCtx->sample_rate = 44100;
tCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
// 结果:如果inputRet >= 0时,avcodec_open2返回-22;如果inputRet < 0时,avcodec_open2返回0
if (0 > inputRet)
ret = avcodec_open2(tCodecCtx, tCodec, nullptr); // ret == 0
else
ret = avcodec_open2(tCodecCtx, tCodec, nullptr); // ret == -22
}
备注:
COM must not be in STA mode错误信息ffmpeg所在源码位置:Mf_utils.c文件中的init_com_mf(void*)函数内
static int init_com_mf(void *log)
{
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (hr == RPC_E_CHANGED_MODE) {
av_log(log, AV_LOG_ERROR, "COM must not be in STA mode\n");
return AVERROR(EINVAL);
} else if (FAILED(hr)) {
av_log(log, AV_LOG_ERROR, "could not initialize COM\n");
return AVERROR(ENOSYS);
}
hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
if (FAILED(hr)) {
av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n");
CoUninitialize();
return AVERROR(ENOSYS);
}
return 0;
}
问题已解决:不放在与界面有关的线程中,可以解决。而avformat_open_input(&iFmtCtx, name.c_str(), iInputFmt, NULL);因为使用了dshow所以算是和界面有关,不能与此放在同一个线程中。
不理解根本原因!希望得到大神们的帮助!