avformat_open_input无法打开包含原始作品音频数据的文件

问题描述

尝试打开包含opus格式的原始音频数据的二进制文件时遇到问题。当我尝试打开此文件时,库返回错误未知输入格式:opus

如何打开此文件

我需要打开它,并将所有原始音频数据写入音频容器。我了解opus格式仅适用于encoding。我使用命令实现了这一点:

$ ffmpeg -formats | grep Opus

ffmpeg version 3.4.4 copyright (c) 2000-2018 the FFmpeg developers
  E opus Ogg Opus # For only encoding

那我应该用什么格式打开这个文件?使用 ogg 吗?我尝试过,但是打开传出文件也有问题。我提供的代码显示打开文件所需的部分:

int main(int argc,char *argv[])
{
    // ...

    av_register_all();

    AVFormatContext *iFrmCtx = nullptr;
    AVFormatContext *oFrmCtx = nullptr;
    AVPacket packet;

    const char *iFilename = "opus.bin"; // Raw audio data with `opus` format
    const char *oFilename = "opus.mka"; // Audio file with `opus` audio format

    AVDictionary* frmOpts = nullptr;
    const qint32 smpRateErrorCode = av_dict_set_int(&frmOpts,"sample_rate",8000,0);
    const qint32 bitRateErrorCode = av_dict_set_int(&frmOpts,"bit_rate",64000,0);
    const qint32 channelErrorCode = av_dict_set_int(&frmOpts,"channels",2,0);
    if (smpRateErrorCode < 0 ||
            bitRateErrorCode < 0 ||
                channelErrorCode < 0) {
        return EXIT_FAILURE;
    }

    AVInputFormat *iFrm = av_find_input_format("opus"); // Error: UnkNown input format
    if (iFrm == nullptr) {
        av_dict_free(&frmOpts);
        return EXIT_FAILURE;
    }

    qint32 ret = 0;
    if ((ret = avformat_open_input(&iFrmCtx,iFilename,iFrm,&frmOpts)) < 0) {
        av_dict_free(&frmOpts);
        return EXIT_FAILURE;
    }

    // We're doing something...
}

解决方法

正如Opus不能自我界定之前所说,它需要一个容器。并且由于您是从rtp有效负载中获取原始数据的,而opus编解码器是动态编解码器(具有动态有效负载大小),因此您无法使用ffmpeg AVFormatContext从文件中读取原始数据。

但是您可以解决此问题,而不是使用(av_read_frame)填充AVPacket对其进行解码,可以手动填充AVPacket数据和大小,然后将其推入解码器。

请注意,您还应该为每个AVPacket更新pts和dts。