[FFMPEG]MUXER:MPEGTS

代码文件:libavformat/mpegtsenc.c

##1.PAT/PMT插入间隔

1.1.插入间隔实质是根据ts->pat_period*90000.0) ,sdt_packet_period和 force_pat共同决定的;

static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts)
{
    ......
    if (++ts->pat_packet_count == ts->pat_packet_period ||
        (dts != AV_NOPTS_VALUE && ts->last_pat_ts == AV_NOPTS_VALUE) ||
        (dts != AV_NOPTS_VALUE && dts - ts->last_pat_ts >= ts->pat_period*90000.0) ||
        force_pat) {
        ts->pat_packet_count = 0;
        if (dts != AV_NOPTS_VALUE)
            ts->last_pat_ts = FFMAX(dts, ts->last_pat_ts);
        mpegts_write_pat(s);
        for (i = 0; i < ts->nb_services; i++)
            mpegts_write_pmt(s, ts->services[i]);
    }
    ......
}

1.2.force_pat的计算,实质是可以通过强制给flags设置MPEGTS_FLAG_PAT_PMT_AT_FRAMES即可。

    ......
    int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
    ......
    if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        force_pat = 1;
    }
    ......

1.3.sdt_packet_period的计算,我们是无法更改的

    if (ts->mux_rate > 1) {
    ......
        ts->pat_packet_period      = (int64_t)ts->mux_rate * PAT_RETRANS_TIME /
                                     (TS_PACKET_SIZE * 8 * 1000);
    ......                         
    } else {
    ......
        /* Arbitrary values, PAT/PMT will also be written on video key frames */
        ts->sdt_packet_period = 200;
        ts->pat_packet_period = 40;
    ......
        if (ts->pat_period < INT_MAX/2) {
            ts->pat_packet_period = INT_MAX;
        }
        if (ts->sdt_period < INT_MAX/2) {
            ts->sdt_packet_period = INT_MAX;
        }
    ......
    }

1.4.总结
<1>pat/pmt插入时间间隔根据mux_rate的值不同,计算方式有区别:当mux_rate大于1时,可根据设定的间隔发送pat/pmt表;当mux_rate不大于1时,则发送间隔为固定值;
<2>若希望按照设定好的间隔发送PAT和PMT表,首先需要设置"mux_rate"的值,其次需要配置"mpegts_flags"选项的"pat_pmt_at_frames"属性OPT_SET(ofmt_ctx->priv_data,“mpegts_flags”,“pat_pmt_at_frames”);
<3>对于25帧视频默认的信息: muxrate VBR, pcr every 2 pkts, sdt every 200, pat/pmt every 40 pkts
<4>值得注意的是:当我们将pat_period和sdt_period设置过小时,ts->pat_packet_period和ts->sdt_packet_period将会新被设定为INT_MAX;

##2.PCR
###2.1.PCR插入间隔

    if (ts->mux_rate > 1) {
        service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
                                     (TS_PACKET_SIZE * 8 * 1000);
    ......
    } else {
    ......
        if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0);
            if (!frame_size) {
                av_log(s, AV_LOG_WARNING, "frame size not set\n");
                service->pcr_packet_period =
                    pcr_st->codecpar->sample_rate / (10 * 512);
            } else {
                service->pcr_packet_period =
                    pcr_st->codecpar->sample_rate / (10 * frame_size);
            }
        } else {
            // max delta PCR 0.1s
            // TODO: should be avg_frame_rate
            service->pcr_packet_period =
                ts_st->user_tb.den / (10 * ts_st->user_tb.num);
        }
        if (!service->pcr_packet_period)
            service->pcr_packet_period = 1;
    }

    ......
        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;
                write_pcr = 1;
            }
        }

###2.2.PCR计算
pcr的计算在ffmpeg中有两个方法,代码如下:

            if (ts->mux_rate > 1)
                pcr = get_pcr(ts, s->pb);
            else
                pcr = (dts - delay) * 300;

2.2.1.使用muxrate(即插空包)

    if (ts->mux_rate > 1) {
        if (ts->copyts < 1)
            ts->first_pcr = av_rescale(s->max_delay, PCR_TIME_BASE, AV_TIME_BASE);
    }
    
static int64_t get_pcr(const MpegTSWrite *ts, AVIOContext *pb)
{
    return av_rescale(avio_tell(pb) + 11, 8 * PCR_TIME_BASE, ts->mux_rate) +
           ts->first_pcr;
}

展开为:(avio_tell(pb) + 11)* (8 * PCR_TIME_BASE)/ts->mux_rate + ts->first_pcr

2.2.2.不插空包(即VBR)

pcr = (dts - delay) * 300 (时间基准27Mhz)

2.3.总结
<1>PCR的值和插入时间间隔根据mux_rate的值不同,计算方式都有区别;
<2>当我们设定了mux_rate大于1时,根据我们设定的pcr间隔(默认30ms)进行发送,pcr值为(avio_tell(pb) + 11)* (8 * PCR_TIME_BASE)/ts->mux_rate + ts->first_pcr
<3>当我们设定了mux_rate不大于1时,pcr计算是根据ts_st->user_tb.den / (10 * ts_st->user_tb.num)来计算的。对于25帧视频来说pcr_packet_period值为2,pcr计算方式为(dts - delay) * 300

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷咪哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值