[vlc-commits] demux: es: add support for chapters

Francois Cartegnie git at videolan.org
Thu Feb 14 19:37:56 CET 2019


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Thu Feb 14 16:21:55 2019 +0100| [5019307b13e9854c081ca7bfa8e4c50d00e80bca] | committer: Francois Cartegnie

demux: es: add support for chapters

Adapted from initial work by Isaac Park <isaac.a.park at gmail.com>

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5019307b13e9854c081ca7bfa8e4c50d00e80bca
---

 modules/demux/mpeg/es.c | 144 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 131 insertions(+), 13 deletions(-)

diff --git a/modules/demux/mpeg/es.c b/modules/demux/mpeg/es.c
index d5be9a2527..a736769add 100644
--- a/modules/demux/mpeg/es.c
+++ b/modules/demux/mpeg/es.c
@@ -124,6 +124,12 @@ typedef struct
 
 typedef struct
 {
+    uint32_t i_offset;
+    seekpoint_t *p_seekpoint;
+} chap_entry_t;
+
+typedef struct
+{
     codec_t codec;
     vlc_fourcc_t i_original;
 
@@ -146,6 +152,7 @@ typedef struct
     int i_packet_size;
 
     uint64_t i_stream_offset;
+    unsigned i_demux_flags;
 
     float   f_fps;
 
@@ -164,6 +171,12 @@ typedef struct
     float rgf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
 
     sync_table_t mllt;
+    struct
+    {
+        size_t i_count;
+        size_t i_current;
+        chap_entry_t *p_entry;
+    } chapters;
 } demux_sys_t;
 
 static int MpgaProbe( demux_t *p_demux, uint64_t *pi_offset );
@@ -225,6 +238,8 @@ static int OpenCommon( demux_t *p_demux,
     p_sys->b_big_endian = false;
     p_sys->f_fps = var_InheritFloat( p_demux, "es-fps" );
     p_sys->p_packetized_data = NULL;
+    p_sys->chapters.i_current = 0;
+    TAB_INIT(p_sys->chapters.i_count, p_sys->chapters.p_entry);
 
     if( vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset ) )
     {
@@ -312,6 +327,21 @@ static int OpenVideo( vlc_object_t *p_this )
     }
     return OpenCommon( p_demux, VIDEO_ES, &codec_m4v, i_off );
 }
+
+static void IncreaseChapter( demux_t *p_demux, vlc_tick_t i_time )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    while( p_sys->chapters.i_current + 1 < p_sys->chapters.i_count )
+    {
+        const chap_entry_t *p = &p_sys->chapters.p_entry[p_sys->chapters.i_current + 1];
+        if( (p->i_offset != UINT32_MAX && vlc_stream_Tell( p_demux->s ) < p->i_offset) ||
+            (i_time == VLC_TICK_INVALID || p->p_seekpoint->i_time_offset + VLC_TICK_0 > i_time) )
+            break;
+        ++p_sys->chapters.i_current;
+        p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT;
+    }
+}
+
 /*****************************************************************************
  * Demux: reads and demuxes data packets
  *****************************************************************************
@@ -328,6 +358,11 @@ static int Demux( demux_t *p_demux )
     else
         ret = Parse( p_demux, &p_block_out ) ? 0 : 1;
 
+    /* Update chapter if any */
+    IncreaseChapter( p_demux,
+                     p_block_out ? p_sys->i_time_offset + p_block_out->i_dts
+                                 : VLC_TICK_INVALID );
+
     while( p_block_out )
     {
         block_t *p_next = p_block_out->p_next;
@@ -380,6 +415,9 @@ static void Close( vlc_object_t * p_this )
 
     if( p_sys->p_packetized_data )
         block_ChainRelease( p_sys->p_packetized_data );
+    for( size_t i=0; i< p_sys->chapters.i_count; i++ )
+        vlc_seekpoint_Delete( p_sys->chapters.p_entry[i].p_seekpoint );
+    TAB_CLEAN( p_sys->chapters.i_count, p_sys->chapters.p_entry );
     if( p_sys->mllt.p_bits )
         free( p_sys->mllt.p_bits );
     demux_PacketizerDestroy( p_sys->p_packetizer );
@@ -400,6 +438,8 @@ static int MovetoTimePos( demux_t *p_demux, vlc_tick_t i_time, uint64_t i_pos )
     if( p_sys->p_packetized_data )
         block_ChainRelease( p_sys->p_packetized_data );
     p_sys->p_packetized_data = NULL;
+    p_sys->chapters.i_current = 0;
+    p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT;
     return VLC_SUCCESS;
 }
 
@@ -463,6 +503,77 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             /* FIXME TODO: implement a high precision seek (with mp3 parsing)
              * needed for multi-input */
             break;
+
+        case DEMUX_GET_TITLE_INFO:
+        {
+            if( p_sys->chapters.i_count == 0 )
+                return VLC_EGENERIC;
+            input_title_t **pp_title = malloc( sizeof(*pp_title) );
+            if( !pp_title )
+                return VLC_EGENERIC;
+            *pp_title = vlc_input_title_New();
+            if( !*pp_title )
+            {
+                free( pp_title );
+                return VLC_EGENERIC;
+            }
+            (*pp_title)->seekpoint = vlc_alloc( p_sys->chapters.i_count, sizeof(seekpoint_t) );
+            if( !(*pp_title)->seekpoint )
+            {
+                free( *pp_title );
+                free( pp_title );
+                return VLC_EGENERIC;
+            }
+            for( size_t i=0; i<p_sys->chapters.i_count; i++ )
+            {
+                seekpoint_t *s = vlc_seekpoint_Duplicate( p_sys->chapters.p_entry[i].p_seekpoint );
+                if( s )
+                    (*pp_title)->seekpoint[(*pp_title)->i_seekpoint++] = s;
+            }
+            *(va_arg( args, input_title_t *** )) = pp_title;
+            *(va_arg( args, int* )) = 1;
+            *(va_arg( args, int* )) = 0;
+            *(va_arg( args, int* )) = 0;
+            return VLC_SUCCESS;
+        }
+        break;
+
+        case DEMUX_GET_TITLE:
+            if( p_sys->chapters.i_count == 0 )
+                return VLC_EGENERIC;
+            *(va_arg( args, int* )) = 0;
+            return VLC_SUCCESS;
+
+        case DEMUX_GET_SEEKPOINT:
+            if( p_sys->chapters.i_count == 0 )
+                return VLC_EGENERIC;
+            *(va_arg( args, int* )) = p_sys->chapters.i_current;
+            return VLC_SUCCESS;
+
+        case DEMUX_SET_TITLE:
+            return va_arg( args, int) == 0 ? VLC_SUCCESS : VLC_EGENERIC;
+
+        case DEMUX_SET_SEEKPOINT:
+        {
+            int i = va_arg( args, int );
+            if( (size_t)i>=p_sys->chapters.i_count )
+                return VLC_EGENERIC;
+            const chap_entry_t *p = &p_sys->chapters.p_entry[i];
+            if( p_sys->chapters.p_entry[i].i_offset == UINT32_MAX )
+                return demux_Control( p_demux, DEMUX_SET_TIME, p->p_seekpoint->i_time_offset );
+            int i_ret= MovetoTimePos( p_demux, p->p_seekpoint->i_time_offset, p->i_offset );
+            if( i_ret == VLC_SUCCESS )
+                p_sys->chapters.i_current = i;
+            return i_ret;
+        }
+
+        case DEMUX_TEST_AND_CLEAR_FLAGS:
+        {
+            unsigned *restrict flags = va_arg( args, unsigned * );
+            *flags &= p_sys->i_demux_flags;
+            p_sys->i_demux_flags &= ~*flags;
+            return VLC_SUCCESS;
+        }
     }
 
     int ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1,
@@ -470,21 +581,28 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     if( ret != VLC_SUCCESS )
         return ret;
 
-    if( p_sys->i_bitrate_avg > 0
-     && (i_query == DEMUX_SET_POSITION || i_query == DEMUX_SET_TIME) )
+    if( i_query == DEMUX_SET_POSITION || i_query == DEMUX_SET_TIME )
     {
-        int64_t i_time = INT64_C(8000000)
-            * ( vlc_stream_Tell(p_demux->s) - p_sys->i_stream_offset )
-            / p_sys->i_bitrate_avg;
-
-        /* Fix time_offset */
-        if( i_time >= 0 )
-            p_sys->i_time_offset = i_time - p_sys->i_pts;
-        /* And reset buffered data */
-        if( p_sys->p_packetized_data )
-            block_ChainRelease( p_sys->p_packetized_data );
-        p_sys->p_packetized_data = NULL;
+        if( p_sys->i_bitrate_avg > 0 )
+        {
+            int64_t i_time = INT64_C(8000000)
+                * ( vlc_stream_Tell(p_demux->s) - p_sys->i_stream_offset )
+                / p_sys->i_bitrate_avg;
+
+            /* Fix time_offset */
+            if( i_time >= 0 )
+                p_sys->i_time_offset = i_time - p_sys->i_pts;
+            /* And reset buffered data */
+            if( p_sys->p_packetized_data )
+                block_ChainRelease( p_sys->p_packetized_data );
+            p_sys->p_packetized_data = NULL;
+        }
+
+        /* Reset chapter if any */
+        p_sys->chapters.i_current = 0;
+        p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT;
     }
+
     return VLC_SUCCESS;
 }
 



More information about the vlc-commits mailing list