[vlc-devel] [PATCH] demux: mp4: Add support for GoPro HiLight tags as chapters, so they can appear in the progress bar
Emeric Grange
emeric.grange at gmail.com
Wed Oct 28 19:56:40 CET 2015
---
modules/demux/mp4/libmp4.c | 41 +++++++++++++++++++++++++++++++++++++++++
modules/demux/mp4/libmp4.h | 15 +++++++++++++++
modules/demux/mp4/mp4.c | 22 ++++++++++++++++++++++
3 files changed, 78 insertions(+)
diff --git a/modules/demux/mp4/libmp4.c b/modules/demux/mp4/libmp4.c
index e902ac8..f7918da 100644
--- a/modules/demux/mp4/libmp4.c
+++ b/modules/demux/mp4/libmp4.c
@@ -3175,6 +3175,46 @@ static int MP4_ReadBox_chpl( stream_t *p_stream, MP4_Box_t *p_box )
MP4_READBOX_EXIT( 1 );
}
+/* GoPro HiLight tags support */
+static void MP4_FreeBox_hmmt( MP4_Box_t *p_box )
+{
+ MP4_Box_data_HMMT_t *p_hmmt = p_box->data.p_hmmt;
+ for( unsigned i = 0; i < p_hmmt->i_chapter; i++ )
+ free( p_hmmt->chapter[i].psz_name );
+}
+
+static int MP4_ReadBox_HMMT( stream_t *p_stream, MP4_Box_t *p_box )
+{
+ MP4_Box_data_HMMT_t *p_hmmt;
+ char tag_nb[4] = {0};
+
+ MP4_READBOX_ENTER( MP4_Box_data_HMMT_t, MP4_FreeBox_hmmt );
+
+ p_hmmt = p_box->data.p_hmmt;
+
+ MP4_GET4BYTES( p_hmmt->i_chapter );
+
+ for( uint32_t i = 0; i < p_hmmt->i_chapter; i++ )
+ {
+ uint64_t i_start;
+
+ p_hmmt->chapter[i].psz_name = malloc( 18 );
+ if( !p_hmmt->chapter[i].psz_name )
+ MP4_READBOX_EXIT( 0 );
+ strncpy(p_hmmt->chapter[i].psz_name, "HiLight tag #", 17);
+ snprintf(tag_nb, 3, "%d", i + 1);
+ strncat(p_hmmt->chapter[i].psz_name, tag_nb, 4);
+
+ MP4_GET4BYTES( i_start );
+ p_hmmt->chapter[i].i_start = i_start;
+ }
+
+ msg_Dbg( p_stream, "read box: \"HMMT\" %d HiLight tags",
+ p_hmmt->i_chapter );
+
+ MP4_READBOX_EXIT( 1 );
+}
+
static void MP4_FreeBox_tref_generic( MP4_Box_t *p_box )
{
FREENULL( p_box->data.p_tref_generic->i_track_ID );
@@ -3971,6 +4011,7 @@ static const struct
{ ATOM_name, MP4_ReadBox_String, ATOM_udta },
{ ATOM_vndr, MP4_ReadBox_String, ATOM_udta },
{ ATOM_SDLN, MP4_ReadBox_String, ATOM_udta },
+ { ATOM_HMMT, MP4_ReadBox_HMMT, ATOM_udta }, /* GoPro HiLights */
/* udta, non meta */
{ ATOM_tsel, MP4_ReadBox_tsel, ATOM_udta },
diff --git a/modules/demux/mp4/libmp4.h b/modules/demux/mp4/libmp4.h
index 62a6b30..b2ca71e 100644
--- a/modules/demux/mp4/libmp4.h
+++ b/modules/demux/mp4/libmp4.h
@@ -314,6 +314,7 @@ typedef int64_t stime_t;
#define ATOM_0xa9xyz VLC_FOURCC( 0xa9, 'x', 'y', 'z' )
#define ATOM_aART VLC_FOURCC( 'a', 'A', 'R', 'T' )
#define ATOM_chpl VLC_FOURCC( 'c', 'h', 'p', 'l' )
+#define ATOM_HMMT VLC_FOURCC( 'H', 'M', 'M', 'T' )
#define ATOM_disk VLC_FOURCC( 'd', 'i', 's', 'k' )
#define ATOM_WLOC VLC_FOURCC( 'W', 'L', 'O', 'C' )
@@ -1103,6 +1104,19 @@ typedef struct
typedef struct
{
+ uint8_t i_version;
+ uint32_t i_flags;
+
+ uint32_t i_chapter;
+ struct
+ {
+ char *psz_name;
+ int64_t i_start;
+ } chapter[400];
+} MP4_Box_data_HMMT_t;
+
+typedef struct
+{
uint8_t i_version;
uint8_t i_profile;
uint8_t i_profile_compatibility;
@@ -1490,6 +1504,7 @@ typedef union MP4_Box_data_s
MP4_Box_data_pnot_t *p_pnot;
MP4_Box_data_chpl_t *p_chpl;
+ MP4_Box_data_HMMT_t *p_hmmt;
MP4_Box_data_tref_generic_t *p_tref_generic;
MP4_Box_data_tfrf_t *p_tfrf;
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index ff9fb3b..9bec173 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -1774,6 +1774,23 @@ static void LoadChapterGpac( demux_t *p_demux, MP4_Box_t *p_chpl )
TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
}
}
+static void LoadChapterGoPro( demux_t *p_demux, MP4_Box_t *p_chpl )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ int i;
+
+ p_sys->p_title = vlc_input_title_New();
+ for( i = 0; i < BOXDATA(p_chpl)->i_chapter; i++ )
+ {
+ seekpoint_t *s = vlc_seekpoint_New();
+
+ s->psz_name = strdup( BOXDATA(p_chpl)->chapter[i].psz_name );
+ EnsureUTF8( s->psz_name );
+ // HiLights are expressed in ms, convert to µs
+ s->i_time_offset = BOXDATA(p_chpl)->chapter[i].i_start * 1000;
+ TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
+ }
+}
static void LoadChapterApple( demux_t *p_demux, mp4_track_t *tk )
{
demux_sys_t *p_sys = p_demux->p_sys;
@@ -1823,6 +1840,11 @@ static void LoadChapter( demux_t *p_demux )
{
LoadChapterGpac( p_demux, p_chpl );
}
+ else if( ( p_chpl = MP4_BoxGet( p_sys->p_root, "/moov/udta/HMMT" ) ) &&
+ BOXDATA(p_chpl) && BOXDATA(p_chpl)->i_chapter > 0 )
+ {
+ LoadChapterGoPro( p_demux, p_chpl );
+ }
else if( p_sys->p_tref_chap )
{
MP4_Box_data_tref_generic_t *p_chap = p_sys->p_tref_chap->data.p_tref_generic;
--
2.6.2
More information about the vlc-devel
mailing list