* [FFmpeg-devel] [PATCH] avformat/movenc: add support for writing srat box (PR #21001)
@ 2025-11-23 12:28 James Almer via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: James Almer via ffmpeg-devel @ 2025-11-23 12:28 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: James Almer
PR #21001 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21001
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21001.patch
Defined mainly to signal a sample rate with a value that doesn't fit the standard 16bit field for formats that don't report a sample rate within private codec parameters (which in general takes precedence), as is the case for PCM.
For those, the spec recommends using AudioSampleEntryV1 to signal their parsing is required.
>From 2d5f77c5a2e0fe601eedd804dc67fef7a4708f78 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial@gmail.com>
Date: Fri, 21 Nov 2025 23:06:25 -0300
Subject: [PATCH] avformat/movenc: add support for writing srat box
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavformat/movenc.c | 51 +++++++++++++++++++++++++++++++++++++++-----
libavformat/movenc.h | 1 +
2 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 42c8771496..443ef2866c 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -161,6 +161,18 @@ static int64_t update_size(AVIOContext *pb, int64_t pos)
return curpos - pos;
}
+static int64_t update_size_and_version(AVIOContext *pb, int64_t pos, int version)
+{
+ int64_t curpos = avio_tell(pb);
+ avio_seek(pb, pos, SEEK_SET);
+ avio_wb32(pb, curpos - pos); /* rewrite size */
+ avio_skip(pb, 4);
+ avio_w8(pb, version); /* rewrite version */
+ avio_seek(pb, curpos, SEEK_SET);
+
+ return curpos - pos;
+}
+
static int co64_required(const MOVTrack *track)
{
if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
@@ -1344,6 +1356,18 @@ static int mov_write_pcmc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra
return update_size(pb, pos);
}
+static int mov_write_srat_tag(AVIOContext *pb, MOVTrack *track)
+{
+ int64_t pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* size */
+ ffio_wfourcc(pb, "srat");
+ avio_wb32(pb, 0); /* version & flags */
+
+ avio_wb32(pb, track->par->sample_rate);
+
+ return update_size(pb, pos);
+}
+
static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
{
int64_t pos = avio_tell(pb);
@@ -1363,6 +1387,10 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
track->par->codec_id == AV_CODEC_ID_QDM2) {
version = 1;
}
+ } else if (track->mode == MODE_MP4) {
+ if (track->par->sample_rate > UINT16_MAX &&
+ (tag == MOV_MP4_IPCM_TAG || tag == MOV_MP4_FPCM_TAG))
+ version = 1;
}
avio_wb32(pb, 0); /* size */
@@ -1395,6 +1423,8 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
avio_wb32(pb, track->sample_size);
avio_wb32(pb, get_samples_per_packet(track));
} else {
+ unsigned sample_rate = track->par->sample_rate;
+
if (track->mode == MODE_MOV) {
avio_wb16(pb, track->par->ch_layout.nb_channels);
if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
@@ -1415,6 +1445,9 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
avio_wb16(pb, 16);
}
avio_wb16(pb, 0);
+
+ while (sample_rate > UINT16_MAX)
+ sample_rate >>= 1;
}
avio_wb16(pb, 0); /* packet size (= 0) */
@@ -1425,14 +1458,14 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
else if (track->par->codec_id == AV_CODEC_ID_TRUEHD)
avio_wb32(pb, track->par->sample_rate);
else
- avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
- track->par->sample_rate : 0);
+ avio_wb16(pb, sample_rate);
if (track->par->codec_id != AV_CODEC_ID_TRUEHD)
avio_wb16(pb, 0); /* Reserved */
}
if (version == 1) { /* SoundDescription V1 extended info */
+ if (track->mode == MODE_MOV) {
if (mov_pcm_le_gt16(track->par->codec_id) ||
mov_pcm_be_gt16(track->par->codec_id))
avio_wb32(pb, 1); /* must be 1 for uncompressed formats */
@@ -1441,6 +1474,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */
avio_wb32(pb, track->sample_size); /* Bytes per frame */
avio_wb32(pb, 2); /* Bytes per sample */
+ }
}
if (track->mode == MODE_MOV &&
@@ -1489,9 +1523,13 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
if (ret < 0)
return ret;
- if (track->mode == MODE_MP4 && track->par->codec_type == AVMEDIA_TYPE_AUDIO
- && ((ret = mov_write_SA3D_tag(s, pb, track)) < 0)) {
+ if (track->mode == MODE_MP4) {
+ ret = mov_write_SA3D_tag(s, pb, track);
+ if (ret < 0)
return ret;
+
+ if (track->par->sample_rate > UINT16_MAX)
+ mov_write_srat_tag(pb, track);
}
if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO
@@ -1508,6 +1546,9 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
((ret = mov_write_btrt_tag(pb, track)) < 0))
return ret;
+ if (track->mode == MODE_MP4)
+ track->entry_version = version;
+
ret = update_size(pb, pos);
return ret;
}
@@ -3122,7 +3163,7 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext
track->last_stsd_index = stsd_index_back;
- return update_size(pb, pos);
+ return update_size_and_version(pb, pos, track->entry_version);
}
static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index 942ad905f7..eb12551ee5 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -86,6 +86,7 @@ typedef struct MOVFragmentInfo {
typedef struct MOVTrack {
int mode;
+ int entry_version;
int entry, entry_written;
unsigned timescale;
uint64_t time;
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-11-23 12:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-23 12:28 [FFmpeg-devel] [PATCH] avformat/movenc: add support for writing srat box (PR #21001) James Almer via ffmpeg-devel
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