Opened 9 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 , 9 years ago
Version: | unspecified → git-master |
---|
comment:2 by , 9 years ago
comment:3 by , 9 years ago
Keywords: | mpegts h264 added; mpeg-ts estimate_timings estimate_timings_from_pts removed |
---|
comment:4 by , 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..
after raising DURATION_MAX_READ_SIZE to 1 Mb :
#define DURATION_MAX_READ_SIZE ( 1024LL * 1024 )
new duration_ts:
duration_ts=320400