[vlc-devel] [PATCH 1/2] added support for "quicktime reference" file.

Rajneesh Soni soni.rajneesh at gmail.com
Tue Sep 19 16:32:22 CEST 2017


ticket - https://trac.videolan.org/vlc/ticket/3073

Fixes as per suggestion from RĂ©mi Denis-Courmont

- demux.s is read only,
- track stream is deleted on track cleanup.

QuickTime reference movie allow the MDAT data to be located separately then the MOOV (header data),
This separatation allow fast editing of the file. DREF atom contains the location of the media data.
This location can be local file or a http/https location.Quicktime player 7 is able to play
such file but VLC fails to play.
This commit parse the dref atom and if the track data are in located separately.
it will launch a new stream to fetch the track data.
---
 modules/demux/mp4/mp4.c | 57 +++++++++++++++++++++++++++++++++++--------------
 modules/demux/mp4/mp4.h |  4 ++++
 2 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index f8b8d24..98987df 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -37,6 +37,7 @@
 #include <assert.h>
 #include <limits.h>
 #include "../codec/cc.h"
+#include "vlc_stream_extractor.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -65,7 +66,7 @@ vlc_module_end ()
  * Local prototypes
  *****************************************************************************/
 static int   Demux   ( demux_t * );
-static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
+//static int   DemuxRef( demux_t *p_demux ){ (void)p_demux; return 0;}
 static int   DemuxFrag( demux_t * );
 static int   Control ( demux_t *, int, va_list );
 
@@ -884,7 +885,7 @@ static int Open( vlc_object_t * p_this )
         else
         {
             msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" );
-            p_demux->pf_demux = DemuxRef;
+            p_demux->pf_demux = Demux ;//DemuxRef;
             return VLC_SUCCESS;
         }
     }
@@ -1205,6 +1206,7 @@ static int DemuxTrack( demux_t *p_demux, mp4_track_t *tk, uint64_t i_readpos,
 {
     uint32_t i_nb_samples = 0;
     uint32_t i_samplessize = 0;
+    stream_t *p_active_stream = p_demux->s;
 
     if( !tk->b_ok || tk->i_sample >= tk->i_sample_count )
         return VLC_DEMUXER_EOS;
@@ -1212,6 +1214,17 @@ static int DemuxTrack( demux_t *p_demux, mp4_track_t *tk, uint64_t i_readpos,
     if( tk->b_chapters_source )
         return VLC_DEMUXER_SUCCESS;
 
+    if( tk->b_is_dref && !tk->b_dref_started )
+    {
+         tk->s = vlc_stream_NewMRL(p_demux,tk->p_dref_url);
+         tk->b_dref_started = true;
+    }
+
+    if( tk->b_is_dref )
+    {
+            p_active_stream = tk->s;
+    }
+
     uint32_t i_run_seq = MP4_TrackGetRunSeq( tk );
     mtime_t i_current_nzdts = MP4_TrackGetDTS( p_demux, tk );
     const mtime_t i_demux_max_nzdts =(i_max_preload < UINT_MAX)
@@ -1235,9 +1248,9 @@ static int DemuxTrack( demux_t *p_demux, mp4_track_t *tk, uint64_t i_readpos,
             block_t *p_block;
             int64_t i_delta;
 
-            if( vlc_stream_Tell( p_demux->s ) != i_readpos )
+            if( vlc_stream_Tell( p_active_stream ) != i_readpos )
             {
-                if( MP4_Seek( p_demux->s, i_readpos ) != VLC_SUCCESS )
+                if( MP4_Seek( p_active_stream, i_readpos ) != VLC_SUCCESS )
                 {
                     msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)"
                                        ": Failed to seek to %"PRIu64,
@@ -1248,7 +1261,7 @@ static int DemuxTrack( demux_t *p_demux, mp4_track_t *tk, uint64_t i_readpos,
             }
 
             /* now read pes */
-            if( !(p_block = vlc_stream_Block( p_demux->s, i_samplessize )) )
+            if( !(p_block = vlc_stream_Block( p_active_stream, i_samplessize )) )
             {
                 msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)"
                                    ": Failed to read %d bytes sample at %"PRIu64,
@@ -1292,6 +1305,7 @@ static int DemuxTrack( demux_t *p_demux, mp4_track_t *tk, uint64_t i_readpos,
     return VLC_DEMUXER_SUCCESS;
 
 end:
+
     return VLC_DEMUXER_EGENERIC;
 }
 
@@ -3336,21 +3350,29 @@ static void MP4_TrackSetup( demux_t *p_demux, mp4_track_t *p_track,
         for( i = 0; i < elst->i_entry_count; i++ )
         {
             msg_Dbg( p_demux, "   - [%d] duration=%"PRId64"ms media time=%"PRId64
-                     "ms) rate=%d.%d", i,
-                     MP4_rescale( elst->i_segment_duration[i], p_sys->i_timescale, 1000 ),
-                     elst->i_media_time[i] >= 0 ?
-                        MP4_rescale( elst->i_media_time[i], p_track->i_timescale, 1000 ) :
-                        INT64_C(-1),
-                     elst->i_media_rate_integer[i],
-                     elst->i_media_rate_fraction[i] );
+                    "ms) rate=%d.%d", i,
+                    MP4_rescale( elst->i_segment_duration[i], p_sys->i_timescale, 1000 ),
+                    elst->i_media_time[i] >= 0 ?
+                    MP4_rescale( elst->i_media_time[i], p_track->i_timescale, 1000 ) :
+                    INT64_C(-1),
+                    elst->i_media_rate_integer[i],
+                    elst->i_media_rate_fraction[i] );
         }
     }
 
 
-/*  TODO
-    add support for:
-    p_dinf = MP4_BoxGet( p_minf, "dinf" );
-*/
+/*  extract the dinf url if applicable  */
+    MP4_Box_t *p_dref = MP4_BoxGet(p_box_trak, "mdia/minf/dinf/dref");
+    MP4_Box_t *p_url = MP4_BoxGet(p_dref, "url ");
+
+    if( p_url )
+    {
+      p_track->b_is_dref = true;
+      p_track->b_dref_started = false;
+      p_track->p_dref_url = strdup(BOXDATA(p_url)->psz_location);
+      msg_Dbg( p_demux," url in the vstub dref url = %s  \n",p_track->p_dref_url);
+    }
+
     if( !( p_track->p_stbl = MP4_BoxGet( p_box_trak,"mdia/minf/stbl" ) ) ||
         !( p_track->p_stsd = MP4_BoxGet( p_box_trak,"mdia/minf/stbl/stsd") ) )
     {
@@ -3513,6 +3535,9 @@ static void MP4_TrackClean( es_out_t *out, mp4_track_t *p_track )
     if ( p_track->asfinfo.p_frame )
         block_ChainRelease( p_track->asfinfo.p_frame );
 
+    if( p_track->b_is_dref && p_track->s )
+         vlc_stream_Delete( p_track->s );
+
     free( p_track->context.runs.p_array );
 }
 
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
index 99cb9bb..145bad6 100644
--- a/modules/demux/mp4/mp4.h
+++ b/modules/demux/mp4/mp4.h
@@ -164,6 +164,10 @@ typedef struct
         uint64_t i_trun_sample_pos;
 
     } context;
+    bool b_dref_started;
+    bool b_is_dref;
+    char *p_dref_url;
+    stream_t *s;
 
     /* ASF packets handling */
     const MP4_Box_t *p_asf;
-- 
2.7.4



More information about the vlc-devel mailing list