【问题标题】:avformat_open_input cannot open a file with raw opus audio dataavformat_open_input 无法打开带有原始作品音频数据的文件
【发布时间】:2021-01-21 09:40:36
【问题描述】:

我在尝试打开包含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 格式的原始音频数据是什么意思? Opus 不是自定界的,它需要一个容器(OGG、Matroska、ISO BMFF 可能/建议、UDP/RTP)。在 RFC 6716 中有一个用于自定界帧的附录 B,但它通常用于为多个流/通道打包数据包,并且它仍然依赖于传输层来发出信号。我在 FFmpeg 中知道的所有解复用器都是用于 OGG 的。无论如何,使用虚拟的image2 demuxer 似乎至少能够检测从 RTP 有效负载中提取的作品,但不确定它是否在所有情况下都能解码,无论如何这都是个坏主意。
  • @aergistal,opus 格式是指音频数据以 opus 编码(也可以是 pcm_alaw 音频数据、pcm_mulaw 等)。在实践中,我得到 RTP 数据包,其中 opus 音频数据存储在有效负载中。然后我从 RTP 数据包中提取有效负载并将其发送到音频编码器。在我的示例中,我只想从文件中提取所有 opus 格式的音频数据,并将其打包为 Matroska 格式。
  • @aergistal,音频数据没有问题alawmulaws16les16be(因为avformat_open_input 找到了这些格式),但我的作品有问题,在问题本身中进行了描述。如果你愿意,我可以给你我自己的代码 (~300 lines of code),我用它来将原始音频数据编码成一个音频文件 :)
  • 就像我说的,我没有看到任何用于原始有效负载的解复用器,只有 OGG。但是您可以编写一个快速解复用器来设置有效负载长度,然后将其传递给libopus(可选编解码器,您需要在 FFmpeg 配置期间启用)。不过没试过。
  • @aergistal,写一个解复用器,this 足以让我理解如何实现它吗?另外,这句话是什么意思:you need to enable during FFmpeg configure.

标签: c++ ffmpeg encode


【解决方案1】:

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

但是您可以解决这个问题,而不是使用 (av_read_frame) 填充 AVPacket 来解码它们,您可以手动填充 AVPacket 数据和大小,然后将其推送到解码器。

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

【讨论】:

  • 我需要填写哪些字段?我想我只需要填写buf::databuf::sizeptsdts。但是具体指定为ptsdts 我不知道。更准确地说,我不知道如何正确计算ptsdts的当前值。
  • pts 和 dts 对于每个数据包增加 960,对于 48KHz 作品流从零开始
  • 是否有关于如何为特定编解码器计算 ptsdts 的说明的链接?我的意思是,如果我得到采样率为44100 而不是48000OPUS 数据,那么ptsdts 会有任何变化吗?或者例如,GSM 编解码器的增量是多少。
  • 是的,它肯定会因一个编解码器而异,例如 mulaw 编解码器以 1024 递增。您可以查看此问题以更好地理解它stackoverflow.com/questions/43333542/…
  • 奇怪,因为在使用opus 音频编解码器查看音频文件中的ptsdts 字段时,值不均匀。您可以使用以下命令查看任何音频文件的ptsdts 输出示例:ffprobe -show_frames aud-opus-48000SampleRate-36000BitRate-2Channel.mka。您需要查看pkt_ptspkt_dts 字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
相关资源
最近更新 更多