[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