一生一世学坛

 找回密码
 立即注册
搜索
查看: 4695|回复: 0
打印 上一主题 下一主题

FFMPEG中时间戳的知识

[复制链接]

334

主题

385

帖子

6891

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
6891
跳转到指定楼层
楼主
发表于 2019-9-23 14:24:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
FFMPEG中时间戳的知识
转自:
https://blog.csdn.net/topsluo/article/details/76239136
/*
*Date:2017-07-28
*Author:TopsLuo
*Function:掌握ffmpeg中时间戳的知识点。并根据实际的时间来生成ffmpeg内部不同时间基的时间戳

*知识点1:av_q2d(AVRational a)函数
    av_q2d(AVRational);该函数负责把AVRational结构转换成double,通过这个函数可以计算出某一帧在视频中的时间位置
    timestamp(秒) = pts * av_q2d(st->time_base);
    计算视频长度的方法:
    time(秒) = st->duration * av_q2d(st->time_base);

*知识点2:av_rescale_q(int64_t a, AVRational bq, AVRational cq)函数
    这个函数的作用是计算a*bq / cq来把时间戳从一个时间基调整到另外一个时间基。在进行时间基转换的时候,应该首先这个函数,因为它可以避免溢出的情况发生

*知识点3:ffmpeg内部的时间与标准的时间转换方法:
    timestamp(ffmpeg内部的时间戳) = AV_TIME_BASE * time(秒)
    time(秒) = AV_TIME_BASE_Q * timestamp(ffmpeg内部的时间戳)

*知识点4:ts格式文件中3600间隔是什么意思?
    它是25fps帧率的ts媒体文件,每个视频帧的间隔时间。
    ts文件的封装时基是90kHz为单位,timebase是AVRational{1,90000},简单的理解就是把1秒分成了90000等分,拿25帧率ts文件来分析
    按标准时间来计算每帧的间隔:
    公式为:1 / 25 = 0.04(秒) = 40毫秒
    按ffmpeg中的1秒(即90000)来计算每帧的间隔(单位好像没有明确的定义,暂且使用ffmpeg吧):
    90000 / 25 = 3600(ffmpeg)
    用时间转换公式可能会更清楚一些:
    1(s) = 90000(ffmpeg)
    40(ms) = 3600(ffmpeg)

*知识点5:不同的时间基
    现实中不同的封装格式,timebase是不一样的。另外,整个转码过程,不同的数据状态对应的时间基也不一致。还是拿mpegts封装格式25fps来
    说(只说视频,音频大致一样,但也略有不同)。非压缩时候的数据(即YUV或者其它),在ffmpeg中对应的结构体为AVFrame,它的时间基为AVRational{1,25}。
    压缩后的数据(对应的结构体为AVPacket)对应的时间基为AVRational{1,90000}
*/

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/time.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int i = 0;
    av_register_all();
    int64_t start = av_gettime_relative();
    AVRational tb = (AVRational){1,90000};
    for(i=1; i < 100; i++)
    {
    #if 1
        usleep(1000*40);//等待40毫秒
        int64_t time = av_gettime_relative();//单位:AV_TIME_BASE,即ffmpeg内部使用的时间单位
        int64_t timestamp = time - start;
    #else
        int64_t timestamp = i*0.04 * AV_TIME_BASE;//把实际的时间单位转换成AV_TIME_BASE
    #endif

        //时间基转换
        int64_t pts = av_rescale_q(timestamp, AV_TIME_BASE_Q, tb);
        printf("timestamp:%"PRId64" pts:%"PRId64"\n", timestamp, pts);
    }
    return 0;
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|分享学习  

GMT+8, 2024-6-13 19:12 , Processed in 0.042942 second(s), 6 queries , File On.

声明:本站严禁任何人以任何形式发表违法言论!

本站内容由网友原创或转载,如果侵犯了您的合法权益,请及时联系处理!© 2017 zamxqun@163.com

皖公网安备 34010402700634号

皖ICP备17017002号-1

快速回复 返回顶部 返回列表