PR #25579 opened by Zhao Zhili (quink) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25579 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25579.patch
# Summary of changes DJI cameras store flight and gimbal data in djmd and dbgi metadata tracks: a 20-byte sample entry, a child box of the same name in gmhd, and the meta handler named "CAM meta" or "CAM dbgi". **DJI doesn't registered the fourcc at https://mp4ra.org/search, so as GoPro gpmd** >From 6d69eafd2208fb08b3825a93dd710b812d5d142f Mon Sep 17 00:00:00 2001 From: Zhao Zhili <[email protected]> Date: Thu, 29 Oct 2026 13:20:13 +0800 Subject: [PATCH 1/2] avformat/mov: demux DJI djmd and dbgi tracks as bin_data DJI cameras write flight and gimbal data into djmd and dbgi tracks whose sample entries use a private fourcc under the meta handler. Map them to bin_data, as is already done for the GoPro gpmd track. Signed-off-by: Zhao Zhili <[email protected]> --- libavformat/isom.c | 2 ++ libavformat/isom.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/libavformat/isom.c b/libavformat/isom.c index 0a2f93d762f..09be63aa193 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -81,6 +81,8 @@ const AVCodecTag ff_codec_movsubtitle_tags[] = { const AVCodecTag ff_codec_movdata_tags[] = { { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') }, + { AV_CODEC_ID_BIN_DATA, MOV_MP4_DJMD_TAG }, + { AV_CODEC_ID_BIN_DATA, MOV_MP4_DBGI_TAG }, { AV_CODEC_ID_ITUT_T35, MKTAG('i', 't', '3', '5') }, { AV_CODEC_ID_NONE, 0 }, }; diff --git a/libavformat/isom.h b/libavformat/isom.h index 18c2fe41b9a..6230218e37f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -507,6 +507,9 @@ static inline enum AVCodecID ff_mov_get_lpcm_codec_id(int bps, int flags) #define MOV_MP4_FPCM_TAG MKTAG('f', 'p', 'c', 'm') #define MOV_MP4_IPCM_TAG MKTAG('i', 'p', 'c', 'm') +#define MOV_MP4_DJMD_TAG MKTAG('d', 'j', 'm', 'd') +#define MOV_MP4_DBGI_TAG MKTAG('d', 'b', 'g', 'i') + struct MP4TrackKindValueMapping { int disposition; const char *value; -- 2.54.0 >From 6ab132f5b44849ebe35d9db662c36af483887271 Mon Sep 17 00:00:00 2001 From: Zhao Zhili <[email protected]> Date: Thu, 29 Oct 2026 15:24:48 +0800 Subject: [PATCH 2/2] avformat/movenc: add DJI djmd and dbgi metadata support DJI cameras store flight and gimbal data in djmd and dbgi metadata tracks: a 20-byte sample entry, a child box of the same name in gmhd, and the meta handler named "CAM meta" or "CAM dbgi". Signed-off-by: Zhao Zhili <[email protected]> --- libavformat/movenc.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index debe1acb7e0..d6b6a87688f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -3244,6 +3244,18 @@ static int mov_write_gpmd_tag(AVIOContext *pb, const MOVTrack *track) return update_size(pb, pos); } +static int mov_write_dji_tag(AVIOContext *pb, const MOVTrack *track, uint32_t tag) +{ + avio_wb32(pb, 20); + avio_wl32(pb, tag); + avio_wb32(pb, 0); /* Reserved */ + avio_wb16(pb, 0); /* Reserved */ + avio_wb16(pb, 1); /* Data-reference index */ + avio_wb32(pb, 0); /* Reserved */ + + return 0; +} + static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t pos = avio_tell(pb); @@ -3269,6 +3281,9 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext ret = mov_write_tmcd_tag(pb, track); else if (track->par->codec_tag == MKTAG('g','p','m','d')) ret = mov_write_gpmd_tag(pb, track); + else if (track->par->codec_tag == MOV_MP4_DJMD_TAG || + track->par->codec_tag == MOV_MP4_DBGI_TAG) + ret = mov_write_dji_tag(pb, track, track->par->codec_tag); if (ret < 0) return ret; @@ -3615,6 +3630,13 @@ static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "gpmd"); avio_wb32(pb, 0); /* version */ update_size(pb, gpmd_pos); + } else if (track->par->codec_tag == MOV_MP4_DBGI_TAG) { + avio_wb32(pb, 12); + avio_wl32(pb, MOV_MP4_DBGI_TAG); + avio_wb32(pb, 0); + } else if (track->par->codec_tag == MOV_MP4_DJMD_TAG) { + avio_wb32(pb, 8); + avio_wl32(pb, MOV_MP4_DJMD_TAG); } return update_size(pb, pos); } @@ -3707,6 +3729,12 @@ static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra } else if (track->par->codec_tag == MKTAG('g','p','m','d')) { hdlr_type = "meta"; descr = "GoPro MET"; // GoPro Metadata + } else if (track->par->codec_tag == MOV_MP4_DJMD_TAG) { + hdlr_type = "meta"; + descr = "CAM meta"; + } else if (track->par->codec_tag == MOV_MP4_DBGI_TAG) { + hdlr_type = "meta"; + descr = "CAM dbgi"; } else { av_log(s, AV_LOG_WARNING, "Unknown hdlr_type for %s, writing dummy values\n", @@ -3956,7 +3984,9 @@ static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext mov_write_nmhd_tag(pb); else mov_write_gmhd_tag(pb, track); - } else if (track->tag == MKTAG('g','p','m','d')) { + } else if (track->tag == MKTAG('g','p','m','d') || + track->tag == MOV_MP4_DJMD_TAG || + track->tag == MOV_MP4_DBGI_TAG) { mov_write_gmhd_tag(pb, track); } if (track->mode == MODE_MOV) /* ISO 14496-12 8.4.3.1 specifies hdlr only within mdia or meta boxes */ @@ -9492,6 +9522,8 @@ static const AVCodecTag codec_mp4_tags[] = { { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') }, { AV_CODEC_ID_MOV_TEXT, MKTAG('t', 'x', '3', 'g') }, { AV_CODEC_ID_BIN_DATA, MKTAG('g', 'p', 'm', 'd') }, + { AV_CODEC_ID_BIN_DATA, MOV_MP4_DJMD_TAG }, + { AV_CODEC_ID_BIN_DATA, MOV_MP4_DBGI_TAG }, { AV_CODEC_ID_MPEGH_3D_AUDIO, MKTAG('m', 'h', 'm', '1') }, { AV_CODEC_ID_TTML, MOV_MP4_TTML_TAG }, { AV_CODEC_ID_TTML, MOV_ISMV_TTML_TAG }, -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
