文档章节

Opus 编解码遇到的怪事

UMU
 UMU
发布于 2017/07/01 17:23
字数 499
阅读 208
收藏 0

    最近参考 ffmpeg 的 transcoding_aac 示例代码,写了一个 transcoding_opus,并拿 MP3 测试转码,结果发现转完的 opus 文件的 SampleFormat 和指定的并不一样。UMU 的代码是把源文件解码出来的 sample 先 resample 成 AV_SAMPLE_FMT_S16 格式,然后再交给 opus encoder 去编码的,但是编完用 ffprobe 查看,发现 SampleFormat 变成 AV_SAMPLE_FMT_FLTP。

    那么第一个问题来了,为什么会这样?

    开始研究,首先 UMU 把 opus encoder 支持的 sample_fmt 打印出来,发现只有两种:AV_SAMPLE_FMT_S16、AV_SAMPLE_FMT_FLT,压根就没有 AV_SAMPLE_FMT_FLTP,强行指定 AV_SAMPLE_FMT_FLTP 之后,直接报错,不支持这种 sample_fmt。

    推测,真的被编码为 AV_SAMPLE_FMT_S16 了,是 ffprobe 的问题,于是自己写了个简化版的 ffprobe,流程几乎是一样的,出来的结果——果然一模一样……打印出 AV_SAMPLE_FMT_FLTP。

    接着怀疑 ffprobe 用的 decoder,于是去看了 avcodec_find_decoder 返回的 AVCodec,打印一下 name 和 long_name,和 transcoding_opus 的 avcodec_find_encoder 返回的一比,果然不一样……

    选用的编码器是这样的:

AVCodec ff_libopus_encoder = {
    .name            = "libopus",
    .long_name       = NULL_IF_CONFIG_SMALL("libopus Opus"),
    .type            = AVMEDIA_TYPE_AUDIO,
    .id              = AV_CODEC_ID_OPUS,
    .priv_data_size  = sizeof(LibopusEncContext),
    .init            = libopus_encode_init,
    .encode2         = libopus_encode,
    .close           = libopus_encode_close,
    .capabilities    = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
    .sample_fmts     = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_FLT,
                                                      AV_SAMPLE_FMT_NONE },
    .supported_samplerates = libopus_sample_rates,
    .priv_class      = &libopus_class,
    .defaults        = libopus_defaults,
};

    而选用的解码器是这样的:

AVCodec ff_opus_encoder = {
    .name           = "opus",
    .long_name      = NULL_IF_CONFIG_SMALL("Opus"),
    .type           = AVMEDIA_TYPE_AUDIO,
    .id             = AV_CODEC_ID_OPUS,
    .defaults       = opusenc_defaults,
    .priv_class     = &opusenc_class,
    .priv_data_size = sizeof(OpusEncContext),
    .init           = opus_encode_init,
    .encode2        = opus_encode_frame,
    .close          = opus_encode_end,
    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
    .capabilities   = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
    .supported_samplerates = (const int []){ 48000, 0 },
    .channel_layouts = (const uint64_t []){ AV_CH_LAYOUT_MONO,
                                            AV_CH_LAYOUT_STEREO, 0 },
    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                     AV_SAMPLE_FMT_NONE },
};

    问题清楚了,看来用 ID 查找编解码器并不靠谱,因为这个 ID 是 Type ID,不是 Item ID,还是改为用 name 来找:

//AVCodec *output_codec = avcodec_find_encoder(AV_CODEC_ID_OPUS);
AVCodec *output_codec = avcodec_find_encoder_by_name("opus");

    那么,第二个问题顺势而来……哪个比较牛?

    用 AV_SAMPLE_FMT_FLTP 后 frame_size 是 120,用其它是 960,frame_size 小有小的好处,比如在做实时编码直播时,理论延迟会更小。

    经过测试,用 AV_SAMPLE_FMT_FLTP 的 opus 比 libopus 压缩率普遍略高一些,但它只支持 48000Hz 一种 sample_rate,libopus 支持的更多:48000, 24000, 16000, 12000, 8000。

© 著作权归作者所有

共有 人打赏支持
UMU

UMU

粉丝 118
博文 112
码字总数 44043
作品 0
厦门
程序员
私信 提问
加载中

评论(1)

sandmanhome
sandmanhome
居然还有这种坑:satisfied:
Baresip 0.4.9 发布,SIP 用户代理

Baresip 是一个可移植的模块化的 SIP 用户代理,支持音频和视频。 Baresip 0.4.9 发布,此版本支持 ZRTP media 加密(通过新模块 zrtp.so);支持 LLVM clang 编译;添加一个日志框架; OPUS...

oschina
2014/01/08
412
0
Agora SOLO X™:兼容 WebRTC 标准的抗丢包语音编码器

本文分享了声网Agora 首席音频工匠高泽华在 RTC 2018 实时互联网大会上,以《SOLO X™:兼容 WebRTC 标准的抗丢包语音编码器》为题的演讲。主要介绍了声网推出的抗丢包语音编码器 Agora SOLO...

Agora
10/12
0
0
Microsoft Edge 将支持开源视频编解码器 VP9

今天微软宣布 Microsoft Edge 将会支持开源视频编解码器 WebM/VP9,现在正在开发过程中。VP9 是开源编码器,提供高效的流 HD 内容压缩,有更低的压缩比率,适用于 UHD 流。VP9 最初支持不久后...

oschina
2015/09/09
2.5K
8
iOS下 AAC 音频编码

编码结构图 前言 iOS下Apple为我们提供了非常方便的音频编解码工具AudioToolbox。该工具中包含了常见的编解码库,如AAC、iLBC、OPUS等。今天我们就介绍一下如何使用 AudioToolbox 进行AAC音频...

音视频直播技术专家
2017/10/14
0
0
Opus 1.1 发布,最高支持255个音频通道

Opus开源免专利费音频编解码器发布了1.1版, 改进了环绕声编码,支持最高255个音频通道。Opus合并了Xiph.org的CELT低延时音频编解码器和Skype的SILK语音编解码器,专为互联网音频设计,可用于...

oschina
2013/12/08
2.2K
2

没有更多内容

加载失败,请刷新页面

加载更多

(三)Honghu Cloud云架构一定时调度平台

2018-11-16 14:45:08 产品简介 鸿鹄云架构是一个完全由Java编写的开源任务调度框架,为企业在任务调度提供了简单却强大的机制。开发人员根据业务规则,使用调度平台简单配置,就可以让任务在...

itcloud
4分钟前
0
0
护航Lazada双11购物节 阿里云CDN全球化火力全开

摘要: Lazada是东南亚最大B2C平台,业务范围覆盖印度尼西亚、马来西亚、菲律宾、新加坡、泰国和越南六个东南亚国家,覆盖大约6亿消费者。在双11期间,阿里云CDN为Lazada电商内容加速,并且通...

阿里云官方博客
4分钟前
0
0
常用设计模式之代理模式解析

1. 简介 代理模式(Proxy Pattern)是常用设计模式之一。代理模式的定义:Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个...

老道士
5分钟前
0
0
Vue瀑布流插件的使用示例

我自己写的一个的Vue瀑布流插件,列数自适应,不用设置每个卡片的高度。 测试页面:Page.vue 模板页面:WaterFollow.vue 和 WFColumn.vue 在Page.vue中,修改itemW的值,设置每列的最小宽度。...

peakedness丶
5分钟前
0
0
多种负载均衡算法及其Java代码实现【网络上较好的转载】

首先给大家介绍下什么是负载均衡(来自百科) 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提高网...

stys352
9分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部