【FFMEPG】时间框架

1 转换函数

av_rescale_q(a,b,c)作用相当于执行a*b/c,通过设置b,c的值,可以很方便的实现time_base之间转换。

2 FFPLAY 输出的pts时间

static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
    int ret = AVERROR(EAGAIN);

    for (;;) {
        AVPacket pkt;

        if (d->queue->serial == d->pkt_serial) {
            do {
                if (d->queue->abort_request)
                    return -1;

                switch (d->avctx->codec_type) {
                    case AVMEDIA_TYPE_VIDEO:
                        ret = avcodec_receive_frame(d->avctx, frame);
                        if (ret >= 0) {
                            if (decoder_reorder_pts == -1) {
                                frame->pts = frame->best_effort_timestamp;
                            } else if (!decoder_reorder_pts) {
                                frame->pts = frame->pkt_dts;
                            }
                        }
                        break;
                    case AVMEDIA_TYPE_AUDIO:
                        ret = avcodec_receive_frame(d->avctx, frame);
                        if (ret >= 0) {
                            AVRational tb = (AVRational){1, frame->sample_rate};
                            if (frame->pts != AV_NOPTS_VALUE)
                                frame->pts = **av_rescale_q**(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb);
                            else if (d->next_pts != AV_NOPTS_VALUE)
                                frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);
                            if (frame->pts != AV_NOPTS_VALUE) {
                                d->next_pts = frame->pts + frame->nb_samples;
                                d->next_pts_tb = tb;
                            }
                        }
                        break;
                }

三 duration

一 AVFormatContext

duration:整个码流的时⻓,获取正常时⻓的时候要除以AV_TIME_BASE,得到的结果单位是秒

//获取文件时长 s 为单位
AVFormatContext *pFormatCtx = NULL;
if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
    // Failed to open file or unknown error occurred
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
    // Failed to retrieve stream information
}
int duration = pFormatCtx->duration / AV_TIME_BASE;

四 Audio Frame PTS的获取

ffplay有3次对于Audio的pts进⾏转换
第⼀次 将其由AVStrean->time_base转换为(1/采样率)
frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);
第⼆次 将其由(1/采样率)转换为秒
af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
第三次 根据实际拷⻉给sdl的数据⻓度做调整
audio_pts = is->audio_clock -
(double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec;

五 如何获取时间基

AVStream.time_base是AVPacket中pts和dts的时间单位,输⼊流与输出流中time_base按如下⽅式确
定:
对于输⼊流:打开输⼊⽂件后,调⽤avformat_find_stream_info()可获取到每个流中的time_base
对于输出流:打开输出⽂件后,调⽤avformat_write_header()可根据输出⽂件封装格式确定每个流的
time_base并写⼊输出⽂件中

你可能感兴趣的:(ffmpeg,媒体)