Opened 8 years ago

Last modified 8 years ago

#5423 new defect

Wrong duration_ts from mpeg-ts file by avformat_find_stream_info()

Reported by: Aleksandr Owned by:
Priority: normal Component: avformat
Version: git-master Keywords: mpegts h264
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:
Function avformat_find_stream_info from libavformat/avformat.h may get wrong duration of the mpeg-ts file sometimes.

For example:
Below you can see different duration_ts of the video stream and the audio stream, but actually it's not so. Duration_ts of the video stream is the same as audio stream, and function avformat_find_stream_info got it wrong.

% C:\Users\slobodeniuk>ffprobe -show_streams e:\data\00000.MTS
ffprobe version N-77782-g42c54d4 Copyright (c) 2007-2016 the FFmpeg developers
  built with gcc 5.2.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-av
isynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enab
le-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --
enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm --enable-l
ibilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enab
le-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --en
able-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --ena
ble-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc
 --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enabl
e-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --
enable-lzma --enable-decklink --enable-zlib
  libavutil      55. 13.100 / 55. 13.100
  libavcodec     57. 22.100 / 57. 22.100
  libavformat    57. 21.101 / 57. 21.101
  libavdevice    57.  0.100 / 57.  0.100
  libavfilter     6. 23.100 /  6. 23.100
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
Input #0, mpegts, from 'e:\data\00000.MTS':
  Duration: 00:00:03.64, start: 1.040000, bitrate: 23995 kb/s
  Program 1
    Stream #0:0[0x1011]: Video: h264 (High) (HDMV / 0x564D4448), yuv420p, 1920x1
080 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x1100]: Audio: pcm_bluray (HDMV / 0x564D4448), 48000 Hz, stereo
, s16, 1536 kb/s
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=High
codec_type=video
codec_time_base=1/50
codec_tag_string=HDMV
codec_tag=0x564d4448
width=1920
height=1080
coded_width=1920
coded_height=1088
has_b_frames=1
sample_aspect_ratio=1:1
display_aspect_ratio=16:9
pix_fmt=yuv420p
level=40
color_range=N/A
color_space=unknown
color_transfer=unknown
color_primaries=unknown
chroma_location=left
timecode=N/A
refs=2
is_avc=false
nal_length_size=0
id=0x1011
r_frame_rate=25/1
avg_frame_rate=25/1
time_base=1/90000
start_pts=100800
start_time=1.120000
duration_ts=316800
duration=3.520000
bit_rate=N/A
max_bit_rate=N/A
bits_per_raw_sample=8
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
[/STREAM]
[STREAM]
index=1
codec_name=pcm_bluray
codec_long_name=PCM signed 16|20|24-bit big-endian for Blu-ray media
profile=unknown
codec_type=audio
codec_time_base=1/48000
codec_tag_string=HDMV
codec_tag=0x564d4448
sample_fmt=s16
sample_rate=48000
channels=2
channel_layout=stereo
bits_per_sample=0
id=0x1100
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/90000
start_pts=93600
start_time=1.040000
duration_ts=327601
duration=3.640011
bit_rate=1536000
max_bit_rate=N/A
bits_per_raw_sample=N/A
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
[/STREAM]

File 00000.mts can be downloaded here:
https://yadi.sk/i/luPXJFEoquMJs

duration_ts=316800 is equivalent to ~89 frames, but the real duration of the video stream is 91 frame.

Why is it happening: (found from the debugging)
1) Function estimate_timings_from_pts() begin reading last packets from some point near the end of the file:
utils.c:2569

offset = filesize - (DURATION_MAX_READ_SIZE << retry);
#define DURATION_MAX_READ_SIZE 250000LL

and gets max pts of the packet for each stream

duration = pkt->pts + pkt->duration;

In case of the file, attached in this report, it got one video packet , and a lot of audio packets. So the max pts of the video stream counted by the last frame in stream order.

2) The real last timestamp (max pts) of some mpeg-4-whatewer stream is the timestamp of the last packet in display order. And this packet may not be the last packet in the stream order because of organization of mpeg stream with open gop.
In case of the atteched file the last frame in display order (with the latest timestamp) is the 90th frame in stream order, but function estimate_timings_from_pts() got only 91th frame, and used it's pts.

Maybe the DURATION_MAX_READ_SIZE should be raised as a variant of the solution (but it doesn't look like a really clean way).

Change History (4)

comment:1 by Aleksandr, 8 years ago

Version: unspecifiedgit-master

comment:2 by Aleksandr, 8 years ago

after raising DURATION_MAX_READ_SIZE to 1 Mb :
#define DURATION_MAX_READ_SIZE ( 1024LL * 1024 )

new duration_ts:
duration_ts=320400

C:\public\ff-new\bin>ffprobe -show_streams e:\data\00000.MTS
ffprobe version 3.0.1 Copyright (c) 2007-2016 the FFmpeg developers
  built with gcc 4.9.1 (GCC)
  configuration: --enable-cross-compile --arch=x86 --target-os=mingw32 --cross-p
refix=i686-w64-mingw32- --enable-shared --enable-memalign-hack --enable-debug --
enable-runtime-cpudetect --enable-libmp3lame --enable-libopenh264 --disable-stri
pping --extra-cflags=-I/home/aleksandr/SDK/lame/win32/include --extra-ldflags='-
L/home/aleksandr/SDK/lame/win32/lib -static' --pkg-config=pkg-config --pkg-confi
g-flags=--static --prefix=/home/aleksandr/SDK/output/w32
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
Input #0, mpegts, from 'e:\data\00000.MTS':
  Duration: 00:00:03.64, start: 1.040000, bitrate: 23995 kb/s
  Program 1
    Stream #0:0[0x1011]: Video: h264 (High) (HDMV / 0x564D4448), yuv420p, 1920x1
080 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x1100]: Audio: pcm_bluray (HDMV / 0x564D4448), 48000 Hz, stereo
, s16, 1536 kb/s
[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
profile=High
codec_type=video
codec_time_base=1/50
codec_tag_string=HDMV
codec_tag=0x564d4448
width=1920
height=1080
coded_width=1920
coded_height=1088
has_b_frames=1
sample_aspect_ratio=1:1
display_aspect_ratio=16:9
pix_fmt=yuv420p
level=40
color_range=N/A
color_space=unknown
color_transfer=unknown
color_primaries=unknown
chroma_location=left
timecode=N/A
refs=2
is_avc=false
nal_length_size=0
id=0x1011
r_frame_rate=25/1
avg_frame_rate=25/1
time_base=1/90000
start_pts=100800
start_time=1.120000
duration_ts=320400
duration=3.560000
bit_rate=N/A
max_bit_rate=N/A
bits_per_raw_sample=8
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
[/STREAM]
[STREAM]
index=1
codec_name=pcm_bluray
codec_long_name=PCM signed 16|20|24-bit big-endian for Blu-ray media
profile=unknown
codec_type=audio
codec_time_base=1/48000
codec_tag_string=HDMV
codec_tag=0x564d4448
sample_fmt=s16
sample_rate=48000
channels=2
channel_layout=stereo
bits_per_sample=0
id=0x1100
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/90000
start_pts=93600
start_time=1.040000
duration_ts=327601
duration=3.640011
bit_rate=1536000
max_bit_rate=N/A
bits_per_raw_sample=N/A
nb_frames=N/A
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
[/STREAM]

comment:3 by Carl Eugen Hoyos, 8 years ago

Keywords: mpegts h264 added; mpeg-ts estimate_timings estimate_timings_from_pts removed

comment:4 by Aleksandr, 8 years ago

Invented some "regular" solution for this problem, but it doesn't look like very good too.

reordered frame can be detected like this:

duration = pkt->pts + pkt->duration;
if (duration < previous duration)
{
    we met I or P frame before.
}
else
{
    we didn't meet I or P frame before, so we probably should
    increment duration on one frame in the end, or maybe read some mem before.
}

But what if there's a row of b-frames in the end, that are referenced only backward..

Note: See TracTickets for help on using tickets.