From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH 1/2] avformat/matroskaenc: Don't create wrong packet durations
Date: Sun, 1 Oct 2023 15:08:51 +0200
Message-ID: <AS8P250MB0744E00FA1B93CD5BC8436408FC6A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <AS8P250MB0744A27B21CEC9E7014FED7C8FC0A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM>
Andreas Rheinhardt:
> We have to write an explicit BlockDuration element (and use
> a BlockGroup instead of a SimpleBlock) in case the Track
> has a DefaultDuration that is inconsistent with the duration
> of the packet.
>
> The matroska-h264-remux test uses a file with coded fields
> where the duration of a Block is the duration of a field,
> not of a frame, therefore this patch writes said BlockDuration
> elements.
>
> (When using a BlockGroup, one has to add ReferenceBlock elements
> to distinguish keyframes from non-keyframes. Unfortunately,
> the AV1 codec mapping [1] requires us to reference all references
> and to really use the real references, which requires a lot of
> effort for basically no gain. When BlockGroups are used with AV1,
> the created files are most likely invalid, both before and after
> this patch, but this patch makes this more likely to happen.)
>
> [1]: https://github.com/ietf-wg-cellar/matroska-specification/blob/master/codec/av1.md
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
> libavformat/matroskaenc.c | 40 ++++++++++++++++++++++--------
> tests/ref/fate/matroska-h264-remux | 4 +--
> 2 files changed, 32 insertions(+), 12 deletions(-)
>
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index ba54f5f98e..9286932a08 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -195,6 +195,8 @@ typedef struct mkv_track {
> int codecpriv_offset;
> unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field
> int64_t ts_offset;
> + uint64_t default_duration_low;
> + uint64_t default_duration_high;
> /* This callback will be called twice: First with a NULL AVIOContext
> * to return the size of the (Simple)Block's data via size
> * and a second time with the AVIOContext set when the data
> @@ -1805,6 +1807,16 @@ static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv,
> return ebml_writer_write(&writer, pb);
> }
>
> +static void mkv_write_default_duration(mkv_track *track, AVIOContext *pb,
> + AVRational duration)
> +{
> + put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION,
> + 1000000000LL * duration.num / duration.den);
> + track->default_duration_low = 1000LL * duration.num / duration.den;
> + track->default_duration_high = track->default_duration_low +
> + !!(1000LL * duration.num % duration.den);
> +}
> +
> static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
> AVStream *st, mkv_track *track, AVIOContext *pb,
> int is_default)
> @@ -1913,16 +1925,19 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
> }
>
> switch (par->codec_type) {
> + AVRational frame_rate;
> case AVMEDIA_TYPE_VIDEO:
> mkv->have_video = 1;
> put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
>
> - if( st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0
> - && av_cmp_q(av_inv_q(st->avg_frame_rate), st->time_base) > 0)
> - put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->avg_frame_rate.den / st->avg_frame_rate.num);
> - else if( st->r_frame_rate.num > 0 && st->r_frame_rate.den > 0
> - && av_cmp_q(av_inv_q(st->r_frame_rate), st->time_base) > 0)
> - put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->r_frame_rate.den / st->r_frame_rate.num);
> + frame_rate = (AVRational){ 0, 1 };
> + if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0)
> + frame_rate = st->avg_frame_rate;
> + else if (st->r_frame_rate.num > 0 && st->r_frame_rate.den > 0)
> + frame_rate = st->r_frame_rate;
> +
> + if (frame_rate.num > 0)
> + mkv_write_default_duration(track, pb, av_inv_q(frame_rate));
>
> if (CONFIG_MATROSKA_MUXER && !native_id &&
> ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) &&
> @@ -2739,7 +2754,12 @@ static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
> ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKGROUP);
> ebml_writer_add_block(&writer, mkv);
>
> - if (duration)
> + if (duration > 0 && (par->codec_type == AVMEDIA_TYPE_SUBTITLE ||
> + /* If the packet's duration is inconsistent with the default duration,
> + * add an explicit duration element. */
> + track->default_duration_high > 0 &&
> + duration != track->default_duration_high &&
> + duration != track->default_duration_low))
> ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration);
>
> av_log(logctx, AV_LOG_DEBUG,
> @@ -2917,7 +2937,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
> /* All subtitle blocks are considered to be keyframes. */
> int keyframe = is_sub || !!(pkt->flags & AV_PKT_FLAG_KEY);
> int64_t duration = FFMAX(pkt->duration, 0);
> - int64_t write_duration = is_sub ? duration : 0;
> + int64_t cue_duration = is_sub ? duration : 0;
> int ret;
> int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
> int64_t relative_packet_pos;
> @@ -2958,7 +2978,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
> /* The WebM spec requires WebVTT to be muxed in BlockGroups;
> * so we force it even for packets without duration. */
> ret = mkv_write_block(s, mkv, pb, par, track, pkt,
> - keyframe, ts, write_duration,
> + keyframe, ts, duration,
> par->codec_id == AV_CODEC_ID_WEBVTT,
> relative_packet_pos);
> if (ret < 0)
> @@ -2969,7 +2989,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt)
> !mkv->have_video && !track->has_cue)) {
> ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts,
> mkv->cluster_pos, relative_packet_pos,
> - write_duration);
> + cue_duration);
> if (ret < 0)
> return ret;
> track->has_cue = 1;
> diff --git a/tests/ref/fate/matroska-h264-remux b/tests/ref/fate/matroska-h264-remux
> index 2c727f03cd..6362b6f684 100644
> --- a/tests/ref/fate/matroska-h264-remux
> +++ b/tests/ref/fate/matroska-h264-remux
> @@ -1,5 +1,5 @@
> -f6b943ed3ff05087d0ef58fbaf7abcb0 *tests/data/fate/matroska-h264-remux.matroska
> -2036067 tests/data/fate/matroska-h264-remux.matroska
> +277a08f708965112a7c2fb25d941e68a *tests/data/fate/matroska-h264-remux.matroska
> +2036806 tests/data/fate/matroska-h264-remux.matroska
> #tb 0: 1/25
> #media_type 0: video
> #codec_id 0: rawvideo
Will apply this patchset tomorrow unless there are objections.
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
prev parent reply other threads:[~2023-10-01 13:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-29 16:01 Andreas Rheinhardt
2023-09-29 16:04 ` [FFmpeg-devel] [PATCH 2/2] avformat/matroskaenc: Write default duration for audio Andreas Rheinhardt
2023-09-29 16:08 ` [FFmpeg-devel] [PATCH 1/2] avformat/matroskaenc: Don't create wrong packet durations James Almer
2023-09-29 16:47 ` Andreas Rheinhardt
2023-10-01 13:08 ` Andreas Rheinhardt [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AS8P250MB0744E00FA1B93CD5BC8436408FC6A@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM \
--to=andreas.rheinhardt@outlook.com \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git