[vlc-devel] commit: avformat: Support for AVChapters. (Derk-Jan Hartman )

git version control git at videolan.org
Tue Sep 23 17:01:35 CEST 2008


vlc | branch: master | Derk-Jan Hartman <hartman at videolan.org> | Tue Sep 23 17:01:54 2008 +0200| [be3f9e2d910a61ae87d79f4fb0481848331dc950] | committer: Derk-Jan Hartman 

avformat: Support for AVChapters.

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

 modules/demux/avformat/demux.c |  121 +++++++++++++++++++++++++++++++++++++--
 1 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/modules/demux/avformat/demux.c b/modules/demux/avformat/demux.c
index 683c184..3c17ac4 100644
--- a/modules/demux/avformat/demux.c
+++ b/modules/demux/avformat/demux.c
@@ -35,6 +35,7 @@
 #include <vlc_stream.h>
 #include <vlc_meta.h>
 #include <vlc_input.h>
+#include <vlc_charset.h>
 
 /* ffmpeg header */
 #if defined(HAVE_LIBAVFORMAT_AVFORMAT_H)
@@ -56,6 +57,10 @@
 #   define HAVE_FFMPEG_CODEC_ATTACHMENT 1
 #endif
 
+#if (LIBAVFORMAT_VERSION_INT >= ((52<<16)+(15<<8)+0) )
+#   define HAVE_FFMPEG_CHAPTERS 1
+#endif
+
 /*****************************************************************************
  * demux_sys_t: demux descriptor
  *****************************************************************************/
@@ -79,6 +84,9 @@ struct demux_sys_t
 
     int                i_attachments;
     input_attachment_t **attachments;
+
+    /* Only one title with seekpoints possible atm. */
+    input_title_t *p_title;
 };
 
 /*****************************************************************************
@@ -90,6 +98,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args );
 static int IORead( void *opaque, uint8_t *buf, int buf_size );
 static offset_t IOSeek( void *opaque, offset_t offset, int whence );
 
+static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time );
+
 /*****************************************************************************
  * Open
  *****************************************************************************/
@@ -99,8 +109,9 @@ int OpenDemux( vlc_object_t *p_this )
     demux_sys_t   *p_sys;
     AVProbeData   pd;
     AVInputFormat *fmt;
-    unsigned int i;
-    bool b_avfmt_nofile;
+    unsigned int  i;
+    bool          b_avfmt_nofile;
+    int64_t       i_start_time = -1;
 
     /* Init Probe data */
     pd.filename = p_demux->psz_path;
@@ -163,6 +174,7 @@ int OpenDemux( vlc_object_t *p_this )
     p_sys->i_pcr_tk = -1;
     p_sys->i_pcr = -1;
     TAB_INIT( p_sys->i_attachments, p_sys->attachments);
+    p_sys->p_title = NULL;
 
     /* Create I/O wrapper */
     p_sys->io_buffer_size = 32768;  /* FIXME */
@@ -298,17 +310,37 @@ int OpenDemux( vlc_object_t *p_this )
                  psz_type, (char*)&fcc );
         TAB_APPEND( p_sys->i_tk, p_sys->tk, es );
     }
+    if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
+        i_start_time = p_sys->ic->start_time * 1000000 / AV_TIME_BASE;
 
     msg_Dbg( p_demux, "AVFormat supported stream" );
     msg_Dbg( p_demux, "    - format = %s (%s)",
              p_sys->fmt->name, p_sys->fmt->long_name );
-    msg_Dbg( p_demux, "    - start time = %"PRId64,
-             ( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ) ?
-             p_sys->ic->start_time * 1000000 / AV_TIME_BASE : -1 );
+    msg_Dbg( p_demux, "    - start time = %"PRId64, i_start_time );
     msg_Dbg( p_demux, "    - duration = %"PRId64,
              ( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE ) ?
              p_sys->ic->duration * 1000000 / AV_TIME_BASE : -1 );
 
+#if HAVE_FFMPEG_CHAPTERS
+    p_sys->p_title = vlc_input_title_New();
+    for( i = 0; i < p_sys->ic->nb_chapters; i++ )
+    {
+        seekpoint_t *s = vlc_seekpoint_New();
+
+        if( p_sys->ic->chapters[i]->title )
+        {
+            s->psz_name = strdup( p_sys->ic->chapters[i]->title );
+            EnsureUTF8( s->psz_name );
+            msg_Dbg( p_demux, "    - chapter %d: %s", i, s->psz_name );
+        }
+        s->i_time_offset = p_sys->ic->chapters[i]->start * 1000000 *
+            p_sys->ic->chapters[i]->time_base.num /
+            p_sys->ic->chapters[i]->time_base.den -
+            (i_start_time != -1 ? i_start_time : 0 );
+        TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
+    }
+#endif
+
     return VLC_SUCCESS;
 }
 
@@ -332,6 +364,9 @@ void CloseDemux( vlc_object_t *p_this )
         free( p_sys->attachments[i] );
     TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);
 
+    if( p_sys->p_title )
+        vlc_input_title_Delete( p_sys->p_title );
+
     free( p_sys->io_buffer );
     free( p_sys );
 }
@@ -397,10 +432,34 @@ static int Demux( demux_t *p_demux )
     }
 
     es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame );
+
+    UpdateSeekPoint( p_demux, p_sys->i_pcr);
     av_free_packet( &pkt );
     return 1;
 }
 
+static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time )
+{
+    demux_sys_t *p_sys = p_demux->p_sys;
+    int i;
+
+    if( !p_sys->p_title )
+        return;
+
+    for( i = 0; i < p_sys->p_title->i_seekpoint; i++ )
+    {
+        if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset )
+            break;
+    }
+    i--;
+
+    if( i != p_demux->info.i_seekpoint && i >= 0 )
+    {
+        p_demux->info.i_seekpoint = i;
+        p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+    }
+}
+
 /*****************************************************************************
  * Control:
  *****************************************************************************/
@@ -444,12 +503,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                     (av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0) )
                 {
                     int64_t i_size = stream_Size( p_demux->s );
-                    i64 = (int64_t)i_size * f;
 
                     msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
-                    if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
+                    if( av_seek_frame( p_sys->ic, -1, (i_size * f), AVSEEK_FLAG_BYTE ) < 0 )
                         return VLC_EGENERIC;
                 }
+                UpdateSeekPoint( p_demux, i64 );
                 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
                 p_sys->i_pcr = -1; /* Invalidate time display */
             }
@@ -483,6 +542,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
             p_sys->i_pcr = -1; /* Invalidate time display */
+            UpdateSeekPoint( p_demux, i64 );
             return VLC_SUCCESS;
 
         case DEMUX_GET_META:
@@ -526,6 +586,53 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             return VLC_SUCCESS;
         }
 
+        case DEMUX_GET_TITLE_INFO:
+        {
+            input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
+            int *pi_int    = (int*)va_arg( args, int* );
+            int *pi_title_offset = (int*)va_arg( args, int* );
+            int *pi_seekpoint_offset = (int*)va_arg( args, int* );
+
+            if( !p_sys->p_title )
+                return VLC_EGENERIC;
+
+            *pi_int = 1;
+            *ppp_title = malloc( sizeof( input_title_t**) );
+            (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
+            *pi_title_offset = 0;
+            *pi_seekpoint_offset = 0;
+            return VLC_SUCCESS;
+        }
+        case DEMUX_SET_TITLE:
+        {
+            const int i_title = (int)va_arg( args, int );
+            if( !p_sys->p_title || i_title != 0 )
+                return VLC_EGENERIC;
+            return VLC_SUCCESS;
+        }
+        case DEMUX_SET_SEEKPOINT:
+        {
+            const int i_seekpoint = (int)va_arg( args, int );
+            if( !p_sys->p_title )
+                return VLC_EGENERIC;
+
+            i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *AV_TIME_BASE / 1000000;
+            if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
+                i64 += p_sys->ic->start_time;
+
+            msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
+
+            if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
+            {
+                return VLC_EGENERIC;
+            }
+            es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
+            p_sys->i_pcr = -1; /* Invalidate time display */
+            UpdateSeekPoint( p_demux, i64 );
+            return VLC_SUCCESS;
+        }
+
+
         default:
             return VLC_EGENERIC;
     }




More information about the vlc-devel mailing list