ffmpeg3.3新版本AVStream的封装流参数由codec替换codecpar(解码)

原创夏曹俊2017-08-24 10:34:13评论(0)297人阅读

ffmpeg新版本中(封装流)AVStream的codec参数要被codecpar参数所替代,这样替代我们要注意什么,为什么要替代,我们先来看下ffmpeg的代码。

代码分析和新参数优势

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef struct AVStream {
#if FF_API_LAVF_AVCTX
/**
* @deprecated use the codecpar struct instead
*/
attribute_deprecated
AVCodecContext *codec;
#endif
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*
* Codec parameters associated with this stream. Allocated and freed by
* libavformat in avformat_new_stream() and avformat_free_context()
* respectively.
*
* - demuxing: filled by libavformat on stream creation or in
* avformat_find_stream_info()
* - muxing: filled by the caller before avformat_write_header()
*/
AVCodecParameters *codecpar;
}

从代码中我们可以看出codec参数在58版本及之后就不会支持了,需要由codecpar参数所替代。这样做的目的我想主要是将编码和封装彻底分离,之前封装和编码使用的参数都是存放在codec中,这样的好处是代码简洁,不需要额外给封装传递参数,但坏处是把编码和封装的代码融合在一块耦合性较大,有很多需求,我们只需要编码并不需要做封装,比如我们做自己的推流协议,直接吧编码后h264数据通过自定义的协议发送。

再比如直播推流中我们编码和封装推流会在不同的线程中处理,如果共用一个上下文肯定还需要处理互斥问题,分开就不会存在这个问题。

既然必须要替换我们如何处理;

比如原来的视频播放处理方式是这样(错误处理省略):

1
2
3
4
5
6
7
//打开多媒体文件,我们假定视频流索引为0
AVFormatContext *ic = NULL;
avformat_open_input(&ic, "test.mp4", 0, 0);
//找到视频解码器,比如H264
  AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codec->codecid);
  //打开视频解码器,打开音频解码器用的也是同一个函数
avcodec_open2(enc, ic->streams[0]->codec, NULL);

看代码我们知道avformat_open_input之后音视频的配置信息已经被写在了codec中,解封装和解码用同一套参数。但是如果替换为codecpar ,那解码器是独立创建的,那是否还要手动填写一遍解码参数,理论上是需要的,不过还好ffmpeg提供给我们一个函数做参数复制

int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);

那我们codec参数替换为codecpar 代码就可以这样写了(错误处理省略)

1
2
3
4
5
6
7
8
9
//打开多媒体文件,我们假定视频流索引为0
AVFormatContext *ic = NULL;
avformat_open_input(&ic, "test.mp4", 0, 0);
//找到视频解码器,比如H264
  AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codecpar->codec_id);
//独立的解码上下文
AVCodecContext * vc = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(vc, ic->streams[0]->codecpar);
avcodec_open2(vc, codec, NULL);

代码改变后解码上下文就是独立的,后面解码也不需要与解封装上下文关联,包括清理。

解码器的ID号也变为从codecpar->codec_id成员获取。

ffmpeg新版本中(封装流)AVStream的codec参数要被codecpar参数所替代,这样替代我们要注意什么,为什么要替代,我们先来看下ffmpeg的代码。
代码分析和新参数优势
typedef struct AVStream {
#if FF_API_LAVF_AVCTX
/**
* @deprecated use the codecpar struct instead
*/
attribute_deprecated
AVCodecContext *codec;
#endif
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/*
* Codec parameters associated with this stream. Allocated and freed by
* libavformat in avformat_new_stream() and avformat_free_context()
* respectively.
*
* - demuxing: filled by libavformat on stream creation or in
* avformat_find_stream_info()
* - muxing: filled by the caller before avformat_write_header()
*/
AVCodecParameters *codecpar;
}
从代码中我们可以看出codec参数在58版本及之后就不会支持了,需要由codecpar参数所替代。这样做的目的我想主要是将编码和封装彻底分离,之前封装和编码使用的参数都是存放在codec中,这样的好处是代码简洁,不需要额外给封装传递参数,但坏处是把编码和封装的代码融合在一块耦合性较大,有很多需求,我们只需要编码并不需要做封装,比如我们做自己的推流协议,直接吧编码后h264数据通过自定义的协议发送。
再比如直播推流中我们编码和封装推流会在不同的线程中处理,如果共用一个上下文肯定还需要处理互斥问题,分开就不会存在这个问题。
既然必须要替换我们如何处理;
比如原来的视频播放处理方式是这样(错误处理省略):
//打开多媒体文件,我们假定视频流索引为0
AVFormatContext *ic = NULL;
avformat_open_input(&ic, "test.mp4", 0, 0);
//找到视频解码器,比如H264
  AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codec->codecid);
  //打开视频解码器,打开音频解码器用的也是同一个函数
avcodec_open2(enc, ic->streams[0]->codec, NULL);
看代码我们知道avformat_open_input之后音视频的配置信息已经被写在了codec中,解封装和解码用同一套参数。但是如果替换为codecpar ,那解码器是独立创建的,那是否还要手动填写一遍解码参数,理论上是需要的,不过还好ffmpeg提供给我们一个函数做参数复制
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
那我们codec参数替换为codecpar 代码就可以这样写了(错误处理省略)
//打开多媒体文件,我们假定视频流索引为0
AVFormatContext *ic = NULL;
avformat_open_input(&ic, "test.mp4", 0, 0);
//找到视频解码器,比如H264
  AVCodec *codec = avcodec_find_decoder(ic->streams[0]->codecpar->codec_id);
//独立的解码上下文
AVCodecContext * vc = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(vc, ic->streams[0]->codecpar);
avcodec_open2(vc, codec, NULL);
代码改变后解码上下文就是独立的,后面解码也不需要与解封装上下文关联,包括清理。
解码器的ID号也变为从codecpar->codec_id成员获取。

ffmpeg3.3新版本AVStream的封装流参数由codec替换codecpar相关推荐

  1. 十一、Struts2封装请求参数的方式

    十一.Struts2封装请求参数的方式 方式一.Action 本身作为model对象,通过成员setter封装(一个名字为params的拦截器干的) 注意:表单中的名称要和动作类中的名称一致(这是必须 ...

  2. 2※、封装流(包装流派)、缓冲流【字节缓冲流、字符缓冲流】-->【字节缓冲流、字符缓冲流】 、字符集、转换流以及打印流

    封装流(包装流) ※缓冲流 [字节缓冲流.字符缓冲流] 缓冲流[字节流]文件复制以及BufferedOutputStream的源码查看 缓冲流[字符流] [读取操作.写出操作] 练习:文本排序:请将文 ...

  3. 如何修改相机码流参数和抓拍图片大小?

    Q:如何修改相机码流参数和抓拍图片大小? A:进入[配置]>[图像配置]>[编码]中,可以对相机的编码相关选项进行配置. 图像采集制式指相机采集图像的制式,默认情况下不需要修改. 主码流部 ...

  4. 【SpringBoot专题】整合mybatis-plus之封装查询参数简化查询

    [SpringBoot专题]整合mybatis-plus之封装查询参数简化查询 通常开发过程中,操作数据库是作为后端开发必要掌握的本领,今天分享的是springboot整合mybatis-plus,官 ...

  5. pandas使用read_csv函数读取文件时指定数据列的数据类型、pandas使用read_csv函数读取文件时通过keep_default_na参数设置缺失值替换为空字符串

    pandas使用read_csv函数读取文件时指定数据列的数据类型.pandas使用read_csv函数读取文件时通过keep_default_na参数设置缺失值替换为空字符串 目录

  6. SIwave仿真入门 | PI篇——封装PDN参数仿真

    目录 前言 1. 仿真流程 2. EDA模型导入 3. 模型处理 4. 端口及求解设置 5. 仿真结果 6. 结果导出 关注"电磁学社",让电磁仿真不再复杂! 前言 本文介绍如何利 ...

  7. PageHelper 封装返回参数

    解决了什么问题? 有时候我们并不需要那么多的返回参数,需要适当精简. 一,首先需要一个PageBean import java.io.Serializable; import java.util.Li ...

  8. Android中的封装流式布局FlowLayout

    鸿洋的GitHub:https://github.com/hongyangAndroid/FlowLayout 第一步:加依赖 implementation 'com.hyman:flowlayout ...

  9. 用js参数实现模板替换机制

    Ext中为String扩展了一个静态方法format用于实现对字符串类模板机制的格式化. 如String.format("{0},{1},{2}","a",&q ...

最新文章

  1. java好还是python好-现在学Python还是Java好呢?
  2. mysql workbench中删除数据表记录提示出错的问题
  3. c语言坐标三角形判断,【C语言】判断三角形类型(示例代码)
  4. C51语言支持哪些数据类型,C51编译器支持的数据类型(1)
  5. 西南大学计算机与信息科学学院陈武,学院副院长——陈武 - 计算机与信息科学学院 - Powered by 西南大学...
  6. VMware 修复 Fusion 和 Horizon 中的两个提权漏洞
  7. yolobile 道路损坏检测实战
  8. 正则表达式 - 中文、英文姓名匹配
  9. 对话机器学习大神Yoshua Bengio(下)
  10. 开发嵌入式软件构建管道
  11. Deprecated注解
  12. 解决拉取远程分支后出现.xcodeproj Couldn't load project的问题
  13. 编译程序原理VS解释程序原理
  14. uniapp开发微信小程序,开发者工具、真机预览都没问题,唯独预览、体验版在手机上列表顺序错乱,用的localeCompare做的中文排序,终于找到问题并解决掉了,记录一下子
  15. 简单三步实现给公众号添加附件
  16. Linux系列(四)、文件属性查看和修改,以及软硬连接
  17. Neural-Motifs 源码解读(3):RelModel类
  18. Python 负数的补码表示
  19. Linux安装IPFS
  20. 有情人终成眷属---为好友hualex2006.12.9结婚祝福

热门文章

  1. linux跨服务器复制文件夹,linux下跨服务器文件文件夹的复制
  2. 专题 7 设备文件编程
  3. bash: 无法为立即文档创建临时文件: 权限不够_世界顶级Linux大牛耗时三年总结出3000页Linux文档...
  4. session与cookie的区别
  5. Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
  6. drupal与html转换,Drupal 7修改網頁HTML和顯示Title的辦法
  7. 前端html继承的方式,好程序员web前端教程之JS继承实现方式解析
  8. linux ssh别的机器,Linux SSH 登录其他机器
  9. 华为 mysql实例监控,华为云文档数据库服务DDS监控告警全新优化
  10. linux服务器安全文档,CentOS Linux服务器安全设置