如何确定编解码器/容器组合是否与FFmpeg兼容?

时间:2017-11-14 02:28:20

标签: audio ffmpeg libavcodec libav libavformat

我正在考虑重新复制一些容纳音频和视频的容器,以便我提取最好的第一个音频流,并将其存储在一个新的容器中,例如, 音频流存在。

FFmpeg的输出上下文的创建方式如下:

AVFormatContext* output_context = NULL;
avformat_alloc_output_context2( &output_context, NULL, "mp4", NULL );

我有一份可接受的输出名单,例如: MP4,M4A等......基本上是Apple的音频文件服务可读的那些:

kAudioFileAIFFType              = 'AIFF',
kAudioFileAIFCType              = 'AIFC',
kAudioFileWAVEType              = 'WAVE',
kAudioFileSoundDesigner2Type    = 'Sd2f',
kAudioFileNextType              = 'NeXT',
kAudioFileMP3Type               = 'MPG3',   // mpeg layer 3
kAudioFileMP2Type               = 'MPG2',   // mpeg layer 2
kAudioFileMP1Type               = 'MPG1',   // mpeg layer 1
kAudioFileAC3Type               = 'ac-3',
kAudioFileAAC_ADTSType          = 'adts',
kAudioFileMPEG4Type             = 'mp4f',
kAudioFileM4AType               = 'm4af',
kAudioFileM4BType               = 'm4bf',
kAudioFileCAFType               = 'caff',
kAudioFile3GPType               = '3gpp',
kAudioFile3GP2Type              = '3gp2',
kAudioFileAMRType               = 'amrf'

我的问题是:在FFmpeg中是否有一个简单的API,可以利用音频流所在的编解码器来选择兼容的输出容器?

2 个答案:

答案 0 :(得分:2)

有一个动态的方法可以解决这个问题。这枚举了每个容器的编解码器,但您也会得到相反的结果:

// enumerate all codecs and put into list
std::vector<AVCodec*> encoderList;
AVCodec * codec = nullptr;
while (codec = av_codec_next(codec))
{
    // try to get an encoder from the system
    auto encoder = avcodec_find_encoder(codec->id);
    if (encoder)
    {
        encoderList.push_back(encoder);
    }
}
// enumerate all containers
AVOutputFormat * outputFormat = nullptr;
while (outputFormat = av_oformat_next(outputFormat))
{
    for (auto codec : encoderList)
    {
        // only add the codec if it can be used with this container
        if (avformat_query_codec(outputFormat, codec->id, FF_COMPLIANCE_STRICT) == 1)
        {
            // add codec for container
        }
    }
}

如果只需要特定的容器或编解码器,则可以将白名单及其nameid字段使用,并在枚举时使用。

答案 1 :(得分:1)

对于每个单独的复用器,通常都有一个编解码器标签写入功能。该功能将检查另一个源文件中的列表,或者通过相同的switch语句进行处理。没有中央名册或容器匹配效用函数。您最好的选择是在libavcodec/allcodecs.c中识别编解码器ID,然后在libavformat/中为该ID识别,特别是在以enc为后缀的文件中,例如matroskaenc.c