[vlc-commits] demux: asf: decode payload extension

Francois Cartegnie git at videolan.org
Sat Dec 7 19:11:57 CET 2013


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Dec  2 13:49:38 2013 +0100| [c3ae02a6d43b05fae1dbba479206110f672ac544] | committer: Francois Cartegnie

demux: asf: decode payload extension

Reads keyframe flag from payload extensions.
Some formats like DVR-MS ships keyframe info into
payload extensions and not as packet flag. Why make things simple ?

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

 modules/demux/asf/asf.c    |   73 ++++++++++++++++++++++++++++++++++++++++++--
 modules/demux/asf/libasf.c |   35 ++++++++++++++++++---
 modules/demux/asf/libasf.h |   14 +++++++++
 3 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/modules/demux/asf/asf.c b/modules/demux/asf/asf.c
index 88648c1..d56d0d4 100644
--- a/modules/demux/asf/asf.c
+++ b/modules/demux/asf/asf.c
@@ -534,7 +534,8 @@ static void SendPacket(demux_t *p_demux, asf_track_t *tk)
 }
 
 static int DemuxSubPayload(demux_t *p_demux, asf_track_t *tk,
-        uint32_t i_sub_payload_data_length, mtime_t i_pts, mtime_t i_dts, uint32_t i_media_object_offset)
+        uint32_t i_sub_payload_data_length, mtime_t i_pts, mtime_t i_dts,
+        uint32_t i_media_object_offset, bool b_keyframe )
 {
     /* FIXME I don't use i_media_object_number, sould I ? */
     if( tk->p_frame && i_media_object_offset == 0 )
@@ -548,6 +549,8 @@ static int DemuxSubPayload(demux_t *p_demux, asf_track_t *tk,
 
     p_frag->i_pts = VLC_TS_0 + i_pts;
     p_frag->i_dts = VLC_TS_0 + i_dts;
+    if ( b_keyframe )
+        p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
 
     block_ChainAppend( &tk->p_frame, p_frag );
 
@@ -576,6 +579,66 @@ static uint32_t SkipBytes( stream_t *s, uint32_t i_bytes )
     return i_bytes_read;
 }
 
+static void ParsePayloadExtensions(demux_t *p_demux, asf_track_t *tk,
+                                   const struct asf_packet_t *pkt,
+                                   uint32_t i_length, bool *b_keyframe )
+{
+    if ( !tk || !tk->p_esp || !tk->p_esp->p_ext ) return;
+    const uint8_t *p_data = pkt->p_peek + pkt->i_skip + 8;
+    i_length -= 8;
+    uint16_t i_payload_extensions_size;
+    asf_payload_extension_system_t *p_ext = NULL;
+
+    /* Extensions always come in the declared order */
+    for ( int i=0; i< tk->p_esp->i_payload_extension_system_count; i++ )
+    {
+        asf_payload_extension_system_t *p_ext = &tk->p_esp->p_ext[i];
+        if ( p_ext->i_data_size == 0xFFFF ) /* Variable length extension data */
+        {
+            if ( i_length < 2 ) return;
+            i_payload_extensions_size = GetWLE( p_data );
+            p_data += 2;
+            i_length -= 2;
+            i_payload_extensions_size = 0;
+        }
+        else
+        {
+            i_payload_extensions_size = p_ext->i_data_size;
+        }
+
+        if ( i_length < i_payload_extensions_size ) return;
+
+        if ( guidcmp( &p_ext->i_extension_id, &mfasf_sampleextension_outputcleanpoint_guid ) )
+        {
+            if ( i_payload_extensions_size != sizeof(uint8_t) ) goto sizeerror;
+            *b_keyframe |= *p_data;
+        }
+        else if ( guidcmp( &p_ext->i_extension_id, &asf_dvr_sampleextension_videoframe_guid ) )
+        {
+            if ( i_payload_extensions_size != sizeof(uint32_t) ) goto sizeerror;
+
+            uint32_t i_val = GetDWLE( p_data );
+            /* Valid keyframe must be a split frame start fragment */
+            *b_keyframe = i_val & ASF_EXTENSION_VIDEOFRAME_NEWFRAME;
+            if ( *b_keyframe )
+            {
+                /* And flagged as IFRAME */
+                *b_keyframe |= ( ( i_val & ASF_EXTENSION_VIDEOFRAME_TYPE_MASK )
+                                 == ASF_EXTENSION_VIDEOFRAME_IFRAME );
+            }
+        }
+
+        i_length -= i_payload_extensions_size;
+        p_data += i_payload_extensions_size;
+    }
+
+    return;
+
+sizeerror:
+    msg_Warn( p_demux, "Unknown extension " GUID_FMT " data size of %u",
+              GUID_PRINT( p_ext->i_extension_id ), i_payload_extensions_size );
+}
+
 static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payload)
 {
 #ifndef ASF_DEBUG
@@ -605,6 +668,11 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
     if( i_replicated_data_length > 1 ) // should be at least 8 bytes
     {
         i_base_pts = (mtime_t)GetDWLE( pkt->p_peek + pkt->i_skip + 4 );
+
+        /* Parsing extensions, See 7.3.1 */
+        ParsePayloadExtensions( p_demux, p_sys->track[i_stream_number], pkt,
+                                i_replicated_data_length, &b_packet_keyframe );
+
         pkt->i_skip += i_replicated_data_length;
 
         if( ! pkt->left || pkt->i_skip >= pkt->left )
@@ -696,7 +764,8 @@ static int DemuxPayload(demux_t *p_demux, struct asf_packet_t *pkt, int i_payloa
 
         if ( i_sub_payload_data_length &&
              DemuxSubPayload(p_demux, tk, i_sub_payload_data_length,
-                        i_payload_pts, i_payload_dts, i_media_object_offset) < 0)
+                        i_payload_pts, i_payload_dts, i_media_object_offset,
+                        b_packet_keyframe ) < 0)
             return -1;
 
         if ( pkt->left > pkt->i_skip + i_sub_payload_data_length )
diff --git a/modules/demux/asf/libasf.c b/modules/demux/asf/libasf.c
index 6e19e47..dedb7c9 100644
--- a/modules/demux/asf/libasf.c
+++ b/modules/demux/asf/libasf.c
@@ -904,12 +904,28 @@ static int ASF_ReadObject_extended_stream_properties( stream_t *s,
     }
     p_esp->i_stream_name_count = i;
 
-    for( i = 0; i < p_esp->i_payload_extension_system_count; i++ )
+    p_esp->p_ext = calloc( p_esp->i_payload_extension_system_count,
+                           sizeof( asf_payload_extension_system_t ) );
+    if ( p_esp->p_ext )
     {
-        ASF_SKIP( 16 );   // GUID
-        ASF_SKIP( 2 );
-        ASF_SKIP( ASF_READ4() );
-    }
+        for( i = 0; i < p_esp->i_payload_extension_system_count; i++ )
+        {
+            asf_payload_extension_system_t *p_ext = & p_esp->p_ext[i];
+            if( !ASF_HAVE( 16+2+4 ) ) break;
+            ASF_GetGUID( &p_ext->i_extension_id, p_data );
+            ASF_SKIP( 16 );   // GUID
+            p_ext->i_data_size = ASF_READ2();
+            p_ext->i_info_length = ASF_READ4();
+            if ( p_ext->i_info_length )
+            {
+                if( !ASF_HAVE( p_ext->i_info_length ) ) break;
+                p_ext->pi_info = malloc( p_ext->i_info_length );
+                if ( p_ext->pi_info )
+                    memcpy( p_ext->pi_info, p_data, p_ext->i_info_length );
+                ASF_SKIP( p_ext->i_info_length );
+            }
+        }
+    } else p_esp->i_payload_extension_system_count = 0;
 
     p_esp->p_sp = NULL;
     if( p_data < &p_peek[i_peek] )
@@ -956,6 +972,9 @@ static int ASF_ReadObject_extended_stream_properties( stream_t *s,
                  p_esp->ppsz_stream_name[i] );
     msg_Dbg( s, "  - payload extension system count=%d",
              p_esp->i_payload_extension_system_count );
+    for( i = 0; i < p_esp->i_payload_extension_system_count; i++ )
+        msg_Dbg( s, "  - %d  - payload extension: " GUID_FMT, i,
+                 GUID_PRINT( p_esp->p_ext[i].i_extension_id ) );
 #endif
     return VLC_SUCCESS;
 }
@@ -963,6 +982,12 @@ static void ASF_FreeObject_extended_stream_properties( asf_object_t *p_obj)
 {
     asf_object_extended_stream_properties_t *p_esp = &p_obj->ext_stream;
 
+    if ( p_esp->p_ext )
+    {
+        for( int i = 0; i < p_esp->i_payload_extension_system_count; i++ )
+            free( p_esp->p_ext[i].pi_info );
+        FREENULL( p_esp->p_ext );
+    }
     for( int i = 0; i < p_esp->i_stream_name_count; i++ )
         FREENULL( p_esp->ppsz_stream_name[i] );
     FREENULL( p_esp->pi_stream_name_language );
diff --git a/modules/demux/asf/libasf.h b/modules/demux/asf/libasf.h
index 5271fec..59a2cb1 100644
--- a/modules/demux/asf/libasf.h
+++ b/modules/demux/asf/libasf.h
@@ -247,6 +247,18 @@ typedef struct
     } bitrate[128];
 } asf_object_stream_bitrate_properties_t;
 
+
+typedef struct
+{
+    guid_t   i_extension_id;
+    uint16_t i_data_size;
+    uint32_t i_info_length;
+    char     *pi_info;
+} asf_payload_extension_system_t;
+#define ASF_EXTENSION_VIDEOFRAME_NEWFRAME  0x08
+#define ASF_EXTENSION_VIDEOFRAME_IFRAME    0x01
+#define ASF_EXTENSION_VIDEOFRAME_TYPE_MASK 0x07
+
 typedef struct
 {
     ASF_OBJECT_COMMON
@@ -267,7 +279,9 @@ typedef struct
     int64_t i_average_time_per_frame;
 
     int     i_stream_name_count;
+
     int     i_payload_extension_system_count;
+    asf_payload_extension_system_t *p_ext;
 
     int     *pi_stream_name_language;
     char    **ppsz_stream_name;



More information about the vlc-commits mailing list