@@ -614,7 +614,27 @@ static int lavf_seek_frame
614
614
// incorrect synchronization point.
615
615
// https://github.com/FFmpeg/FFmpeg/blob/n4.4/libavformat/mpegts.c#L2898
616
616
if ((flags & AVSEEK_FLAG_BYTE ) && strcmp (s -> iformat -> name , "mpegts" ) == 0 ) {
617
- timestamp += 4 ; // skip the TC header
617
+ // However, not all mpegts files are BD, e.g. TV ts does not have such a 4B
618
+ // TP_extra_header.
619
+ //
620
+ // There is no easy way to differentiate between the two (using file extension
621
+ // will be too fragile.) Fortunately, the top 2-bit of TP_extra_header is
622
+ // the copy permission indication, which all sources seem to set to 0, so
623
+ // the first byte of TP_extra_header should not be 0x47, and we can use
624
+ // this to detect these two cases.
625
+ //
626
+ // We do the offset compensation only when the 1st byte is not 0x47 and the
627
+ // 5th byte is 0x47.
628
+ // This test should not affect the performance much as av_seek_frame is going
629
+ // to read at least 188 bytes from position timestamp anyway.
630
+ unsigned char buf [5 ];
631
+ const char sync_byte = 0x47 ;
632
+ avio_seek (s -> pb , timestamp , SEEK_SET );
633
+ avio_read (s -> pb , buf , sizeof buf );
634
+ if (buf [0 ] != sync_byte && buf [4 ] == sync_byte )
635
+ timestamp += 4 ; // skip the TC header
636
+ // There is no need to restore file pointer as we have set AVSEEK_FLAG_BYTE and
637
+ // so we are going to seek to timestamp anyway.
618
638
}
619
639
return av_seek_frame (s , stream_index , timestamp , flags );
620
640
}
0 commit comments