Timestamps are ignored if decoded frames are in wrong order
Reported by
taemoji...@gmail.com,
Dec 10 2017
|
||
Issue description
Chrome Version : 62.0.3202.97 (64-bit)
URLs (if applicable) :
OS version : 9901.77.0 stable (unless Platform is not OS)
Network (such as Cable/DSL/Dial up etc):
Audio/Video format (if applicable): mpeg4 / .avi
Special chrome flags (if applicable):
Behavior in Firefox (if known): The file is not supported.
Video issue, Audio issue, both, neither? Video
Occurs with HTML5 or native playback.
I am attempting to play a file from around 10 years ago on a Chromebook, since it seems difficult or impossible to use the Chromebook to play it on a certain Roku set-top device model. The problem is it 'stutters', going one or two frames forward and then going back to an older frame. This happens both with the 'video app' and with the Chrome browser.
As noted above, Firefox won't play the file at all. The Chrome browser on my (GNU/)Linux laptop will play audio from the file, but no video shows up and the controls are centered with no video size selected. So to play the video with a 'stutter' is an improvement. The video plays fine in other applications using the avformat/ffmpeg-based libraries with no problems.
The ffmpeg mpeg4 demuxer gives this warning:
"Video uses a non-standard and wasteful way to store B-frames ('packed B-frames'). Consider using the mpeg4_unpack_bframes bitstream filter without encoding but stream copy to fix it."
I tried copying the video to an mp4 container, same result. I tried using this bitstream filter. The warning disappears, but ChromeOS still plays the file with a stutter.
I tried testing the ordered-frames.mp4 file, generated with this command:
ffmpeg -filter_complex "color=white:160x160:1,drawtext='fontcolor=black:fontsize=96:x=(W-tw)/2+4:y=(H-th)/2+4:text=%{n}:alpha=0.5',boxblur,drawtext='fontcolor=black:fontsize=96:x=(W-tw)/2:y=(H-th)/2:text=%{n}'" -preset veryslow -refs 8 -aq-strength 0.5 -threads 1 -crf 20 -frames:v 30 -movflags faststart ordered-frames.mp4
The resulting frames are out of order, as can be seen from 'ffprobe -hide_banner -show_frames ordered-frames.mp4 -select_streams v | grep coded', but Chrome OS and the Chrome browser play the file perfectly.
slow.mp4 is copy.mp4 slowed down using mencoder. The stuttering can be seen in more detail.
The reason for the stuttering seems to be that the 'Video Player' and Chrome browser in Chrome OS show frames in the order they appear in the decoded stream, without regard to the timestamps.
With ordered-frames.mp4 and typical h.264 files such as those served by YouTube, if you examine the packets with ffprobe and -show_packets or a command like ' ffprobe -hide_banner -show_entries packet=size,pts_time,flags ordered-frames.mp4 -select_streams v | less', you can see the timestamps skip around.
But if you check the decoded frames, with 'ffprobe -show_frames <file>', they are in monotonically ascending timestamp order.
With copy.mp4, it's the opposite. The packets are in order, but the decoded frames are mixed up, with the B-frames coming before the P-frames that they, presumably, depend on. I had sort of assumed that ffprobe sorted the packets itself, but either a file like this is specifying the packet order independently of the timestamps, or the demuxer is bugged and putting the outputted frames in the wrong order even if it gets the timestamps right.
The dts/decode timestamps of copy.mp4 are also changed between -show_frames and -show_packets, and I think I've seen this to be a problem before, but I don't think it's the problem in this case.
(One thing I haven't done is check other .avi files, since I guess .avi files don't track dts, and whether putting an mpeg stream into an avi file will cause it to stutter after being moved back to mp4.)
,
Dec 10 2017
So, the title of this bug is partially incorrect. Apparently, Chrome displays an mp4 file converted from avi 'incorrectly' only because it reads frames early, allowing it to notice presentation timestamps before other programs, even if it apparently reads less than 10 frames ahead so some frames can get missed and then dropped, if a file is 'broken' with dts being later than pts. To reiterate, in copy.mp4, Chrome isn't displaying the decoded frames in stream order as shown in ffprobe. It is paying attention to presentation timestamps, not ignoring them. The frames are not in the wrong order, but they do appear to have the wrong presentation timestamps (pts), which is why Chrome displays them incorrectly. Other programs display them correctly because they avoid decoding frames early. The reason for displaying an avi file incorrectly might be different. Chrome displays the avi file the same as it does the re-muxed (?) mp4 file, but avi files have no recorded pts value for Chrome to look for. It appears Chrome is showing frames based on their packet dts as shown in ffprobe, instead of the frame dts which is different. So looking at ordered-frames.avi, using 'ffprobe -hide_banner -show_entries frame=pkt_pts_time,pkt_dts_time,pkt_size,coded_picture_number ordered-frames.avi -select_streams v | less'. The frames appear sorted, starting at pkt_dts_time=2 and increasing from there. But packet sizes go 1808, 351, 779. If we look at the packets instead, with 'ffprobe -hide_banner -show_entries packet=dts_time,size ordered-frames.avi -select_streams v | less', the packets seem sorted here as well, going 0, 1, 2, 3... But size goes 1808, 779, 351. Based on ffprobe output for the original file, ordered-frames.mp4, the second frame should have size 351. (Also, coded_picture_number doesn't mean what I implied it did, and if their order was close to the 'buggy' output, probably coincidence.) In the buggy output, the numbers displayed go 0, 2, 1. For the avi file, this matches the packet order and packet dts values, not the frame order or frame dts values that ffprobe shows. Presumably the packets contain the different dts value. For pts values and mp4 files, it seems the packet and frame pts are the same. dts for frames is shown as always being the same as pts for the original file, ordered-frames.mp4, with no relation to the packet dts; but in ordered-frames-avicopy.mp4, the frame pts is always the same as the packet dts (and packet pts), which is two more than the packet pts for the original, while the frame dts is always two more than the frame dts for the original. I'm not sure why the dts for a packet, and pkt_dts for a frame, are different when "pkt" seems like an abbreviation for packet. For typical files that aren't copied from an avi, the frame dts and pts seem to always be the same. So if programs are ignoring the 'frame pts' recorded for a frame, and only using the dts value which has also been recorded for the frame separately than for the packet that contains it, they wouldn't have any bugs. But Chrome doesn't ignore it or reads ahead when other programs don't, and also apparently handles avi files wrong in a way that coincidentally leads to the same output, so the video stutters. I hope this problem can be fixed, so avi files and bugged mp4 files will play correctly in Chrome OS.
,
Dec 10 2017
pts values reported as a bug for ffmpeg, but will not fix avi playback: https://trac.ffmpeg.org/ticket/6905
,
Dec 10 2017
Using MP4Box, which is part of the 'gpac' package, I was able to get a non-bugged mp4 for the original avi I was testing with, but it didn't accept the 'avc1' (h.264) codec from ordered-frames.avi.
After copying the first few seconds of the original avi to copy.avi, I then performed
MP4Box -add copy.avi copy-MP4Box.mp4
The result is attached. It doesn't stutter in Chrome OS. When I unpacked the frames using ffmpeg's bitstream filter, the time to play that file ('time ffmpeg -i copy2-MP4Box.mp4 -f null -', with CPU frequency locked) is statistically indistinguishable from the non-unpacked version, though it could possibly affect hardware decoding.
Neither the unpacked nor the packed B-frame versions would play video in Chrome on Linux, so I am just including the original packed version.
In this file, the frame pts's are the same as the dts's when examined with ffprobe.
,
Dec 11 2017
I appreciate your debugging, but we intentionally do not support manual reordering of decoded frames. These files are considered broken if the encoded bitstream is not correctly marked for reordering (which doesn't use timestamps). It seems you've found a way to remux the file with correct timestamps in c#4 without re-encoding which is great! Chrome doesn't aim to play or work with every file; for reasons of maintenance and security over the lifetime of a project the size and age of Chrome, we try to error out on unexpected conditions as soon as possible.
,
Dec 14 2017
You may want to prevent Chrome from playing .avi files, then. As it was, I spent some time looking for a cause and solution. Many answers about stuttering video said to disable hardware acceleration, which I tried. I do wonder why Chrome OS has libraries to demux .avi files if it does not intend to correctly order the frames in it. |
||
►
Sign in to add a comment |
||
Comment 1 by taemoji...@gmail.com
, Dec 10 201720.0 KB
20.0 KB Download
13.8 KB
13.8 KB View Download
1000 KB
1000 KB Download