X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Freal.c;h=36084c689c036b253293e9ea6162d86104f22dc7;hb=fa81ade13492bab2a809e6c8990e211f04aecab8;hp=43a1bb21b64b159202fd158af6cc576cd3d78826;hpb=449fd28aaf007c6411251dae9d0dbfdc65b135d1;p=vlc diff --git a/modules/demux/real.c b/modules/demux/real.c index 43a1bb21b6..36084c689c 100644 --- a/modules/demux/real.c +++ b/modules/demux/real.c @@ -39,18 +39,20 @@ * * Real Audio Only * --------------- - * Not supported... + * v3 and v4/5 headers are parsed. + * Doesn't work yet... */ /***************************************************************************** * Preamble *****************************************************************************/ + #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include - +#include +#include #include #include @@ -63,8 +65,8 @@ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); vlc_module_begin(); - set_description( _("Real demuxer" ) ); - set_capability( "demux2", 15 ); + set_description( N_("Real demuxer" ) ); + set_capability( "demux", 15 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); set_callbacks( Open, Close ); @@ -94,10 +96,18 @@ typedef struct int i_subpacket; int i_subpackets; block_t **p_subpackets; + int64_t *p_subpackets_timecode; int i_out_subpacket; } real_track_t; +typedef struct +{ + uint32_t file_offset; + uint32_t time_offset; + uint32_t frame_index; +} rm_index_t; + struct demux_sys_t { int64_t i_data_offset; @@ -106,6 +116,8 @@ struct demux_sys_t uint32_t i_data_packets; int64_t i_data_offset_next; + bool b_is_real_audio; + int i_our_duration; int i_mux_rate; @@ -120,12 +132,18 @@ struct demux_sys_t uint8_t buffer[65536]; int64_t i_pcr; + vlc_meta_t *p_meta; + + int64_t i_index_offset; + int b_seek; + rm_index_t *p_index; }; static int Demux( demux_t *p_demux ); static int Control( demux_t *p_demux, int i_query, va_list args ); static int HeaderRead( demux_t *p_demux ); +static const uint8_t * MetaRead( demux_t *p_demux, const uint8_t *p_peek ); static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ); /***************************************************************************** @@ -137,14 +155,18 @@ static int Open( vlc_object_t *p_this ) demux_sys_t *p_sys; const uint8_t *p_peek; + bool b_is_real_audio = false; if( stream_Peek( p_demux->s, &p_peek, 10 ) < 10 ) return VLC_EGENERIC; + + /* Real Audio */ if( !memcmp( p_peek, ".ra", 3 ) ) { - msg_Warn( p_demux, ".ra files unsuported" ); - return VLC_EGENERIC; + msg_Err( p_demux, ".ra files unsuported" ); + b_is_real_audio = true; } - if( memcmp( p_peek, ".RMF", 4 ) ) return VLC_EGENERIC; + /* Real Media Format */ + else if( memcmp( p_peek, ".RMF", 4 ) ) return VLC_EGENERIC; /* Fill p_demux field */ p_demux->pf_demux = Demux; @@ -152,9 +174,8 @@ static int Open( vlc_object_t *p_this ) p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); if( p_sys == NULL ) - { return VLC_ENOMEM; - } + memset( p_sys, 0, sizeof( demux_sys_t ) ); p_sys->i_data_offset = 0; @@ -162,9 +183,19 @@ static int Open( vlc_object_t *p_this ) p_sys->track = NULL; p_sys->i_pcr = 1; + p_sys->b_seek = 0; + p_sys->b_is_real_audio = b_is_real_audio; /* Parse the headers */ - if( HeaderRead( p_demux ) ) + /* Real Audio files */ + if( b_is_real_audio ) + { + ReadCodecSpecificData( p_demux, 32, 0 ); /* At least 32 */ + return VLC_EGENERIC; /* We don't know how to read + correctly the data yet */ + } + /* RMF files */ + else if( HeaderRead( p_demux ) ) { int i; msg_Err( p_demux, "invalid header" ); @@ -211,7 +242,11 @@ static void Close( vlc_object_t *p_this ) if( tk->p_subpackets[ j ] ) block_Release( tk->p_subpackets[ j ] ); } - if( tk->i_subpackets ) free( tk->p_subpackets ); + if( tk->i_subpackets ) + { + free( tk->p_subpackets ); + free( tk->p_subpackets_timecode ); + } free( tk ); } @@ -220,6 +255,7 @@ static void Close( vlc_object_t *p_this ) free( p_sys->psz_artist ); free( p_sys->psz_copyright ); free( p_sys->psz_description ); + free( p_sys->p_index ); if( p_sys->i_track > 0 ) free( p_sys->track ); free( p_sys ); @@ -262,16 +298,15 @@ static int Demux( demux_t *p_demux ) if( stream_Read( p_demux->s, header, 12 ) < 12 ) return 0; + // int i_version = GetWBE( &header[0] ); i_size = GetWBE( &header[2] ) - 12; i_id = GetWBE( &header[4] ); i_pts = 1000 * GetDWBE( &header[6] ); i_pts += 1000; /* Avoid 0 pts */ i_flags= header[11]; /* flags 0x02 -> keyframe */ -#if 0 msg_Dbg( p_demux, "packet %d size=%d id=%d pts=%u", p_sys->i_data_packets, i_size, i_id, (uint32_t)(i_pts/1000) ); -#endif p_sys->i_data_packets++; @@ -366,7 +401,7 @@ static int Demux( demux_t *p_demux ) ( tk->p_frame->i_dts != i_pts || tk->i_frame != i_len ) ) { - msg_Dbg( p_demux, "sending size=%d", tk->p_frame->i_buffer ); + msg_Dbg( p_demux, "sending size=%zu", tk->p_frame->i_buffer ); es_out_Send( p_demux->out, tk->p_es, tk->p_frame ); @@ -515,22 +550,37 @@ static int Demux( demux_t *p_demux ) int i_index, i; /* Sanity check */ - if( i_flags & 2 ) y = tk->i_subpacket = 0; + if( i_flags & 2 || ( p_sys->b_seek ) ) + { + y = tk->i_subpacket = 0; + tk->i_out_subpacket = 0; + p_sys->b_seek = 0; + } if( tk->fmt.i_codec == VLC_FOURCC( 'c', 'o', 'o', 'k' ) || tk->fmt.i_codec == VLC_FOURCC( 'a', 't', 'r', 'c' )) - for( i = 0; i < tk->i_frame_size / tk->i_subpacket_size; i++ ) { - block_t *p_block = block_New( p_demux, tk->i_subpacket_size ); - memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size ); - p_buf += tk->i_subpacket_size; + int num = tk->i_frame_size / tk->i_subpacket_size; + for( i = 0; i < num; i++ ) + { + block_t *p_block = block_New( p_demux, tk->i_subpacket_size ); + memcpy( p_block->p_buffer, p_buf, tk->i_subpacket_size ); + p_buf += tk->i_subpacket_size; - i_index = tk->i_subpacket_h * i + - ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1); + i_index = tk->i_subpacket_h * i + + ((tk->i_subpacket_h + 1) / 2) * (y&1) + (y>>1); - p_block->i_dts = p_block->i_pts = i_pts; - tk->p_subpackets[i_index] = p_block; - tk->i_subpacket++; + if ( tk->p_subpackets[i_index] != NULL ) + { + msg_Dbg(p_demux, "p_subpackets[ %d ] not null!", i_index ); + free( tk->p_subpackets[i_index] ); + } + + tk->p_subpackets[i_index] = p_block; + tk->i_subpacket++; + p_block->i_dts = p_block->i_pts = 0; + } + tk->p_subpackets_timecode[tk->i_subpacket - num] = i_pts; } if( tk->fmt.i_codec == VLC_FOURCC( '2', '8', '_', '8' ) || @@ -553,6 +603,7 @@ static int Demux( demux_t *p_demux ) tk->p_subpackets[tk->i_out_subpacket] ) { /* Set the PCR */ +#if 0 if (tk->i_out_subpacket == 0) { p_sys->i_pcr = tk->p_subpackets[tk->i_out_subpacket]->i_dts; @@ -564,6 +615,20 @@ static int Demux( demux_t *p_demux ) tk->p_subpackets[tk->i_out_subpacket] = 0; if( tk->i_out_subpacket ) p_block->i_dts = p_block->i_pts = 0; +#endif + + block_t *p_block = tk->p_subpackets[tk->i_out_subpacket]; + tk->p_subpackets[tk->i_out_subpacket] = 0; + if ( tk->p_subpackets_timecode[tk->i_out_subpacket] ) + { + p_block->i_dts = p_block->i_pts = + tk->p_subpackets_timecode[tk->i_out_subpacket]; + tk->p_subpackets_timecode[tk->i_out_subpacket] = 0; + + p_sys->i_pcr = p_block->i_dts; + es_out_Control( p_demux->out, ES_OUT_SET_PCR, + (int64_t)p_sys->i_pcr ); + } es_out_Send( p_demux->out, tk->p_es, p_block ); tk->i_out_subpacket++; @@ -652,21 +717,28 @@ static int Demux( demux_t *p_demux ) static int Control( demux_t *p_demux, int i_query, va_list args ) { demux_sys_t *p_sys = p_demux->p_sys; -#if 0 double f, *pf; int64_t i64; -#endif + rm_index_t * p_index; int64_t *pi64; switch( i_query ) { -#if 0 case DEMUX_GET_POSITION: pf = (double*) va_arg( args, double* ); + + if( p_sys->i_our_duration > 0 ) + { + *pf = (double)p_sys->i_pcr / 1000.0 / p_sys->i_our_duration; + return VLC_SUCCESS; + } + + /* read stream size maybe failed in rtsp streaming, + so use duration to determin the position at first */ i64 = stream_Size( p_demux->s ); if( i64 > 0 ) { - *pf = (double)stream_Tell( p_demux->s ) / (double)i64; + *pf = (double)1.0*stream_Tell( p_demux->s ) / (double)i64; } else { @@ -674,24 +746,90 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } return VLC_SUCCESS; - case DEMUX_SET_POSITION: - f = (double) va_arg( args, double ); - i64 = stream_Size( p_demux->s ); - - es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); - - return stream_Seek( p_demux->s, (int64_t)(i64 * f) ); - case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); - if( p_sys->i_mux_rate > 0 ) + + if( p_sys->i_our_duration > 0 ) { - *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate; + *pi64 = p_sys->i_pcr; return VLC_SUCCESS; } + + /* same as GET_POSTION */ + i64 = stream_Size( p_demux->s ); + if( p_sys->i_our_duration > 0 && i64 > 0 ) + { + *pi64 = (int64_t)( 1000.0 * p_sys->i_our_duration * stream_Tell( p_demux->s ) / i64 ); + return VLC_SUCCESS; + } + *pi64 = 0; return VLC_EGENERIC; -#endif + + case DEMUX_SET_POSITION: + f = (double) va_arg( args, double ); + i64 = (int64_t) ( stream_Size( p_demux->s ) * f ); + + if ( p_sys->i_index_offset == 0 && i64 != 0 ) + { + msg_Err(p_demux,"Seek No Index Real File failed!" ); + return VLC_EGENERIC; // no index! + } + if ( i64 == 0 ) + { + /* it is a rtsp stream , it is specials in access/rtsp/... */ + msg_Dbg(p_demux, "Seek in real rtsp stream!"); + p_sys->i_pcr = (int64_t)1000 * ( p_sys->i_our_duration * f ); + + es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr ); + p_sys->b_seek = 1; + + return stream_Seek( p_demux->s, p_sys->i_pcr ); + } + + if ( p_sys->i_index_offset > 0 ) + { + p_index = p_sys->p_index; + while( p_index->file_offset !=0 ) + { + if ( p_index->file_offset > i64 ) + { + msg_Dbg( p_demux, "Seek Real find! %d %d %d", + p_index->time_offset, p_index->file_offset, + (uint32_t) i64 ); + if ( p_index != p_sys->p_index ) p_index --; + i64 = p_index->file_offset; + break; + } + p_index++; + } + + p_sys->i_pcr = 1000 * (int64_t) p_index->time_offset; + + es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr ); + + return stream_Seek( p_demux->s, i64 ); + } + case DEMUX_SET_TIME: + i64 = (int64_t) va_arg( args, int64_t ) / 1000; + + p_index = p_sys->p_index; + while( p_index->file_offset !=0 ) + { + if ( p_index->time_offset > i64 ) + { + if ( p_index != p_sys->p_index ) + p_index --; + i64 = p_index->file_offset; + break; + } + p_index++; + } + + p_sys->i_pcr = 1000 * (int64_t) p_index->time_offset; + es_out_Control( p_demux->out, ES_OUT_RESET_PCR , p_sys->i_pcr ); + + return stream_Seek( p_demux->s, i64 ); case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); @@ -730,7 +868,6 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) return VLC_SUCCESS; } - case DEMUX_SET_TIME: case DEMUX_GET_FPS: default: return VLC_EGENERIC; @@ -738,6 +875,83 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) return VLC_EGENERIC; } +/***************************************************************************** + * ReadRealIndex: + *****************************************************************************/ + +static void ReadRealIndex( demux_t *p_demux ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + uint8_t buffer[100]; + uint32_t i_id; + uint32_t i_size; + int i_version; + unsigned int i; + + uint32_t i_index_count; + + if ( p_sys->i_index_offset == 0 ) + return; + + stream_Seek( p_demux->s, p_sys->i_index_offset ); + + if ( stream_Read( p_demux->s, buffer, 20 ) < 20 ) + return ; + + i_id = VLC_FOURCC( buffer[0], buffer[1], buffer[2], buffer[3] ); + i_size = GetDWBE( &buffer[4] ); + i_version = GetWBE( &buffer[8] ); + + msg_Dbg( p_demux, "Real index %4.4s size=%d version=%d", + (char*)&i_id, i_size, i_version ); + + if( (i_size < 20) && (i_id != VLC_FOURCC('I','N','D','X')) ) + return; + + i_index_count = GetDWBE( &buffer[10] ); + + msg_Dbg( p_demux, "Real Index : num : %d ", i_index_count ); + + if( i_index_count == 0 ) + return; + + if( GetDWBE( &buffer[16] ) > 0 ) + msg_Dbg( p_demux, "Real Index: Does next index exist? %d ", + GetDWBE( &buffer[16] ) ); + + p_sys->p_index = + (rm_index_t *)malloc( sizeof( rm_index_t ) * (i_index_count+1) ); + if( p_sys->p_index == NULL ) + { + msg_Err( p_demux, "Memory allocation error" ); + return; + } + + memset( p_sys->p_index, 0, sizeof(rm_index_t) * (i_index_count+1) ); + + for( i=0; is, buffer, 14 ) < 14 ) + return ; + + if( GetWBE( &buffer[0] ) != 0 ) + { + msg_Dbg( p_demux, "Real Index: invaild version of index entry %d ", + GetWBE( &buffer[0] ) ); + return; + } + + p_sys->p_index[i].time_offset = GetDWBE( &buffer[2] ); + p_sys->p_index[i].file_offset = GetDWBE( &buffer[6] ); + p_sys->p_index[i].frame_index = GetDWBE( &buffer[10] ); + msg_Dbg( p_demux, "Real Index: time %d file %d frame %d ", + p_sys->p_index[i].time_offset, + p_sys->p_index[i].file_offset, + p_sys->p_index[i].frame_index ); + + } +} + /***************************************************************************** * HeaderRead: *****************************************************************************/ @@ -750,6 +964,7 @@ static int HeaderRead( demux_t *p_demux ) uint32_t i_size; int64_t i_skip; int i_version; + p_sys->p_meta = vlc_meta_New(); for( ;; ) { @@ -800,6 +1015,8 @@ static int HeaderRead( demux_t *p_demux ) /* set the duration for export in control */ p_sys->i_our_duration = (int)GetDWBE(&header[20]); + p_sys->i_index_offset = GetDWBE(&header[28]); + i_flags = GetWBE(&header[38]); msg_Dbg( p_demux, " - flags=0x%x %s%s%s", i_flags, @@ -957,9 +1174,84 @@ static int HeaderRead( demux_t *p_demux ) /* TODO read index if possible */ + if ( p_sys->i_index_offset > 0 ) + { + int64_t pos; + pos = stream_Tell( p_demux->s ); + ReadRealIndex( p_demux ); + stream_Seek( p_demux->s, pos ); + } + return VLC_SUCCESS; } +static const uint8_t * MetaRead( demux_t *p_demux, const uint8_t *p_peek ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + + int i_len; + char *psz; + + /* Title */ + i_len = *p_peek ; p_peek++; + if( i_len > 0 ) + { + psz = malloc( i_len + 1 ); + memcpy( psz, p_peek, i_len ); + psz[i_len] = '\0'; + + EnsureUTF8( psz ); + msg_Dbg( p_demux, " - title=`%s'", psz ); + p_sys->psz_title = psz; + } + p_peek += i_len; + + /* Authors */ + i_len = *p_peek ; p_peek++; + if( i_len > 0 ) + { + psz = malloc( i_len + 1 ); + memcpy( psz, p_peek, i_len ); + psz[i_len] = '\0'; + + EnsureUTF8( psz ); + msg_Dbg( p_demux, " - artist=`%s'", psz ); + p_sys->psz_artist = psz; + } + p_peek += i_len; + + /* Copyright */ + i_len = *p_peek ; p_peek++; + if( i_len > 0 ) + { + psz = malloc( i_len + 1 ); + memcpy( psz, p_peek, i_len ); + psz[i_len] = '\0'; + + EnsureUTF8( psz ); + msg_Dbg( p_demux, " - Copyright=`%s'", psz ); + p_sys->psz_copyright = psz; + } + p_peek += i_len; + + /* Comment */ + i_len = *p_peek ; p_peek++; + if( i_len > 0 ) + { + psz = malloc( i_len + 1 ); + memcpy( psz, p_peek, i_len ); + psz[i_len] = '\0'; + + EnsureUTF8( psz ); + msg_Dbg( p_demux, " - Comment=`%s'", psz ); + p_sys->psz_description = psz; + } + p_peek += i_len; + + return p_peek; +} + + static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) { demux_sys_t *p_sys = p_demux->p_sys; @@ -1013,6 +1305,7 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) tk->i_subpacket = 0; tk->i_subpackets = 0; tk->p_subpackets = NULL; + tk->p_subpackets_timecode = NULL; tk->i_id = i_num; tk->fmt = fmt; tk->i_frame = 0; @@ -1023,8 +1316,12 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) } else if( !strncmp( (char *)p_peek, ".ra\xfd", 4 ) ) { - int i_header_size, i_flavor, i_coded_frame_size, i_subpacket_h; - int i_frame_size, i_subpacket_size; + int i_header_size = 0; + int i_flavor = 0; + int i_coded_frame_size = 0; + int i_subpacket_h = 0; + int i_frame_size = 0; + int i_subpacket_size = 0; char p_genr[4]; int i_version = GetWBE( &p_peek[4] ); /* [0..3] = '.','r','a',0xfd */ msg_Dbg( p_demux, " - audio version=%d", i_version ); @@ -1032,77 +1329,20 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) p_peek += 6; /* 4 + version */ es_format_Init( &fmt, AUDIO_ES, 0 ); - if( i_version == 3 ) + if( i_version == 3 ) /* RMF version 3 or .ra version 3 */ { - int i_len; - char *psz; - i_header_size = GetWBE( p_peek ); p_peek += 2; /* Size from now */ p_peek += 10; /* Unknown */ + msg_Dbg( p_demux, "Data Size: %i", GetDWBE( p_peek ) ); p_peek += 4; /* Data Size */ - /* Title */ - i_len = *p_peek ; p_peek++; - if( i_len > 0 ) - { - psz = malloc( i_len + 1 ); - memcpy( psz, p_peek, i_len ); - psz[i_len] = '\0'; + /* Meta Datas */ + p_peek = MetaRead( p_demux, p_peek ); - EnsureUTF8( psz ); - msg_Dbg( p_demux, " - title=`%s'", psz ); - p_sys->psz_title = psz; - } - p_peek += i_len; - - /* Authors */ - i_len = *p_peek ; p_peek++; - if( i_len > 0 ) - { - psz = malloc( i_len + 1 ); - memcpy( psz, p_peek, i_len ); - psz[i_len] = '\0'; - - EnsureUTF8( psz ); - msg_Dbg( p_demux, " - artist=`%s'", psz ); - p_sys->psz_artist = psz; - } - p_peek += i_len; - - /* Copyright */ - i_len = *p_peek ; p_peek++; - if( i_len > 0 ) - { - psz = malloc( i_len + 1 ); - memcpy( psz, p_peek, i_len ); - psz[i_len] = '\0'; - - EnsureUTF8( psz ); - msg_Dbg( p_demux, " - Copyright=`%s'", psz ); - p_sys->psz_copyright = psz; - } - p_peek += i_len; - - /* Comment */ - i_len = *p_peek ; p_peek++; - if( i_len > 0 ) - { - psz = malloc( i_len + 1 ); - memcpy( psz, p_peek, i_len ); - psz[i_len] = '\0'; - - EnsureUTF8( psz ); - msg_Dbg( p_demux, " - Comment=`%s'", psz ); - p_sys->psz_description = psz; - } - /* This might be unusefull */ - p_peek += i_len; - - p_peek ++; /* Unknown */ - p_peek ++; /* FourCC length = 4 */ - memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4; - /* Up to here :) */ + p_peek ++; /* Unknown */ + p_peek ++; /* FourCC length = 4 */ + memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4; /* FourCC*/ fmt.audio.i_channels = 1; /* This is always the case in rm3 */ fmt.audio.i_rate = 8000; @@ -1110,12 +1350,12 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) msg_Dbg( p_demux, " - audio codec=%4.4s channels=%d rate=%dHz", (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate ); } - else /* RMF version 4/5 */ + else /* RMF version 4/5 or .ra version 4 */ { - p_peek += 2; /* 00 00 */ - p_peek += 4; /* .ra4 or .ra5 */ - p_peek += 4; /* data size */ - p_peek += 2; /* version (4 or 5) */ + p_peek += 2; /* 00 00 */ + p_peek += 4; /* .ra4 or .ra5 */ + p_peek += 4; /* data size */ + p_peek += 2; /* version (4 or 5) */ i_header_size = GetDWBE( p_peek ); p_peek += 4; /* header size */ i_flavor = GetWBE( p_peek ); p_peek += 2; /* codec flavor */ i_coded_frame_size = GetDWBE( p_peek ); p_peek += 4; /* coded frame size*/ @@ -1125,14 +1365,15 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) i_subpacket_h = GetWBE( p_peek ); p_peek += 2; /* 1 */ i_frame_size = GetWBE( p_peek ); p_peek += 2; /* frame size */ i_subpacket_size = GetWBE( p_peek ); p_peek += 2; /* subpacket_size */ - if( !i_subpacket_size || !i_frame_size || !i_coded_frame_size ) + if( (!i_subpacket_size && !p_sys->b_is_real_audio ) + || !i_frame_size || !i_coded_frame_size ) return VLC_EGENERIC; p_peek += 2; /* ?? */ if( i_version == 5 ) p_peek += 6; /* 0, srate, 0 */ - fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2; /* Sample Rate */ - p_peek += 2; /* ?? */ + fmt.audio.i_rate = GetWBE( p_peek ); p_peek += 2; /* Sample Rate */ + p_peek += 2; /* ?? */ fmt.audio.i_bitspersample = GetWBE( p_peek ); p_peek += 2;/* Sure?*/ fmt.audio.i_channels = GetWBE( p_peek ); p_peek += 2; /* Channels */ fmt.audio.i_blockalign = i_frame_size; @@ -1142,30 +1383,36 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) memcpy( (char *)p_genr, p_peek, 4 ); p_peek += 4; /* genr */ memcpy( (char *)&fmt.i_codec, p_peek, 4 ); p_peek += 4; } - else + else /* version 4 */ { - p_peek += p_peek[0] + 1; /* descr 1 */ - memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 ); /* descr 2 */ - p_peek += p_peek[0] + 1; + p_peek += 1 + p_peek[0]; /* Inteleaver ID string and lenth */ + memcpy( (char *)&fmt.i_codec, p_peek + 1, 4 ); /* FourCC */ + p_peek += 1 + p_peek[0]; } msg_Dbg( p_demux, " - audio codec=%4.4s channels=%d rate=%dHz", (char*)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate ); p_peek += 3; /* ?? */ - if( i_version == 5 ) p_peek++; - /* Extra Data then: DWord + byte[] */ - fmt.i_extra = GetDWBE( p_peek ); p_peek += 4; + + if( p_sys->b_is_real_audio ) + { + p_peek = MetaRead( p_demux, p_peek ); + } + else + { + if( i_version == 5 ) p_peek++; + /* Extra Data then: DWord + byte[] */ + fmt.i_extra = GetDWBE( p_peek ); p_peek += 4; + } } switch( fmt.i_codec ) { - case VLC_FOURCC('1','4','_','4'): - /* fmt.audio.i_blockalign = 0x14 */ - break; case VLC_FOURCC('l','p','c','J'): - /* fmt.audio.i_blockalign = 0x14 */ fmt.i_codec = VLC_FOURCC( '1','4','_','4' ); + case VLC_FOURCC('1','4','_','4'): + fmt.audio.i_blockalign = 0x14 ; break; case VLC_FOURCC('2','8','_','8'): @@ -1245,6 +1492,7 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) tk->i_subpacket = 0; tk->i_subpackets = 0; tk->p_subpackets = NULL; + tk->p_subpackets_timecode = NULL; if( fmt.i_codec == VLC_FOURCC('c','o','o','k') || fmt.i_codec == VLC_FOURCC('a','t','r','c') ) { @@ -1252,6 +1500,8 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) i_subpacket_h * i_frame_size / tk->i_subpacket_size; tk->p_subpackets = calloc( tk->i_subpackets, sizeof(block_t *) ); + tk->p_subpackets_timecode = + calloc( tk->i_subpackets , sizeof( int64_t ) ); } else if( fmt.i_codec == VLC_FOURCC('2','8','_','8') ) { @@ -1259,6 +1509,8 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) i_subpacket_h * i_frame_size / tk->i_coded_frame_size; tk->p_subpackets = calloc( tk->i_subpackets, sizeof(block_t *) ); + tk->p_subpackets_timecode = + calloc( tk->i_subpackets , sizeof( int64_t ) ); } /* Check if the calloc went correctly */ @@ -1277,3 +1529,4 @@ static int ReadCodecSpecificData( demux_t *p_demux, int i_len, int i_num ) return VLC_SUCCESS; } +