ffmpeg: time_base分析
来源:互联网 发布:安装vs2015网络 编辑:程序博客网 时间:2024/06/06 03:44
ffmpeg存在多个时间基准(time_base),对应不同的阶段(结构体),每个time_base具体的值不一样,ffmpeg提供函数在各个time_base中进行切换。搞清楚各个time_base的来源,对于阅读ffmpeg的代码很重要。
1、AVStream(libavformat/avformat.h)
typedef struct AVStream { int index; /**< stream index in AVFormatContext */ /** * Format-specific stream ID. * decoding: set by libavformat * encoding: set by the user, replaced by libavformat if left unset */ int id;#if FF_API_LAVF_AVCTX /** * @deprecated use the codecpar struct instead */ attribute_deprecated AVCodecContext *codec;#endif void *priv_data;#if FF_API_LAVF_FRAC /** * @deprecated this field is unused */ attribute_deprecated struct AVFrac pts;#endif /** * This is the fundamental unit of time (in seconds) in terms * of which frame timestamps are represented. * * decoding: set by libavformat * encoding: May be set by the caller before avformat_write_header() to * provide a hint to the muxer about the desired timebase. In * avformat_write_header(), the muxer will overwrite this field * with the timebase that will actually be used for the timestamps * written into the file (which may or may not be related to the * user-provided one, depending on the format). */ AVRational time_base; /** * Decoding: pts of the first frame of the stream in presentation order, in stream time base. * Only set this if you are absolutely 100% sure that the value you set * it to really is the pts of the first frame. * This may be undefined (AV_NOPTS_VALUE). * @note The ASF header does NOT contain a correct start_time the ASF * demuxer must NOT set this. */ int64_t start_time; /** * Decoding: duration of the stream, in stream time base. * If a source file does not specify a duration, but does specify * a bitrate, this value will be estimated from bitrate and file size. * * Encoding: May be set by the caller before avformat_write_header() to * provide a hint to the muxer about the estimated duration. */ int64_t duration; //这个值可以由文件大小和码率来估计 int64_t nb_frames; ///< number of frames in this stream if known or 0 int disposition; /**< AV_DISPOSITION_* bit field */ enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. /** * sample aspect ratio (0 if unknown) * - encoding: Set by user. * - decoding: Set by libavformat. */ AVRational sample_aspect_ratio; AVDictionary *metadata; /** * Average framerate * * - demuxing: May be set by libavformat when creating the stream or in * avformat_find_stream_info(). * - muxing: May be set by the caller before avformat_write_header(). */ AVRational avg_frame_rate;从上面的信息可以看到,AVStream->time_base单位为秒。且这个值在编码时候会在 avformat_write_header()函数中由复用器(muxer)重新估计其值。在设置AVStream->time_base为1/90000。为什么是90000?因为mpeg的pts、dts都是以90kHz来采样的,所以采样间隔为1/90000秒
2、AVCodecContext
typedef struct AVCodecContext { /** * This is the fundamental unit of time (in seconds) in terms * of which frame timestamps are represented. For fixed-fps content, * timebase should be 1/framerate and timestamp increments should be * identically 1. * - encoding: MUST be set by user. * - decoding: Set by libavcodec. */ AVRational time_base;AVCodecContext->time_base单位同样为秒,不过精度没有AVStream->time_base高,大小为1/framerate
总结:
AVStream->time_base比AVCodecContext->time_base精度要高(数值要小),比如AVStream->time_base为1/90000,而AVCodecContext->time_base为1/30(假设frame_rate为30);同样的pts和dts,以AVStream->time_base为单位,数值要比以AVCodecContext->time_base为单位要大。
二、pts、dts
那各个结构下,pts和dts使用哪个time_base来表示呢?
1、AVPacket
typedef struct AVPacket { /** * Presentation timestamp in AVStream->time_base units; the time at which * the decompressed packet will be presented to the user. * Can be AV_NOPTS_VALUE if it is not stored in the file. * pts MUST be larger or equal to dts as presentation cannot happen before * decompression, unless one wants to view hex dumps. Some formats misuse * the terms dts and pts/cts to mean something different. Such timestamps * must be converted to true pts/dts before they are stored in AVPacket. */ int64_t pts; /** * Decompression timestamp in AVStream->time_base units; the time at which * the packet is decompressed. * Can be AV_NOPTS_VALUE if it is not stored in the file. */ int64_t dts;AVPacket下的pts和dts以AVStream->time_base为单位(数值比较大)。这也很容易理解,根据mpeg的协议,压缩后或解压前的数据,pts和dts是90kHz时钟的采样值,时间间隔就是AVStream->time_base。
2、AVFrame
typedef struct AVFrame { /** * Presentation timestamp in time_base units (time when frame should be shown to user). */ int64_t pts; /** * PTS copied from the AVPacket that was decoded to produce this frame. */ int64_t pkt_pts; /** * DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used) * This is also the Presentation time of this AVFrame calculated from * only AVPacket.dts values without pts values. */ int64_t pkt_dts;
注意:
AVFrame里面的pkt_pts和pkt_dts是拷贝自AVPacket,同样以AVStream->time_base为单位;而pts是为输出(显示)准备的,以AVCodecContex->time_base为单位)。
3、InputStream
typedef struct InputStream { int file_index; AVStream *st; AVCodecContext *dec_ctx; int64_t start; /* time when read started */ /* predicted dts of the next packet read for this stream or (when there are * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ int64_t next_dts; int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units)
InputStream下的pts和dts以AV_TIME_BASE为单位(微秒),至于为什么要转化为微妙,可能是为了避免使用浮点数
三、各个time_base之间转换
ffmpeg提供av_rescale_q函数用于time_base之间转换,av_rescale_q(a,b,c)作用相当于执行a*b/c,通过设置b,c的值,可以很方便的实现time_base之间转换。
1、InputStream(AV_TIME_BASE)到AVPacket(AVStream->time_base)
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output){pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);2、AVPacket(AVStream->time_base)到InputStream(AV_TIME_BASE)
static int process_input_packet(InputStream *ist, const AVPacket *pkt){ if (pkt->dts != AV_NOPTS_VALUE) { ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
四、后记:
AVFrame->pts和AVPacket->pts、AVPacket->dts的值,在解码/编码后,会经历短暂的time_base不匹配的情况:
1、解码后
AVFrame->pts和AVPacket->pts、AVPacket->dts的值,在解码/编码后,会经历短暂的time_base不匹配的情况:
1、解码后
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output){ decoded_frame = ist->decoded_frame; pkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); update_benchmark(NULL); ret = avcodec_decode_video2(ist->dec_ctx, decoded_frame, got_output, pkt); best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame); if(best_effort_timestamp != AV_NOPTS_VALUE) ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
解码后,decoded_frame->pts的值使用AVStream->time_base为单位,后在AVFilter里面转换成以AVCodecContext->time_base为单位。 //FIXME
2、编码后
static void do_video_out(AVFormatContext *s, OutputStream *ost, AVFrame *in_picture){ ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet); if (got_packet) { if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); } if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY)) pkt.pts = ost->sync_opts; av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base), av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base)); } frame_size = pkt.size; write_frame(s, &pkt, ost); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } }
编码后,pkt.pts、pkt.dts使用AVCodecContext->time_base为单位,后通过调用"av_packet_rescale_ts"转换为AVStream->time_base为单位。
文章转载地址:http://www.cnitblog.com/luofuchong/archive/2014/11/28/89869.html
0 0
- ffmpeg: time_base分析
- ffmpeg time_base
- ffmpeg time_base
- ffmpeg time_base
- time_base of ffmpeg transcode
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base详解
- ffmpeg time_base介绍
- ffmpeg time_base详解
- FFMPEG Intro - AvCodecContext time_base Set
- time_base
- FFMPEG avformat_write_header changing my stream time_base
- 笔记:FFMPEG 中的几个不同的 time_base
- win7 64 + xbmc-17.1rc1-Krypton + vs2015编译
- 欢迎使用CSDN-markdown编辑器
- 路由器设置端口映射(局域网通过外网访问)
- Django 常用基本命令
- android 浅入浅出看一下事件传递
- ffmpeg: time_base分析
- 循环队列打印杨辉三角
- 系统思考方式
- UIActivityIndicatorView
- PTA 5-19 支票面额
- SharedPreferences
- Linux文件系统命令
- python之禅——import this
- 如何安装Jmeter插件