Skip to content

Commit

Permalink
ffmpeg{,-devel}: add pixeldensity feature for retina displays (#26520)
Browse files Browse the repository at this point in the history
  • Loading branch information
gagan sidhu authored Nov 26, 2024
1 parent 68eb862 commit dc6f621
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 2 deletions.
10 changes: 9 additions & 1 deletion multimedia/ffmpeg-devel/Portfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set my_name ffmpeg
conflicts ffmpeg7

version 7.0.2
revision 1
revision 2
epoch 2

license LGPL-2.1+
Expand Down Expand Up @@ -119,6 +119,14 @@ patchfiles-append patch-libavcodec-librsvgdec.diff
# https://trac.macports.org/ticket/69678
# patchfiles-append patch-fix-vulkan.diff

# add retina resolution capabilities via -movflags write_pixeldensity flag
# this patch is by daniel kaiser who posted on the ffmpeg bugtracker:
# https://fftrac-bg.ffmpeg.org/ticket/7045
# but he never formally submitted it to the FFMpeg mailing list, which i did
# https://ffmpeg.org/pipermail/ffmpeg-devel/2024-July/331470.html
# so the FFMpeg team does not seem to care to include this functionality
patchfiles-append patch-add-pixeldensity.diff

# enable auto configure of asm optimizations
# requires Xcode 3.1 or better on Leopard
minimum_xcodeversions {9 3.1}
Expand Down
91 changes: 91 additions & 0 deletions multimedia/ffmpeg-devel/files/patch-add-pixeldensity.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
diff --git libavformat/movenc.c libavformat/movenc.c
index a961390..c5eb12d 100644
--- libavformat/movenc.c
+++ libavformat/movenc.c 2024-11-08 18:08:40.000000000 -0700
@@ -109,6 +109,7 @@
{ "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
{ "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
{ "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
+ { "write_pixeldensity", "Write pixeldensity metdata for HiDPI videos in QT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_PIXELDENSITY}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "write_colr", "Write colr atom even if the color info is unspecified (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
{ "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
{ "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext, min_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
@@ -4008,6 +4009,56 @@
return size;
}

+static int mov_write_pixeldensity_meta_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVFormatContext *s)
+{
+ int size = 0;
+ int64_t pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* meta atom size */
+ ffio_wfourcc(pb, "meta");
+
+ /* Metadata atom information as described in
+ * https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW9
+ */
+ avio_wb32(pb, 33); /* hdlr atom size: size (4) + 'hdlr' (4) + version/flags (4) + predefined (4) + 'mdta' (4) +
+ reserved (3*4) + name (1) = 33 */
+ ffio_wfourcc(pb, "hdlr");
+ avio_wb32(pb, 0); /* version (1 Byte) and flags (3 Bytes), must be zero */
+ avio_wb32(pb, 0); /* "predefined", must be zero */
+ ffio_wfourcc(pb, "mdta");
+ avio_wb32(pb, 0); /* Reseverved, uint32_t[3] */
+ avio_wb32(pb, 0);
+ avio_wb32(pb, 0);
+ avio_w8(pb, 0); /* Empty name (NULL-terminated) */
+
+ avio_wb32(pb, 56); /* keys atom size: size (4) + 'keys' (4) + version/flasgs (4) + entry_count (4) +
+ keys (32+8) = 56 */
+ ffio_wfourcc(pb, "keys");
+ avio_wb32(pb, 0); /* version (1 Byte) and flags (3 Bytes), must be zero */
+ avio_wb32(pb, 1); /* entry count */
+ avio_wb32(pb, 32 + 8); /* key size: size (4) + 'mdta' (4) + strlen(key) */
+ ffio_wfourcc(pb, "mdta");
+ avio_write(pb, "com.apple.quicktime.pixeldensity", 32);
+
+ avio_wb32(pb, 48); /* ilst atom size: size (4) + 'ilst' (4) + value atom size (40) = 48 */
+ ffio_wfourcc(pb, "ilst");
+ avio_wb32(pb, 40); /* value atom size: size (4) + key (4) + data atom (32) = 40 */
+ avio_wb32(pb, 1); /* metadata key index */
+
+ avio_wb32(pb, 32); /* data atom size: size (4) + 'data' (4) + data_type (4) + locale (4) + value (4 * 4) = 32 */
+ ffio_wfourcc(pb, "data");
+ avio_wb32(pb, 0x1e); /* data type */
+ avio_wb32(pb, 0); /* locale */
+
+ /* actual data (value): consisting of 4 uint32_t: pixel width, pixel height, display width, display height */
+ avio_wb32(pb, track->par->width);
+ avio_wb32(pb, track->par->height);
+ avio_wb32(pb, track->par->width / 2);
+ avio_wb32(pb, track->par->height / 2);
+
+ size = update_size(pb, pos);
+ return size;
+}
+
static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
MOVTrack *track, AVStream *st)
{
@@ -4067,6 +4118,9 @@
if (mov->flags & FF_MOV_FLAG_PIXELDENSITY) {
mov_write_pixeldensity_meta_tag(pb, mov, track, st);
}
+ if (mov->flags & FF_MOV_FLAG_PIXELDENSITY) {
+ mov_write_pixeldensity_meta_tag(pb, mov, track, st);
+ }
mov_write_track_udta_tag(pb, mov, st);
track->entry = entry_backup;
track->chunkCount = chunk_backup;
diff --git libavformat/movenc.h libavformat/movenc.h
index 68d6f23..ed7ea41 100644
--- libavformat/movenc.h
+++ libavformat/movenc.h
@@ -265,6 +265,7 @@ typedef struct MOVMuxContext {
#define FF_MOV_FLAG_SKIP_SIDX (1 << 21)
#define FF_MOV_FLAG_CMAF (1 << 22)
#define FF_MOV_FLAG_PREFER_ICC (1 << 23)
+#define FF_MOV_FLAG_PIXELDENSITY (1 << 24)

int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);

10 changes: 9 additions & 1 deletion multimedia/ffmpeg/Portfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set my_name ffmpeg

# Please increase the revision of mpv whenever ffmpeg's version is updated.
version 4.4.5
revision 0
revision 1
epoch 1

license LGPL-2.1+
Expand Down Expand Up @@ -112,6 +112,14 @@ patchfiles-append patch-libavcodec-videotoolboxenc.c.diff
# Fixed via upstream commit: b786bc7433dfe082441a57c1ba9ae9ea47904b78
patchfiles-append patch-issue-9439-non-b-frame-encoding.diff

# add retina resolution capabilities via -movflags write_pixeldensity flag
# this patch is by daniel kaiser who posted on the ffmpeg bugtracker:
# https://fftrac-bg.ffmpeg.org/ticket/7045
# but he never formally submitted it to the FFMpeg mailing list, which i did
# https://ffmpeg.org/pipermail/ffmpeg-devel/2024-July/331470.html
# so the FFMpeg team does not seem to care to include this functionality
patchfiles-append patch-add-pixeldensity.diff

# enable auto configure of asm optimizations
# requires Xcode 3.1 or better on Leopard
minimum_xcodeversions {9 3.1}
Expand Down
91 changes: 91 additions & 0 deletions multimedia/ffmpeg/files/patch-add-pixeldensity.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
diff --git libavformat/movenc.c libavformat/movenc.c
index a961390..c5eb12d 100644
--- libavformat/movenc.c
+++ libavformat/movenc.c
@@ -78,6 +78,7 @@
{ "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "skip_sidx", "Skip writing of sidx atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+ { "write_pixeldensity", "Write pixeldensity metdata for HiDPI videos in QT", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_PIXELDENSITY}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "write_colr", "Write colr atom even if the color info is unspecified (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "prefer_icc", "If writing colr atom prioritise usage of ICC profile if it exists in stream packet side data", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_PREFER_ICC}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
{ "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -3413,6 +3414,56 @@
return size;
}

+static int mov_write_pixeldensity_meta_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVFormatContext *s)
+{
+ int size = 0;
+ int64_t pos = avio_tell(pb);
+ avio_wb32(pb, 0); /* meta atom size */
+ ffio_wfourcc(pb, "meta");
+
+ /* Metadata atom information as described in
+ * https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW9
+ */
+ avio_wb32(pb, 33); /* hdlr atom size: size (4) + 'hdlr' (4) + version/flags (4) + predefined (4) + 'mdta' (4) +
+ reserved (3*4) + name (1) = 33 */
+ ffio_wfourcc(pb, "hdlr");
+ avio_wb32(pb, 0); /* version (1 Byte) and flags (3 Bytes), must be zero */
+ avio_wb32(pb, 0); /* "predefined", must be zero */
+ ffio_wfourcc(pb, "mdta");
+ avio_wb32(pb, 0); /* Reseverved, uint32_t[3] */
+ avio_wb32(pb, 0);
+ avio_wb32(pb, 0);
+ avio_w8(pb, 0); /* Empty name (NULL-terminated) */
+
+ avio_wb32(pb, 56); /* keys atom size: size (4) + 'keys' (4) + version/flasgs (4) + entry_count (4) +
+ keys (32+8) = 56 */
+ ffio_wfourcc(pb, "keys");
+ avio_wb32(pb, 0); /* version (1 Byte) and flags (3 Bytes), must be zero */
+ avio_wb32(pb, 1); /* entry count */
+ avio_wb32(pb, 32 + 8); /* key size: size (4) + 'mdta' (4) + strlen(key) */
+ ffio_wfourcc(pb, "mdta");
+ avio_write(pb, "com.apple.quicktime.pixeldensity", 32);
+
+ avio_wb32(pb, 48); /* ilst atom size: size (4) + 'ilst' (4) + value atom size (40) = 48 */
+ ffio_wfourcc(pb, "ilst");
+ avio_wb32(pb, 40); /* value atom size: size (4) + key (4) + data atom (32) = 40 */
+ avio_wb32(pb, 1); /* metadata key index */
+
+ avio_wb32(pb, 32); /* data atom size: size (4) + 'data' (4) + data_type (4) + locale (4) + value (4 * 4) = 32 */
+ ffio_wfourcc(pb, "data");
+ avio_wb32(pb, 0x1e); /* data type */
+ avio_wb32(pb, 0); /* locale */
+
+ /* actual data (value): consisting of 4 uint32_t: pixel width, pixel height, display width, display height */
+ avio_wb32(pb, track->par->width);
+ avio_wb32(pb, track->par->height);
+ avio_wb32(pb, track->par->width / 2);
+ avio_wb32(pb, track->par->height / 2);
+
+ size = update_size(pb, pos);
+ return size;
+}
+
static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
MOVTrack *track, AVStream *st)
{
@@ -3460,6 +3511,9 @@ static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext
mov_write_tapt_tag(pb, track);
}
}
+ if (mov->flags & FF_MOV_FLAG_PIXELDENSITY) {
+ mov_write_pixeldensity_meta_tag(pb, mov, track, st);
+ }
mov_write_track_udta_tag(pb, mov, st);
track->entry = entry_backup;
track->chunkCount = chunk_backup;
diff --git libavformat/movenc.h libavformat/movenc.h
index 68d6f23..ed7ea41 100644
--- libavformat/movenc.h
+++ libavformat/movenc.h
@@ -265,6 +265,7 @@ typedef struct MOVMuxContext {
#define FF_MOV_FLAG_SKIP_SIDX (1 << 21)
#define FF_MOV_FLAG_CMAF (1 << 22)
#define FF_MOV_FLAG_PREFER_ICC (1 << 23)
+#define FF_MOV_FLAG_PIXELDENSITY (1 << 24)

int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);

0 comments on commit dc6f621

Please sign in to comment.