FFMPEG PCR PID修改以及插入间隔计算

本文详细介绍了在使用FFMPEG输出MPEGTS格式时,遇到视频和PCR的PID相同的问题,并提供了解决方案。通过修改源码,实现自定义PCR写入函数,确保PID的正确性和视频流与PCR流的独立性。

用FFMPEG输出MPEGTS格式时,发现视频和PCR的PID总是一样。

查看源码如下:

 

  /* <strong>update PCR pid by using the first video stream</strong> */
        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
            service->pcr_pid == 0x1fff) {
            service->pcr_pid = ts_st->pid;
            pcr_st           = st;
        }

<strong>/* if no video stream, use the first stream as PCR */</strong>
    if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
        pcr_st           = s->streams[0];
        ts_st            = pcr_st->priv_data;
        service->pcr_pid = ts_st->pid;
    } else

也就是说PCR PID总是会和VIDEO PID一样。

解决办法:修改源码,在现在源码写PCR的时候,替换成自己的PCR写入函数。


-------------------------------- 华丽的分割线 --------------------------------------

关于PCR插入间隔的计算:

由复用总码率,计算出PCR需要间隔多少包插入一次

#define <strong>PCR_RETRANS_TIME </strong>20

 { "pcr_period", "PCR retransmission time",
      offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,
      { .i64 = PCR_RETRANS_TIME }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },

  if (ts->mux_rate > 1) {
        service-><strong>pcr_packet_period</strong> = (ts->mux_rate * ts->pcr_period) /
                                     (TS_PACKET_SIZE * 8 * 1000);
        ts->sdt_packet_period      = (ts->mux_rate * SDT_RETRANS_TIME) /
                                     (TS_PACKET_SIZE * 8 * 1000);
        ts->pat_packet_period      = (ts->mux_rate * PAT_RETRANS_TIME) /
                                     (TS_PACKET_SIZE * 8 * 1000);

 // output a PCR as soon as possible
    service-><strong>pcr_packet_count</strong> = service-><strong>pcr_packet_period;</strong>

在写PES时,根据这个值来写入PES:
 <strong>write_pcr = 0;</strong>
        if (ts_st->pid == ts_st->service->pcr_pid) {
            if (ts->mux_rate > 1 || is_start) // VBR pcr period is based on frames
                ts_st->service->pcr_packet_count++;
            if (ts_st->service->pcr_packet_count >=
                ts_st->service->pcr_packet_period) {
                ts_st->service->pcr_packet_count = 0;
               <strong> write_pcr = 1;</strong>
            }
        }


。。。 。。。
 if (<strong>write_pcr</strong>) {
            set_af_flag(buf, 0x10);
            q = get_ts_payload_start(buf);
            // add 11, pcr references the last byte of program clock reference base
            if (ts->mux_rate > 1)
                pcr = get_pcr(ts, s->pb);
            else
                pcr = (dts - delay) * 300;
            if (dts != AV_NOPTS_VALUE && dts < pcr / 300)
                av_log(s, AV_LOG_WARNING, "dts < pcr, TS is invalid\n");
            extend_af(buf,<strong> write_pcr_bits(q, pcr)</strong>);
            q = get_ts_payload_start(buf);
        }



<think>嗯,用户想解决FFmpegPCR间隔和精度的错误。首先,我需要回忆一下PCR在MPEG-TS中的作用。PCR是节目时钟参考,用来同步解码器的时钟,确保音视频同步。如果间隔设置不正确或者精度不够,可能会导致播放卡顿或不同步的问题。用户提到的错误可能与PCR的生成间隔有关。根据引用[3],FFmpeg中有个参数pcr_period,默认是20毫秒。这个值可能需要调整,比如设置更小的时间间隔以提高精度,或者更大的间隔以适应某些设备的要求。比如,有些设备可能需要PCR至少每100毫秒出现一次,这时候就需要调整pcr_period为100。另外,可能还需要检查封装格式的参数。比如使用mpegts封装时,是否设置了合适的muxrate参数,这会影响PCR计算。如果muxrate不正确,可能导致时间戳间隔不符合标准。 还有,用户可能需要确保输入源的时间戳是准确的。如果输入文件本身的时间戳有问题,FFmpeg处理时可能会继承这些错误,导致PCR不准确。这时候可以用-vsync参数强制按帧率生成时间戳。另外,引用[4]提到版本问题,用户是否使用的是较新的FFmpeg版本?旧版本可能存在bug,升级到最新版可能解决一些问题。比如,某些版本在生成PCR时可能有计算错误,新版本修复了这些bug。还有,用户可能需要检查第三方设备的兼容性。不同的设备对PCR间隔的要求可能不同,需要根据设备文档调整参数。比如,某些设备要求PCR间隔不超过40毫秒,这时候需要设置pcr_period为40。 总结一下,解决方案可能包括调整pcr_period参数,设置正确的muxrate,确保输入时间戳正确,升级FFmpeg版本,以及检查设备兼容性。需要一步步指导用户如何修改这些参数,并验证是否解决了问题。</think>### FFmpegPCR间隔和精度错误的解决方案 PCR(Program Clock Reference)是MPEG-TS流中用于同步解码器时钟的关键参数[^3]。若出现间隔或精度错误,通常需调整封装参数或修复时间戳生成逻辑。以下是具体解决步骤: --- #### 1. **调整PCR生成间隔** 通过`-pcr_period`参数控制PCR的生成频率: ```bash ffmpeg -i input.mp4 -c copy -f mpegts -muxrate 10080000 -pcr_period 40 output.ts ``` - **默认值**:`20`(单位:毫秒)[^3] - **优化建议**:若设备要求严格同步,可缩短间隔(如`10-40ms`),但需平衡文件体积和兼容性。 --- #### 2. **修复时间戳精度** 若输入流时间戳不连续,需强制生成连续PCR: ```bash ffmpeg -i input.mp4 -vsync passthrough -f mpegts -pcr_period 20 output.ts ``` - `-vsync passthrough`:跳过时间戳修复,直接继承输入流时间戳。 - `-use_wallclock_as_timestamps 1`:用系统时钟覆盖错误时间戳。 --- #### 3. **指定muxrate参数** PCR精度与码率计算相关,需显式指定`-muxrate`: ```bash ffmpeg -i input.mp4 -f mpegts -muxrate 10M -pcr_period 30 output.ts ``` - 计算公式:`muxrate = 目标码率 × 1.02`(预留2%冗余)。 --- #### 4. **检查输入流兼容性** 若输入流为HLS/RTMP,需确保封装格式支持PCR: ```bash ffmpeg -probesize 1000000 -analyzeduration 1000000 -i input.m3u8 ... ``` - 增加探测参数避免解析错误。 --- #### 5. **升级FFmpeg版本** 旧版本(如3.0以下)可能存在PCR生成逻辑缺陷[^4]: ```bash sudo apt upgrade ffmpeg # 通过包管理工具升级 ``` --- #### 验证命令 ```bash ffprobe -show_frames output.ts | grep "pcr_" ``` 检查输出中PCR间隔是否符合预期。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值