[FFmpeg-devel] [PATCHv2 1/4] avformat/mpegtsenc: fix incorrect PCR selection with multiple programs

Marton Balint cus at passwd.hu
Sun Aug 4 23:25:00 EEST 2019



On Sun, 4 Aug 2019, Andreas Håkon wrote:

> Hi Marton,
>
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
>
>> v2: a video is stream is preferred if there are no programs, just like before
>> the patch.
>
> Thank you for your effort!
> However, something is wrong with this patch regarding PCR intervals.
>
> First, try this example (using the file shared by Michael
> https://trac.ffmpeg.org/raw-attachment/ticket/3714/FFmpeg%20Sample_cut.ts ):
>
>
> % ffmpeg -loglevel info -y -i Sample_cut.ts \
> -map '0:v:0' -c:v:0 copy \
> -map '0:v:0' -c:v:1 copy \
> -map '0:a:0' -c:a:0 copy \
> -pat_period 1 \
> -program st=0,1,2 \
> -program st=0,2 \
> -program st=1,2 \
> -program st=3 \
> -sdt_period 1 \
> this_was_less_than_2560000-marton.ts

This command line does not seem correct, there is no stream 3, also in 
order to specify multiple streams per program you have to use this syntax: 
-program st=0:st=2.

>
> Then you get:
> [mpegts @ 0x3046880] service 1 using PCR in pid=256
> [mpegts @ 0x3046880] service 2 using PCR in pid=256
> [mpegts @ 0x3046880] service 3 using PCR in pid=257
> [mpegts @ 0x3046880] service 4 using PCR in pid=258
>
> Until here all seems correct.
>
> However, if you analyze the PCR intervals:
> - 256: PCR_count: 0x3 (3) => repetition rate: 0,299 seconds
> - 257: PCR_count: 0x3 (3) => repetition rate: 0,305 seconds
> - 258: PCR_count: 0x4 (4) => repetition rate: 0,139 seconds
>
> (You can check it with the DVB Inspector tool or any other)
>
> And regular repetition rate are 0,450 seconds (with ffmpeg).

450m PCR seems wrong. ISO/IEC13818-1 specifies 
an interval of 100 ms, while DVB recommends 40 ms PCR-s.

What was the PCR interval before the patch? 450 ms seems like the 
keyframe interval of your video, because for keyframes you always get 
a PCR with the current code.

Keep in mind that according to this
https://ffmpeg.org/pipermail/ffmpeg-devel/2016-March/192040.html
PCR in VBR streams never worked correctly.

CBR with multiple programs was also problematic, because instead of 
counting all packets the counter only counted the packets of a service.

The way I see it PCR generation needs a serious rework, I will post a 
patch for that, you will have to apply it on top of this series.

>
> So...
>
>> @@ -57,8 +57,6 @@ typedef struct MpegTSService {
>> uint8_t name[256];
>> uint8_t provider_name[256];
>> int pcr_pid;
>>
>> -   int pcr_packet_count;
>> -   int pcr_packet_period;
>>     AVProgram *program;
>>     } MpegTSService;
>
> Why you remove the "pcr_packet_period" from services?
> I know that the value can be the same for all services inside the
> same TS, but the PCR interval is per service, and not per TS.

It is per PID now instead of per service.

>
>
>> @@ -1015,8 +1032,7 @@ static int mpegts_init(AVFormatContext *s)
>> else
>> av_log(s, AV_LOG_VERBOSE, "muxrate %d, ", ts->mux_rate);
>>      av_log(s, AV_LOG_VERBOSE,
>> -             "pcr every %d pkts, sdt every %d, pat/pmt every %d pkts\\n",
>> -             service->pcr_packet_period,
>> +             "sdt every %d, pat/pmt every %d pkts\\n",
>>               ts->sdt_packet_period, ts->pat_packet_period);
>
> The information about the PCR interval is a must have. Please, don't remove it!

It is written out in select_pcr_streams.

>
>
>> @@ -1198,12 +1214,12 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
>> force_pat = 0;
>> write_pcr = 0;
>> -          if (ts_st->pid == ts_st->service->pcr_pid) {
>> +          if (ts_st->pcr_packet_period) {
>>                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;
>> +                  ts_st->pcr_packet_count++;
>> +              if (ts_st->pcr_packet_count >=
>> +                  ts_st->pcr_packet_period) {
>> +                  ts_st->pcr_packet_count = 0;
>>                }
>>            }
>
> In this way, with multiple services (the reason for this patch) you're generating a
> Transport Stream with PCR streams sharing the interval period. That's a new serious BUG!

No, ts_st is different for each stream (each PID).

>
> For each service it's one PCR. And the interval of each PCR for one stream is
> computed from the last PCR of the same stream. It can't be calculated from the last
> PCR of any other stream.

ts_st is different for each stream, it is not common.

>
> Please, fix this bug before merging this patch.
>
>
>> @@ -1236,7 +1252,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
>> }
>> if (key && is_start && pts != AV_NOPTS_VALUE) {
>> // set Random Access for key frames
>>
>> -              if (ts_st->pid == ts_st->service->pcr_pid)
>> +              if (ts_st->pcr_packet_period)
>>                    write_pcr = 1;
>>                set_af_flag(buf, 0x40);
>>                q = get_ts_payload_start(buf);
>
> Just the same problem.

Regards,
Marton


More information about the ffmpeg-devel mailing list