[FFMPEG]MUXER:MPEGTS

news/2024/7/10 21:01:42 标签: pcr, ffmpeg, mpegts, sdt, pat
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">path>

代码文件: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


http://www.niftyadmin.cn/n/1336041.html

相关文章

2018年天猫双11交易额重要时刻表

2018年天猫双11交易额重要时刻表&#xff1a;21秒&#xff0c;交易额破10亿&#xff0c;比去年快了7秒。2分05秒&#xff0c;破100亿。比去年用时缩短了将近1分钟&#xff0c;比2016年短了近5分钟。4分20秒&#xff0c;破191亿&#xff0c;比去年缩短了将近1分半。超越2012年双…

[FFMPEG]代码分析:ffmpeg.c

1.前沿 接触ffmpeg2年多&#xff0c;系统使用大概半年左右。ffmpeg命令行方式作为“本地文件”处理足够&#xff0c;但要更加精准的控制还是需要借用SDK的方式&#xff0c;好在ffmpeg的example中提供了大量的简单例子。好了废话不多说&#xff0c;开始干活。 ffmpeg版本3.22.主…

下拉组合框控件演示

下拉组合框控件演示&#xff1a; 关键代码&#xff1a; combobox{cls"combobox";left19;top58;right446;bottom84;edge1;items{};mode"dropdown";z5};//下拉组合框列表的选项集合 winform.combobox.items {选项1;选项2;选项3;选项4;选项5 } 完整代码&#…

ubuntu查看支持的字体库

##1.背景 sugaomsos:~/mscore/src$ uname -a Linux msos 4.4.0-75-generic #96-Ubuntu SMP Thu Apr 20 09:56:33 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux##2.命令 fc-list 查看所有的字体 fc-list :langzh 查看所有的中文字体 ##3.增加字体 默认字体文件放在/usr/share/fon…

重构与重写

在内部看到的评论&#xff0c; 觉得很有道理&#xff0c;记录下&#xff1a; 重构(名词)&#xff1a;对软件内部结构的一种调整&#xff0c;目的是在不改变软件可观察行为的前提下&#xff0c;提高其可理解下&#xff0c;降低其修改成本。 重构(动词)&#xff1a;使用一系列重构…

都8210年了,还不知道docker就过分了

软件开发最大的麻烦事之一&#xff0c;就是环境配置。特别是万恶的windows,经常出现一些奇怪的问题。 特别是新人入职&#xff0c;要装一大堆环境&#xff0c;就比如我们团队&#xff0c;后端是Go&#xff0c;要装啥环境我不太清楚。前端的话&#xff0c;需要装php,redis,node,…

[PPPOE]RP-PPPOE脚本分析

默认配置 配置存放目录:/etc/ppp/pppoe.conf ppp-pap密码存放目录:/etc/ppp/pap-secrets ppp-chap密码存放目录:/etc/ppp/chap-secrets PPP防火墙&#xff1a;/etc/ppp/firewall-standalone和/etc/ppp/firewall-masq ppp网卡:文件/var/run/ppp0.pid 1.配置文件 配置文件&…

[PPPOE]RP-PPPOE源码分析

##1.基本 pppoe-connect中实际调用的pppoe命令为&#xff1a; /usr/sbin/pppoe -p /var/run/pppoe_eth1.pid.pppoe -I eth1 -T 80 -U -m 1412编译依赖文件包括&#xff1a;pppoe.c if.c debug.c common.c ppp.c discovery.c ##2.选项 -I if_name 指定拨号网卡&#xff0c;默认…