Follow up: I appear to have solved this and have some further
information which may be useful.
TL;DR: Setting AVStream's avg_frame_rate, which corresponds to mkvinfo's
"Default duration" field, appears to have fixed this.
From my investigation, it appears VLC will use a few different sources
of information to determine the timecode. The first and foremost is the
aforementioned "default duration", corresponding to avg_frame_rate.
However if it's missing, it appears to use the MKV cluster size
(corresponding to the codec's gop_size). I noticed from mkvinfo that
each cluster started at the times VLC's playhead would appear to jump to
(0:00, 0:03, 0:07, etc.) and that changing the gop_size would shift
these around.
Following from this, it was somewhat inaccurate to say all of the
examples exhibit this issue. The "muxing" example, which sets the
gop_size to 12, creates an MKV that plays reasonably in VLC. With far
more frequent MKV clusters, VLC's timecode doesn't hang for seconds at a
time. However the downside of decreasing the gop_size is that naturally
it makes the file larger due to more intra frames and it presumably
means VLC's playhead is still only accurate to the nearest 12th frame.
When FFmpeg remuxes, it obviously doesn't change the gop_size, but it
does set the "default duration"/avg_frame_rate. Output from my program,
with avg_frame_rate set, works as expected without the file size
increases that result from changing the gop_size, so that appears to be
the solution.
As for the "remuxing" and "transcoding" examples:
* The output from "transcoding" will always exhibit this issue since
it doesn't set gop_size nor avg_frame_rate.
* The "remuxing" example depends on the input. If the MKV has a low
gop_size, it will obviously preserve that. However, it doesn't set
nor preserve "avg_frame_rate", so the output will exhibit this issue
with larger gop_size inputs (including non-MKV files such as MP4s).
* Disregard my comment about "encode_video", I forgot it didn't mux
anything.
It may be worth updating the relevant tests to fix this, but it depends
on whether this is considered a priority or not.
PS Andreas: You were correct about my subtitle packet duration being set
wrong, I have fixed this now.
Matt
On 8/7/2021 10:52 PM, MattKC wrote:
Andreas,
(A quick look showed that the transcoding example does not use
pkt_timebase for decoding, as does your code;
This is certainly the first time I've heard of using pkt_timebase.
Almost all examples and tutorials I've seen use AVStream::time_base.
What's the usage of this though? Documentation says "encoding unused"
and it seems to be null (0/1) when I tried using it just now.
furthermore, your code
sets the duration of subtitle packets wrong, as the end_display_time is
in a different timebase than the subtitle's pts.)
Is that incorrect? The AVSubtitle struct definition says
start_display_time and end_display_time are in ms not in time base
units. Also, the subtitles, as encoded by my program, appear to be
correct when played back.
I can open an issue on trac at some point, but the issue can be fairly
easily recreated just by using "remuxing output.mkv" or
"encode-video output.mkv libx264" or "transcoding
output.mkv". It would seem most if not all of the examples produce a
broken file when outputting to MKV.
I've attached the output of "mkvinfo -a" on both a broken MKV exported
from my program and a remuxed MKV from FFmpeg. They're largely
similar; the "Default duration" section in the remux and slightly
different order of packets are the only parts that stands out to me.
Let me know if you can get any meaningful information out of them.
Matt
On 8/7/2021 9:58 PM, Andreas Rheinhardt wrote:
MattKC:
==Summary==
I've been implementing ffmpeg/libav into an application, and have run
into timing-related issues when playing back Matroska/MKV videos created
by my application in VLC. I tried asking about this on the libav-user
mailing list and received no response so I thought I'd try here. While
it's true that there may be issues with VLC's implementation too, I've
noticed specifically that videos generated by FFmpeg do not cause these
issues, while my application and the examples in "doc/examples" (which
my code is modeled from) do, which makes me think this code is missing
something crucial.
==Symptoms==
During playback, VLC's playback time will appear to stay frozen at 0:00
while the video and audio plays normally. It will then jump only in
increments of a few seconds (0:03, then 0:07, then 0:11, etc.) This
behavior occurs with videos produced both by my application and by the
FF