av_rescale_q、avcodec_get_frame_defaults2、av_set_parameters函数

(1) av_rescale_q用于计算Packet的PTS。av_rescale_q的返回值是一个很大的整数,且每次计算的结果间隔很大。

不同于avcodec_encode_video改变AVCodecContext *avctx的pts(小整数,且间隔小)。

av_rescale_q(a,b,c)是用来把时间戳从一个时基调整到另外一个时基时候用的函数。它基本的动作是计算a*b/c,但是这个函数还是必需的,因为直 接计算会有溢出的情况发生。AV_TIME_BASE_Q是AV_TIME_BASE作为分母后的版本。它们是很不相同的:AV_TIME_BASE * time_in_seconds = avcodec_timestamp而AV_TIME_BASE_Q * avcodec_timestamp = time_in_seconds(注意AV_TIME_BASE_Q实际上是一个AVRational对象,所 你必需使用avcodec中特定的q函数来处理它)。


(2) avcodec_get_frame_defaults2这个函数是在新版本中出现的,与avcodec_get_frame_defaults类似,以下是其老版本函数的用法

必须调用av_set_parameters,否则guess_format("vob",NULL.NULL)时,av_write_header会出错。guess_format("dvd",NULL.NULL)也同样会出错。
if (av_set_parameters(m_pAVFormatContext, NULL) < 0) {
    ReleaseEncoder();
    return E_FAIL;
    }

必须为AVFrame执行初始化。
avcodec_get_frame_defaults(&m_frmRGBPicture);
avcodec_get_frame_defaults(&m_frmYUVpicture);
仅仅为AVFrame执行
avpicture_alloc((AVPicture*)&m_frmYUVpicture,
是不够的。有些重要的成员(pts)没有被初始化。这将导致encode时出错。
获得文件大小,音频大小,视频大小
avcodec_encode_audio()的返回值就是音频数据的大小。
avcodec_encode_video()的返回值就是视频数据的大小。

### FFmpeg 中 `av_rescale_q_rnd` 函数的用法 #### 函数定义 `av_rescale_q_rnd` 是 FFmpeg 提供的一个用于时间基转换的函数,支持指定舍入模式。它的作用是将一个时间戳从一种时间基 (`AVRational`) 转换为另一种时间基,并允许开发者通过参数控制具体的舍入行为。 以下是该函数的原型: ```c int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRound rnd); ``` - 参数解释: - `a`: 需要被转换的时间戳值。 - `bq`: 原始时间基 (source time base),表示输入时间戳所属的时间基。 - `cq`: 目标时间基 (destination time base),表示希望转换到的目标时间基。 - `rnd`: 指定舍入方式,取值范围见下文描述。 #### 可选的舍入模式 `enum AVRound` 定义了几种常见的舍入模式[^4]: - `AV_ROUND_ZERO`: 向零方向舍入。 - `AV_ROUND_INF`: 远离零的方向舍入。 - `AV_ROUND_DOWN`: 向负无穷方向舍入(向下取整)。 - `AV_ROUND_UP`: 向正无穷方向舍入(向上取整)。 - `AV_ROUND_NEAR_INF`: 四舍五入,默认选项。 - `AV_ROUND_PASS_MINMAX`: 特殊用途,保留原始值的最大最小约束。 #### 使用示例 下面是一个完整的 C 示例程序,展示如何使用 `av_rescale_q_rnd` 将时间戳从一个时间基转换到另一个时间基: ```c #include <libavutil/rational.h> #include <stdio.h> void rescale_time_base_example(void) { int64_t timestamp = 1000; // 输入时间戳 AVRational src_tb = {1, 100}; // 原始时间基: 1/100 秒 AVRational dst_tb = {1, 1000}; // 目标时间基: 1/1000 秒 // 使用四舍五入的方式进行转换 int64_t new_timestamp = av_rescale_q_rnd(timestamp, src_tb, dst_tb, AV_ROUND_NEAR_INF); printf("Original Timestamp: %lld\n", (long long)timestamp); printf("Converted Timestamp: %lld\n", (long long)new_timestamp); } int main() { rescale_time_base_example(); return 0; } ``` 上述代码中,假设我们有一个时间戳 `1000` 对应于时间基 `{1, 100}` (即每秒分为 100 份),将其转换为目标时间基 `{1, 1000}` 的形式。最终输出的结果将是经过精确计算并按指定舍入规则调整后的数值。 #### 计算逻辑解析 根据公式 \( \text{new\_value} = \frac{\text{old\_value} \times \text{src\_tb}}{\text{dst\_tb}} \),我们可以手动验证上面的例子: \[ \text{new\_value} = \frac{1000 \cdot 1}{100} \div \frac{1}{1000} = 10000. \] 因此,在此情况下,新的时间戳应该是 `10000`。 --- ### 注意事项 当调用 `av_rescale_q_rnd` 时需要注意以下几点: 1. 时间基数值通常由容器格式或编码器提供,需确保传入的时间基数据有效且一致。 2. 不同场景可能需要不同的舍入策略,例如音频同步可能会倾向于更保守的舍入方法以减少误差累积。 3. 如果不确定具体需求,则推荐默认采用 `AV_ROUND_NEAR_INF` 方式作为通用解决方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值