[vlc-commits] demux: mp4: add WMV3/WMA2 in mov support

Francois Cartegnie git at videolan.org
Mon Oct 6 13:59:14 CEST 2014


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Oct  5 17:35:12 2014 +0200| [fe5fe6249b22f139a8302919a2279afbae083fe8] | committer: Francois Cartegnie

demux: mp4: add WMV3/WMA2 in mov support

aka flip4mac format.

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

 modules/demux/Makefile.am |    3 +-
 modules/demux/mp4/mp4.c   |  154 ++++++++++++++++++++++++++++++++++++++++++++-
 modules/demux/mp4/mp4.h   |    6 ++
 3 files changed, 161 insertions(+), 2 deletions(-)

diff --git a/modules/demux/Makefile.am b/modules/demux/Makefile.am
index 432c8b0..b2bf46d 100644
--- a/modules/demux/Makefile.am
+++ b/modules/demux/Makefile.am
@@ -191,7 +191,8 @@ EXTRA_LTLIBRARIES += libmkv_plugin.la
 
 libmp4_plugin_la_SOURCES = demux/mp4/mp4.c demux/mp4/mp4.h \
                            demux/mp4/libmp4.c demux/mp4/libmp4.h \
-                           demux/mp4/id3genres.h demux/mp4/languages.h
+                           demux/mp4/id3genres.h demux/mp4/languages.h \
+                           demux/asf/asfpacket.c demux/asf/asfpacket.h
 libmp4_plugin_la_LIBADD = $(LIBM)
 libmp4_plugin_la_LDFLAGS = $(AM_LDFLAGS)
 if HAVE_ZLIB
diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c
index 42c718d..eff7bf8 100644
--- a/modules/demux/mp4/mp4.c
+++ b/modules/demux/mp4/mp4.c
@@ -104,6 +104,12 @@ struct demux_sys_t
 
     /* */
     input_title_t *p_title;
+
+    /* ASF in MP4 */
+    asf_packet_sys_t asfpacketsys;
+    uint64_t i_preroll;         /* foobar */
+    int64_t  i_preroll_start;
+    mp4_track_t *p_current_track; /* avoids matching stream_number */
 };
 
 #define BOXDATA(type) type->data.type
@@ -145,6 +151,11 @@ static int LeafGetTrackAndChunkByMOOVPos( demux_t *p_demux, uint64_t *pi_pos,
                                       mp4_track_t **pp_tk, unsigned int *pi_chunk );
 static int LeafMapTrafTrunContextes( demux_t *p_demux, MP4_Box_t *p_moof );
 
+/* ASF Handlers */
+static asf_track_info_t * MP4ASF_GetTrackInfo( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number );
+static void MP4ASF_Send(asf_packet_sys_t *p_packetsys, uint8_t i_stream_number, block_t **pp_frame);
+static void MP4ASF_ResetFrames( demux_sys_t *p_sys );
+
 /* Helpers */
 
 static uint32_t stream_ReadU32( stream_t *s, void *p_read, uint32_t i_toread )
@@ -483,7 +494,26 @@ static void MP4_Block_Send( demux_t *p_demux, mp4_track_t *p_track, block_t *p_b
                              p_track->rgi_chans_reordering,
                              p_track->fmt.i_codec );
     }
-    es_out_Send( p_demux->out, p_track->p_es, p_block );
+
+    /* ASF packets in mov */
+    if( p_track->p_asf )
+    {
+        /* Fake a new stream from MP4 block */
+        stream_t *p_stream = p_demux->s;
+        p_demux->s = stream_MemoryNew( p_demux, p_block->p_buffer, p_block->i_buffer, true );
+        if ( p_demux->s )
+        {
+            p_track->i_dts_backup = p_block->i_dts;
+            p_track->i_pts_backup = p_block->i_pts;
+            /* And demux it as ASF packet */
+            DemuxASFPacket( &p_demux->p_sys->asfpacketsys, p_block->i_buffer, p_block->i_buffer );
+            stream_Delete(p_demux->s);
+        }
+        block_Release(p_block);
+        p_demux->s = p_stream;
+    }
+    else
+        es_out_Send( p_demux->out, p_track->p_es, p_block );
 }
 
 /*****************************************************************************
@@ -859,6 +889,15 @@ static int Open( vlc_object_t * p_this )
     /* */
     LoadChapter( p_demux );
 
+    p_sys->asfpacketsys.p_demux = p_demux;
+    p_sys->asfpacketsys.pi_preroll = &p_sys->i_preroll;
+    p_sys->asfpacketsys.pi_preroll_start = &p_sys->i_preroll_start;
+    p_sys->asfpacketsys.pf_doskip = NULL;
+    p_sys->asfpacketsys.pf_send = MP4ASF_Send;
+    p_sys->asfpacketsys.pf_gettrackinfo = MP4ASF_GetTrackInfo;
+    p_sys->asfpacketsys.pf_updatetime = NULL;
+    p_sys->asfpacketsys.pf_setaspectratio = NULL;
+
     return VLC_SUCCESS;
 
 error:
@@ -1118,6 +1157,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date )
     }
     MP4_UpdateSeekpoint( p_demux );
 
+    MP4ASF_ResetFrames( p_sys );
     es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_date );
 
     return VLC_SUCCESS;
@@ -1220,6 +1260,7 @@ static int LeafSeekToTime( demux_t *p_demux, mtime_t i_nztime )
             return VLC_EGENERIC;
     }
 
+    MP4ASF_ResetFrames( p_sys );
     /* And set next display time in that trun/fragment */
     es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, VLC_TS_0 + i_nztime );
     return VLC_SUCCESS;
@@ -2976,6 +3017,56 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
                 break;
             }
 
+            case ATOM_WMA2:
+            {
+                MP4_Box_t *p_WMA2 = MP4_BoxGet( p_sample, "wave/WMA2" );
+                if( p_WMA2 && BOXDATA(p_WMA2) )
+                {
+                    p_track->fmt.audio.i_channels = BOXDATA(p_WMA2)->Format.nChannels;
+                    p_track->fmt.audio.i_rate = BOXDATA(p_WMA2)->Format.nSamplesPerSec;
+                    p_track->fmt.i_bitrate = BOXDATA(p_WMA2)->Format.nAvgBytesPerSec * 8;
+                    p_track->fmt.audio.i_blockalign = BOXDATA(p_WMA2)->Format.nBlockAlign;
+                    p_track->fmt.audio.i_bitspersample = BOXDATA(p_WMA2)->Format.wBitsPerSample;
+                    p_track->fmt.i_extra = BOXDATA(p_WMA2)->i_extra;
+                    if( p_track->fmt.i_extra > 0 )
+                    {
+                        p_track->fmt.p_extra = malloc( BOXDATA(p_WMA2)->i_extra );
+                        memcpy( p_track->fmt.p_extra, BOXDATA(p_WMA2)->p_extra,
+                                p_track->fmt.i_extra );
+                    }
+                    p_track->p_asf = MP4_BoxGet( p_sample, "wave/ASF " );
+                }
+                else
+                {
+                    msg_Err( p_demux, "missing WMA2 %4.4s", (char*) &p_sample->p_father->i_type );
+                    assert(false);
+                }
+                break;
+            }
+
+            case ATOM_WMV3:
+            {
+                MP4_Box_t *p_strf = MP4_BoxGet(  p_sample, "strf", 0 );
+                if ( p_strf && BOXDATA(p_strf) )
+                {
+                    p_track->fmt.i_codec = VLC_CODEC_WMV3;
+                    p_track->fmt.video.i_width = BOXDATA(p_strf)->bmiHeader.biWidth;
+                    p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
+                    p_track->fmt.video.i_height = BOXDATA(p_strf)->bmiHeader.biHeight;
+                    p_track->fmt.video.i_visible_height =p_track->fmt.video.i_height;
+                    p_track->fmt.video.i_bits_per_pixel = BOXDATA(p_strf)->bmiHeader.biBitCount;
+                    p_track->fmt.i_extra = BOXDATA(p_strf)->i_extra;
+                    if( p_track->fmt.i_extra > 0 )
+                    {
+                        p_track->fmt.p_extra = malloc( BOXDATA(p_strf)->i_extra );
+                        memcpy( p_track->fmt.p_extra, BOXDATA(p_strf)->p_extra,
+                                p_track->fmt.i_extra );
+                    }
+                    p_track->p_asf = MP4_BoxGet( p_sample, "ASF " );
+                }
+                break;
+            }
+
             default:
                 msg_Dbg( p_demux, "Unrecognized FourCC %4.4s", (char *)&p_sample->i_type );
                 break;
@@ -3469,6 +3560,9 @@ static void MP4_TrackDestroy( mp4_track_t *p_track )
     {
         FREENULL( p_track->p_sample_size );
     }
+
+    if ( p_track->asfinfo.p_frame )
+        block_ChainRelease( p_track->asfinfo.p_frame );
 }
 
 static int MP4_TrackSelect( demux_t *p_demux, mp4_track_t *p_track,
@@ -5612,4 +5706,62 @@ static int DemuxAsLeaf( demux_t *p_demux )
     return 1;
 }
 
+/* ASF Handlers */
+inline static mp4_track_t *MP4ASF_GetTrack( asf_packet_sys_t *p_packetsys,
+                                            uint8_t i_stream_number )
+{
+    demux_sys_t *p_sys = p_packetsys->p_demux->p_sys;
+    for ( unsigned int i=0; i<p_sys->i_tracks; i++ )
+    {
+        if ( p_sys->track[i].p_asf &&
+             i_stream_number == p_sys->track[i].BOXDATA(p_asf)->i_stream_number )
+        {
+            return &p_sys->track[i];
+        }
+    }
+    return NULL;
+}
+
+static asf_track_info_t * MP4ASF_GetTrackInfo( asf_packet_sys_t *p_packetsys,
+                                               uint8_t i_stream_number )
+{
+    mp4_track_t *p_track = MP4ASF_GetTrack( p_packetsys, i_stream_number );
+    if ( p_track )
+        return &p_track->asfinfo;
+    else
+        return NULL;
+}
+
+static void MP4ASF_Send( asf_packet_sys_t *p_packetsys, uint8_t i_stream_number,
+                         block_t **pp_frame )
+{
+    mp4_track_t *p_track = MP4ASF_GetTrack( p_packetsys, i_stream_number );
+    if ( !p_track )
+    {
+        block_Release( *pp_frame );
+    }
+    else
+    {
+        block_t *p_gather = block_ChainGather( *pp_frame );
+        p_gather->i_dts = p_track->i_dts_backup;
+        p_gather->i_pts = p_track->i_pts_backup;
+        es_out_Send( p_packetsys->p_demux->out, p_track->p_es, p_gather );
+    }
+
+    *pp_frame = NULL;
+}
+
+static void MP4ASF_ResetFrames( demux_sys_t *p_sys )
+{
+    for ( unsigned int i=0; i<p_sys->i_tracks; i++ )
+    {
+        mp4_track_t *p_track = &p_sys->track[i];
+        if( p_track->asfinfo.p_frame )
+        {
+            block_ChainRelease( p_track->asfinfo.p_frame );
+            p_track->asfinfo.p_frame = NULL;
+        }
+    }
+}
+
 #undef BOXDATA
diff --git a/modules/demux/mp4/mp4.h b/modules/demux/mp4/mp4.h
index df95de9..da164e0 100644
--- a/modules/demux/mp4/mp4.h
+++ b/modules/demux/mp4/mp4.h
@@ -31,6 +31,7 @@
 
 #include <vlc_common.h>
 #include "libmp4.h"
+#include "../asf/asfpacket.h"
 
 /* Contain all information about a chunk */
 typedef struct
@@ -134,6 +135,11 @@ typedef struct
         uint64_t   i_traf_base_offset;
     } context;
 
+    /* ASF packets handling */
+    MP4_Box_t       *p_asf;
+    mtime_t          i_dts_backup;
+    mtime_t          i_pts_backup;
+    asf_track_info_t asfinfo;
 } mp4_track_t;
 
 typedef struct mp4_fragment_t mp4_fragment_t;



More information about the vlc-commits mailing list