Mic*_* IV 6 c++ video ffmpeg libav
我想一劳永逸地知道,在FFMPEG中,时基收费和重新缩放是如何工作的.在回答这个问题之前,我做了一些研究,发现了许多有争议的答案,这使得它更加令人困惑.因此,根据官方的FFMPEG 示例,我们必须这样做
从编解码器到流时基的rescale输出数据包时间戳值
用这样的东西:
pkt->pts = av_rescale_q_rnd(pkt->pts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt->dts = av_rescale_q_rnd(pkt->dts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt->duration = av_rescale_q(pkt->duration, *time_base, st->time_base);
Run Code Online (Sandbox Code Playgroud)
但是在这个问题中,一个人向我提出类似的问题,他给出了更多的例子,他们每个人都做了不同的事情.与所有这些方式都很好的答案相反,对我来说,只有以下方法有效:
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
Run Code Online (Sandbox Code Playgroud)
在我的应用程序中,我在FFMPEG API外以60 fps生成视频数据包(h264),然后将它们写入mp4容器.
我明确地说:
video_st->time_base = {1,60};
video_st->r_frame_rate = {60,1};
video_st->codec->time_base = {1 ,60};
Run Code Online (Sandbox Code Playgroud)
我看到的第一个奇怪的事情发生在我为输出格式上下文写入标题之后:
AVDictionary *opts = nullptr;
int ret = avformat_write_header(mOutputFormatContext, &opts);
av_dict_free(&opts);
Run Code Online (Sandbox Code Playgroud)
之后,video_st->time_base填充:
num = 1;
den = 15360
Run Code Online (Sandbox Code Playgroud)
我不明白为什么.
我想要有人请我说.接下来,在写帧之前,我计算了数据包的PTS.在我的情况下PTS = DTS,因为我根本不使用B帧.
我必须这样做:
const int64_t duration = av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
totalPTS += duration; //totalPTS is global variable
packet->pts = totalPTS ;
packet->dts = totalPTS ;
av_write_frame(mOutputFormatContext, mpacket);
Run Code Online (Sandbox Code Playgroud)
我不明白,为什么编解码器和流具有不同的time_base值,即使我明确地将它们设置为相同.因为我看到所有av_rescale_q用于计算持续时间的例子,我真的希望有人来解释这一点.
另外,作为比较,为了实验,我决定尝试为WEBM容器编写流.所以我根本不使用libav输出流.我只抓取用于编码MP4的相同数据包并将其手动写入EBML流.在这种情况下,我计算这样的持续时间:
const int64_t duration =
( video_st->codec->time_base.num / video_st->codec->time_base.den) * 1000;
Run Code Online (Sandbox Code Playgroud)
WEBM需要乘以1000,因为时间戳以毫秒为单位显示在该容器中.这是有效的.那么为什么在MP4流编码的情况下,time_base有所不同,必须重新调整?
ffmpeg 的这种行为也让我感到困惑。用户在这里进行了一些讨论 - http://ffmpeg.org/pipermail/libav-user/2018-January/010843.html。但解决方案是只处理 15360 time_base,而不是对其施加控制。
从该论坛主题中的发帖者指出的来源(https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/movenc.c,搜索“*= 2”)来看,它看起来并不容易据我所知是可以避免的。看来你的选择是让 time_base 改变,或者选择 >= 10000 的东西,然后它就不会改变。
| 归档时间: |
|
| 查看次数: |
1715 次 |
| 最近记录: |