FFMPEG解码学习笔记(一)

FFMPEG的基本处理流程

音频视频同步资料

av_frame_get_pkt_duration(frame)

获取当前帧的持续时间

av_frame_get_pkt_pos(frame)

从最后一个AVPacket进入解码重新排序的偏移量

av_frame_get_best_effort_timestamp(frame)

已流中的时间为基础预估的时间戳

  1. /**
  2. * When decoding, this signals how much the picture must be delayed.
  3. * extra_delay = repeat_pict / (2*fps)
  4. */
  5. int repeat_pict;

当解码时,这个信号告诉你这张图片需要要延迟多少久。

需要求出扩展延时:

extra_delay = repeat_pict / (2*fps)

  1. /**
  2. * This is the fundamental unit of time (in seconds) in terms
  3. * of which frame timestamps are represented. For fixed-fps content,
  4. * timebase should be 1/framerate and timestamp increments should be
  5. * identically 1.
  6. * This often, but not always is the inverse of the frame rate or field rate
  7. * for video. 1/time_base is not the average frame rate if the frame rate is not
  8. * constant.
  9. *
  10. * Like containers, elementary streams also can store timestamps, 1/time_base
  11. * is the unit in which these timestamps are specified.
  12. * As example of such codec time base see ISO/IEC 14496-2:2001(E)
  13. * vop_time_increment_resolution and fixed_vop_rate
  14. * (fixed_vop_rate == 0 implies that it is different from the framerate)
  15. *
  16. * - encoding: MUST be set by user.
  17. * - decoding: the use of this field for decoding is deprecated.
  18. * Use framerate instead.
  19. */
  20. AVRational time_base;

当前帧需要耗时多少秒,每一帧显示的时间

由以上两个定义可以推导:

extra_delay = repeat_pict / (2*fps)

fps=1/time_base

那么

extra_delay= repeat_pict*time_base*0.5

AVCodecContent

  1. /**
  2. * Allocate an AVCodecContext and set its fields to default values. The
  3. * resulting struct should be freed with avcodec_free_context().
  4. *
  5. * @param codec if non-NULL, allocate private data and initialize defaults
  6. * for the given codec. It is illegal to then call avcodec_open2()
  7. * with a different codec.
  8. * If NULL, then the codec-specific defaults won‘t be initialized,
  9. * which may result in suboptimal default settings (this is
  10. * important mainly for encoders, e.g. libx264).
  11. *
  12. * @return An AVCodecContext filled with default values or NULL on failure.
  13. */
  14. AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

分配一个AVCodecContent并为其分配默认值。(可理解为一个AVCodecContent分配内存空间)

释放它的资源使用avcodec_free_context()。

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

  1. /**
  2. * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
  3. * function the context has to be allocated with avcodec_alloc_context3().
  4. *
  5. * The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
  6. * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
  7. * retrieving a codec.
  8. *
  9. * @warning This function is not thread safe!
  10. *
  11. * @note Always call this function before using decoding routines (such as
  12. * @ref avcodec_receive_frame()).
  13. *
  14. * @code
  15. * avcodec_register_all();
  16. * av_dict_set(&opts, "b", "2.5M", 0);
  17. * codec = avcodec_find_decoder(AV_CODEC_ID_H264);
  18. * if (!codec)
  19. * exit(1);
  20. *
  21. * context = avcodec_alloc_context3(codec);
  22. *
  23. * if (avcodec_open2(context, codec, opts) < 0)
  24. * exit(1);
  25. * @endcode
  26. *
  27. * @param avctx The context to initialize.
  28. * @param codec The codec to open this context for. If a non-NULL codec has been
  29. * previously passed to avcodec_alloc_context3() or
  30. * for this context, then this parameter MUST be either NULL or
  31. * equal to the previously passed codec.
  32. * @param options A dictionary filled with AVCodecContext and codec-private options.
  33. * On return this object will be filled with options that were not found.
  34. *
  35. * @return zero on success, a negative value on error
  36. * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),
  37. * av_dict_set(), av_opt_find().
  38. */
  39. int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

使用AVCodec初始化AVCodecContext。在初始化之前需要为其分配内存。

  1. /**
  2. * Copy the settings of the source AVCodecContext into the destination
  3. * AVCodecContext. The resulting destination codec context will be
  4. * unopened, i.e. you are required to call avcodec_open2() before you
  5. * can use this AVCodecContext to decode/encode video/audio data.
  6. *
  7. * @param dest target codec context, should be initialized with
  8. * avcodec_alloc_context3(NULL), but otherwise uninitialized
  9. * @param src source codec context
  10. * @return AVERROR() on error (e.g. memory allocation error), 0 on success
  11. *
  12. * @deprecated The semantics of this function are ill-defined and it should not
  13. * be used. If you need to transfer the stream parameters from one codec context
  14. * to another, use an intermediate AVCodecParameters instance and the
  15. * avcodec_parameters_from_context() / avcodec_parameters_to_context()
  16. * functions.
  17. */
  18. attribute_deprecated
  19. int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);

该函数已不建议使用。它可以将原AVCodecContext的设置拷贝到目标AVCodecContent。

如果在使用这个数据之前调用avcodec_open2(),会导致无法打开。

建议使用avcodec_parameters_from_context() / avcodec_parameters_to_context()传递参数。

  1. /**
  2. * Fill the parameters struct based on the values from the supplied codec
  3. * context. Any allocated fields in par are freed and replaced with duplicates
  4. * of the corresponding fields in codec.
  5. *
  6. * @return >= 0 on success, a negative AVERROR code on failure
  7. */
  8. int avcodec_parameters_from_context(AVCodecParameters *par,
  9. const AVCodecContext *codec);

从一个AVCodecContent中拷贝出AVCodecParameters

  1. /**
  2. * Fill the codec context based on the values from the supplied codec
  3. * parameters. Any allocated fields in codec that have a corresponding field in
  4. * par are freed and replaced with duplicates of the corresponding field in par.
  5. * Fields in codec that do not have a counterpart in par are not touched.
  6. *
  7. * @return >= 0 on success, a negative AVERROR code on failure.
  8. */
  9. int avcodec_parameters_to_context(AVCodecContext *codec,
  10. const AVCodecParameters *par);

向一个AVCodecContent拷贝一个AVCodecParameters

  1. /**
  2. * Return the next frame of a stream.
  3. * This function returns what is stored in the file, and does not validate
  4. * that what is there are valid frames for the decoder. It will split what is
  5. * stored in the file into frames and return one for each call. It will not
  6. * omit invalid data between valid frames so as to give the decoder the maximum
  7. * information possible for decoding.
  8. *
  9. * If pkt->buf is NULL, then the packet is valid until the next
  10. * av_read_frame() or until avformat_close_input(). Otherwise the packet
  11. * is valid indefinitely. In both cases the packet must be freed with
  12. * av_packet_unref when it is no longer needed. For video, the packet contains
  13. * exactly one frame. For audio, it contains an integer number of frames if each
  14. * frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames
  15. * have a variable size (e.g. MPEG audio), then it contains one frame.
  16. *
  17. * pkt->pts, pkt->dts and pkt->duration are always set to correct
  18. * values in AVStream.time_base units (and guessed if the format cannot
  19. * provide them). pkt->pts can be AV_NOPTS_VALUE if the video format
  20. * has B-frames, so it is better to rely on pkt->dts if you do not
  21. * decompress the payload.
  22. *
  23. * @return 0 if OK, < 0 on error or end of file
  24. */
  25. int av_read_frame(AVFormatContext *s, AVPacket *pkt);

返回下一帧的流

来自为知笔记(Wiz)

时间: 2024-10-21 05:45:09

FFMPEG解码学习笔记(一)的相关文章

FFmpeg编程学习笔记一

FFmpeg编程学习笔记一 1.为了学习ffmpeg编程需要单步调试,参照网上的教程用VS2013编译一次成功,之后随便写了个重采样音轨小程序,也就是把一个5.1声道的AC3文件分解成6个WAV文件的简单功能. 2.编译成功执行也正常,但速度奇慢,比同类软件eac3to慢了约5倍. 3.OK上网搜搜咋回事,一天,二天过去了无果. 4.无奈用VS2013的性能与诊断,分析出最占用时间的函数调用具然是:swr_convert参数里的lrintf() lrint() llrint() llrintf(

【视频编解码&#183;学习笔记】8. 熵编码算法:基本算法列举 &amp; 指数哥伦布编码

一.H.264中的熵编码基本方法: 熵编码具有消除数据之间统计冗余的功能,在编码端作为最后一道工序,将语法元素写入输出码流 熵解码作为解码过程的第一步,将码流解析出语法元素供后续步骤重建图像使用 在H.264的标准协议中,不同的语法元素指定了不同的熵编码方法.在协议文档中共指定了10种语法元素的描述符,这些描述符表达了码流解析为语法元素值的方法,其中包含了H.264标准所支持的所有熵编码方法: 语法元素描述符 编码方法 b(8) 8位二进制比特位串,用于描述rbsp_byte() f(n) n位

【视频编解码&#183;学习笔记】11. 提取SPS信息程序

一.准备工作: 回到之前SimpleH264Analyzer程序,找到SPS信息,并对其做解析 调整项目目录结构: 修改Global.h文件中代码,添加新数据类型UINT16,之前编写的工程中,UINT8和UINT32都为小写表示,为了更符合编程规范,将其改为全大写(可使用ctrl+H在整个解决方案内进行替换). typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; 之后编

【视频编解码&#183;学习笔记】6. H.264码流分析工程创建

一.准备工作: 新建一个VS工程SimpleH264Analyzer, 修改工程属性参数-> 输出目录:$(SolutionDir)bin\$(Configuration)\,工作目录:$(SolutionDir)bin\$(Configuration)\ 编译一下工程,工程目录下会生成bin文件夹,其中的debug文件夹中有刚才编译生成的exe文件.将一个.264视频文件拷贝到这个文件夹中(本次使用的仍是学习笔记3中生成的.264文件). 将这个文件作为输入参数传到工程中:属性 -> 调试

FFmpeg编程学习笔记二:音频重采样

ffmpeg实现音频重采样的核心函数swr_convert功能非常强大,可是ffmpeg文档对它的注释太过简单,在应用中往往会出这样那样的问题,其实在读取数据->重采样->编码数据的循环中在第一次执行swr_convert后还应用swr_convert再作个缓存检测看看是否还有数据,如果有就要把它写到FIFO中去,留在下次再使用,这点在转码和由低向高转换采样率时特别重要. 下面一段简单的代码,摘自我自已写的测试程序. const int frame_size = FFMIN(fifo_size

编解码学习笔记(十):Ogg系列

Ogg是一个自由且开放标准的容器格式,由Xiph.Org 基金会所维护.Ogg格式并不受到软件专利的限制,并设计用于有效率地串流媒体和处理高质量的数字多媒体. Ogg意指一种文件格式,能够纳入各式各样自由和开放源码的编解码器,包括音效.视频. 文字(像字幕)与元数据的处理. Ogg Theora Theora是一个免权利金.开放格式的有损影像压缩技术,由Xiph.Org 基金会开发,该基金会还开发了著名的声音编码技术Vorbis, 以及多媒体容器档案Ogg.Theora 是由 On2 Techn

【视频编解码&#183;学习笔记】3. H.264视频编解码工程JM的下载与编解码

一.下载JM工程: JM是H.264标准制定团队所认可的官方参考软件.网址如下 http://iphome.hhi.de/suehring/tml/ 从页面中可找到相应的工程源码,本次选择JM 8.6版本,此版本为经典版本: http://iphome.hhi.de/suehring/tml/download/old_jm/ 二.配置编码环境: 下载后打开工程目录中tml.sln文件,VS中会有三个工程,其中rtpdump没用,删掉.另外两个ldecod和lencod分别为解码和编码工程. 首先

【视频编解码&#183;学习笔记】5. NAL Unit 结构分析

在上一节中通过一个小程序,可以提取NAL Unit所包含的的字节数据.H.264码流中的每一个NAL Unit的作用并不是相同的,而是根据不同的类型起不同的作用.下面将对NAL Unit中的数据进行解析. 一.NAL Unit结构 一个NAL Unit都是由一个NAL Header和一个NAL Body组成.对于基本版本的H.264标准(不考虑SVC和MVC扩展),一个NAL Header的长度固定为1,即8bit.这8bit的含义分别为: forbidden_zero_bit:每一个NAL H

【视频编解码&#183;学习笔记】4. H.264的码流封装格式 &amp; 提取NAL有效数据

一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通用的格式适应不同的传输封装类型. 通常NAL Unit的传输格式分两大类:字节流格式和RTP包格式 字节流格式: 大部分编码器的默认输出格式 每个NAL Unit以规定格式的起始码分割 起始码:0x 00 00 00 01 或 0x 00 00 01 RTP数据包格式: NAL Unit按照RTP数