FFMPEG:av_rescale_q - time_base difference
FFMPEG:av_rescale_q - time_base difference
我想一劳永逸地知道,时间碱核心和重新缩放在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);
但是,在这个问题中,一个人问我类似的问题,他给出了更多的例子,每个人都以不同的方式做。与答案相反,答案说所有这些方法都很好,对我而言,只有以下方法有效:
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
在我的应用程序中,我在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};
我看到的第一个奇怪的事情发生在我为输出格式编写标题上下文之后:
AVDictionary *opts = nullptr;
int ret = avformat_write_header(mOutputFormatContext, &opts);
av_dict_free(&opts);
之后,video_st->time_base
填充了:
num = 1;
den = 15360
我不明白为什么。
我希望有人请让我exaplain that.next,在写作框架之前,我计算数据包的PT。在我的情况下,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);
我不明白,为什么编解码器和流具有不同的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;
乘以1000的乘法是WebM所需的,因为该容器中以毫秒为单位显示了时间戳记。那么,为什么在编码MP4流的情况下,必须重新缩放的时间_base有差异?
ffmpeg的这种行为也使我感到困惑。此处用户对此进行了一些讨论-http://ffmpeg.org/pipermail/libav-user/2018-january/010843.html。但是,那里的决议只是处理15360 Time_base而不是对其施加控制。
从该论坛主题中的海报指出的来源(https://github.com/ffmpeg/ffmpeg/ffmpeg/blob/master/master/libavformat/movenc.c.c.c.据我所知,看起来很容易避免。看来您的选择是让time_base更改或选择某些东西= 10000,然后不会更改。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 构造函数采用 Base&不被调用
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 将sharet_ptr<Derived>转换为shared_ptr<Base>
- 将 BASE 派生类存储在同一容器中
- 避免矢量中的对象切片<Base><shared_ptr>
- 从 std<Derived>::shared_ptr 的向量返回 std::shared_ptr<Base>
- 为什么我会收到"Run-Time Check Failure #2 - Stack around the variable 'pr' was corrupted"错误?
- 如何从unique_ptr返回unique_ptr的引用<Derived><Base>?
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- 如何将unique_ptr<derived>*转换为<base>unique_ptr*?
- <Base> <Derived> 具有相同原始指针共享引用的 shared_ptr 和 shared_ptr 实例是否计数?
- 解析某些行的文本和输出"time of appearance"
- 从 Base 引用对象调用派生类的成员
- 两个成员,在Base中默认初始化,可能在Derived中非默认初始化
- 从"<Base>std::unique_ptr"创建"ClassType<std::unique_ptr>"时出现编译错误<Derived>
- C++ - 打印派生类对象的矢量<base*> 元素
- 为什么在此示例中从unique_ptr自动向上转换<derived>到unique_ptr<base>失败?
- 返回time()库函数的数据类型
- 如何在派生类中不显式调用base::func()的情况下从基类执行虚拟函数