1 /*****************************************************************************
2 * asf.c : ASF demux module
3 *****************************************************************************
4 * Copyright © 2002-2004, 2006-2008, 2010 VLC authors and VideoLAN
6 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_demux.h>
34 #include <vlc_dialog.h>
36 #include <vlc_meta.h> /* vlc_meta_Set*, vlc_meta_New */
37 #include <vlc_access.h> /* GET_PRIVATE_ID_STATE */
38 #include <vlc_codecs.h> /* VLC_BITMAPINFOHEADER, WAVEFORMATEX */
39 #include <vlc_input.h>
44 #include "asfpacket.h"
49 * - add support for the newly added object: language, bitrate,
50 * extended stream properties.
53 /*****************************************************************************
55 *****************************************************************************/
56 static int Open ( vlc_object_t
* );
57 static void Close ( vlc_object_t
* );
60 set_category( CAT_INPUT
)
61 set_subcategory( SUBCAT_INPUT_DEMUX
)
62 set_description( N_("ASF/WMV demuxer") )
63 set_capability( "demux", 200 )
64 set_callbacks( Open
, Close
)
65 add_shortcut( "asf", "wmv" )
69 /*****************************************************************************
71 *****************************************************************************/
72 static int Demux ( demux_t
* );
73 static int Control( demux_t
*, int i_query
, va_list args
);
75 #define MAX_ASF_TRACKS (ASF_MAX_STREAMNUMBER + 1)
76 #define ASF_PREROLL_FROM_CURRENT -1
78 /* callbacks for packet parser */
79 static void Packet_UpdateTime( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
,
81 static void Packet_SetSendTime( asf_packet_sys_t
*p_packetsys
, mtime_t i_time
);
82 static bool Block_Dequeue( demux_t
*p_demux
, mtime_t i_nexttime
);
83 static asf_track_info_t
* Packet_GetTrackInfo( asf_packet_sys_t
*p_packetsys
,
84 uint8_t i_stream_number
);
85 static bool Packet_DoSkip( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
, bool b_packet_keyframe
);
86 static void Packet_Enqueue( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
, block_t
**pp_frame
);
87 static void Packet_SetAR( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
,
88 uint8_t i_ratio_x
, uint8_t i_ratio_y
);
95 es_format_t
*p_fmt
; /* format backup for video changes */
98 mtime_t i_time
; /* track time*/
100 asf_track_info_t info
;
112 mtime_t i_time
; /* s */
114 mtime_t i_length
; /* length of file file */
115 uint64_t i_bitrate
; /* global file bitrate */
116 bool b_eos
; /* end of current stream */
117 bool b_eof
; /* end of current media */
119 asf_object_root_t
*p_root
;
120 asf_object_file_properties_t
*p_fp
;
122 unsigned int i_track
;
123 asf_track_t
*track
[MAX_ASF_TRACKS
]; /* track number is stored on 7 bits */
125 uint64_t i_data_begin
;
130 uint8_t i_seek_track
;
131 uint8_t i_access_selected_track
[ES_CATEGORY_COUNT
]; /* mms, depends on access algorithm */
132 unsigned int i_wait_keyframe
;
134 mtime_t i_preroll_start
;
136 asf_packet_sys_t packet_sys
;
141 static int DemuxInit( demux_t
* );
142 static void DemuxEnd( demux_t
* );
144 static void FlushQueue( asf_track_t
* );
145 static void FlushQueues( demux_t
*p_demux
);
147 /*****************************************************************************
148 * Open: check file and initializes ASF structures
149 *****************************************************************************/
150 static int Open( vlc_object_t
* p_this
)
152 demux_t
*p_demux
= (demux_t
*)p_this
;
155 const uint8_t *p_peek
;
157 /* A little test to see if it could be a asf stream */
158 if( vlc_stream_Peek( p_demux
->s
, &p_peek
, 16 ) < 16 ) return VLC_EGENERIC
;
160 ASF_GetGUID( &guid
, p_peek
);
161 if( !guidcmp( &guid
, &asf_object_header_guid
) ) return VLC_EGENERIC
;
163 /* Set p_demux fields */
164 p_demux
->pf_demux
= Demux
;
165 p_demux
->pf_control
= Control
;
166 p_demux
->p_sys
= p_sys
= calloc( 1, sizeof( demux_sys_t
) );
168 /* Load the headers */
169 if( DemuxInit( p_demux
) )
175 p_sys
->packet_sys
.p_demux
= p_demux
;
176 p_sys
->packet_sys
.pf_doskip
= Packet_DoSkip
;
177 p_sys
->packet_sys
.pf_send
= Packet_Enqueue
;
178 p_sys
->packet_sys
.pf_gettrackinfo
= Packet_GetTrackInfo
;
179 p_sys
->packet_sys
.pf_updatetime
= Packet_UpdateTime
;
180 p_sys
->packet_sys
.pf_updatesendtime
= Packet_SetSendTime
;
181 p_sys
->packet_sys
.pf_setaspectratio
= Packet_SetAR
;
186 /*****************************************************************************
187 * Demux: read packet and send them to decoders
188 *****************************************************************************/
189 #define CHUNK (CLOCK_FREQ / 10)
190 static int Demux( demux_t
*p_demux
)
192 demux_sys_t
*p_sys
= p_demux
->p_sys
;
194 for( int i
=0; i
<ES_CATEGORY_COUNT
; i
++ )
196 if ( p_sys
->i_access_selected_track
[i
] > 0 )
198 es_out_Control( p_demux
->out
, ES_OUT_SET_ES_STATE
,
199 p_sys
->track
[p_sys
->i_access_selected_track
[i
]]->p_es
, true );
200 p_sys
->i_access_selected_track
[i
] = 0;
204 /* Get selected tracks, especially for computing PCR */
205 for( int i
=0; i
<MAX_ASF_TRACKS
; i
++ )
207 asf_track_t
*tk
= p_sys
->track
[i
];
210 es_out_Control( p_demux
->out
, ES_OUT_GET_ES_STATE
, tk
->p_es
, & tk
->b_selected
);
212 tk
->b_selected
= false;
215 while( !p_sys
->b_eos
&& ( p_sys
->i_sendtime
- p_sys
->i_time
- CHUNK
< 0 ||
216 ( p_sys
->i_sendtime
- p_sys
->i_time
- CHUNK
) /
217 UINT64_C( 1000 ) < p_sys
->p_fp
->i_preroll
) )
219 /* Read and demux a packet */
220 if( DemuxASFPacket( &p_sys
->packet_sys
,
221 p_sys
->p_fp
->i_min_data_packet_size
,
222 p_sys
->p_fp
->i_max_data_packet_size
) <= 0 )
225 /* Check if we have concatenated files */
226 const uint8_t *p_peek
;
227 if( vlc_stream_Peek( p_demux
->s
, &p_peek
, 16 ) == 16 )
231 ASF_GetGUID( &guid
, p_peek
);
232 p_sys
->b_eof
= !guidcmp( &guid
, &asf_object_header_guid
);
234 msg_Warn( p_demux
, "found a new ASF header" );
240 if ( p_sys
->i_time
== -1 )
241 p_sys
->i_time
= p_sys
->i_sendtime
;
244 if( p_sys
->b_eos
|| ( p_sys
->i_sendtime
- p_sys
->i_time
- CHUNK
>= 0 &&
245 ( p_sys
->i_sendtime
- p_sys
->i_time
- CHUNK
) /
246 UINT64_C( 1000 ) >= p_sys
->p_fp
->i_preroll
) )
248 bool b_data
= Block_Dequeue( p_demux
, p_sys
->i_time
+ CHUNK
);
250 p_sys
->i_time
+= CHUNK
;
251 es_out_SetPCR( p_demux
->out
, VLC_TS_0
+ p_sys
->i_time
);
253 msg_Dbg( p_demux
, "Demux Loop Setting PCR to %"PRId64
, VLC_TS_0
+ p_sys
->i_time
);
255 if ( !b_data
&& p_sys
->b_eos
)
257 /* We end this stream */
262 /* And we prepare to read the next one */
263 if( DemuxInit( p_demux
) )
265 msg_Err( p_demux
, "failed to load the new header" );
266 vlc_dialog_display_error( p_demux
,
267 _("Could not demux ASF stream"), "%s",
268 _("VLC failed to load the ASF header.") );
269 return VLC_DEMUXER_EOF
;
271 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
274 return VLC_DEMUXER_EOF
;
281 /*****************************************************************************
282 * Close: frees unused data
283 *****************************************************************************/
284 static void Close( vlc_object_t
* p_this
)
286 demux_t
*p_demux
= (demux_t
*)p_this
;
290 free( p_demux
->p_sys
);
293 /*****************************************************************************
294 * WaitKeyframe: computes the number of frames to wait for a keyframe
295 *****************************************************************************/
296 static void WaitKeyframe( demux_t
*p_demux
)
298 demux_sys_t
*p_sys
= p_demux
->p_sys
;
299 if ( ! p_sys
->i_seek_track
)
301 for ( int i
=0; i
<MAX_ASF_TRACKS
; i
++ )
303 asf_track_t
*tk
= p_sys
->track
[i
];
304 if ( tk
&& tk
->info
.p_sp
&& tk
->i_cat
== VIDEO_ES
&& tk
->b_selected
)
306 p_sys
->i_seek_track
= tk
->info
.p_sp
->i_stream_number
;
312 if ( p_sys
->i_seek_track
)
314 /* Skip forward at least 1 min */
315 asf_track_t
*tk
= p_sys
->track
[p_sys
->i_seek_track
];
316 if ( tk
->info
.p_esp
&& tk
->info
.p_esp
->i_average_time_per_frame
)
318 /* 1 min if fastseek, otherwise 5 sec */
319 /* That's a guess for bandwidth */
320 uint64_t i_maxwaittime
= ( p_sys
->b_canfastseek
) ? 600000000 : 50000000;
321 i_maxwaittime
/= tk
->info
.p_esp
->i_average_time_per_frame
;
322 p_sys
->i_wait_keyframe
= __MIN( i_maxwaittime
, UINT_MAX
);
326 p_sys
->i_wait_keyframe
= ( p_sys
->b_canfastseek
) ? 25 * 30 : 25 * 5;
331 p_sys
->i_wait_keyframe
= 0;
336 /*****************************************************************************
337 * SeekIndex: goto to i_date or i_percent
338 *****************************************************************************/
339 static int SeekPercent( demux_t
*p_demux
, int i_query
, va_list args
)
341 demux_sys_t
*p_sys
= p_demux
->p_sys
;
343 WaitKeyframe( p_demux
);
345 msg_Dbg( p_demux
, "seek with percent: waiting %i frames", p_sys
->i_wait_keyframe
);
346 return demux_vaControlHelper( p_demux
->s
, __MIN( INT64_MAX
, p_sys
->i_data_begin
),
347 __MIN( INT64_MAX
, p_sys
->i_data_end
),
348 __MIN( INT64_MAX
, p_sys
->i_bitrate
),
349 __MIN( INT16_MAX
, p_sys
->p_fp
->i_min_data_packet_size
),
353 static int SeekIndex( demux_t
*p_demux
, mtime_t i_date
, float f_pos
)
355 demux_sys_t
*p_sys
= p_demux
->p_sys
;
356 asf_object_index_t
*p_index
;
358 msg_Dbg( p_demux
, "seek with index: %i seconds, position %f",
359 i_date
>= 0 ? (int)(i_date
/1000000) : -1, f_pos
);
362 i_date
= p_sys
->i_length
* f_pos
;
364 p_sys
->i_preroll_start
= i_date
- (int64_t) p_sys
->p_fp
->i_preroll
;
365 if ( p_sys
->i_preroll_start
< 0 ) p_sys
->i_preroll_start
= 0;
367 p_index
= ASF_FindObject( p_sys
->p_root
, &asf_object_simple_index_guid
, 0 );
369 uint64_t i_entry
= p_sys
->i_preroll_start
* 10 / p_index
->i_index_entry_time_interval
;
370 if( i_entry
>= p_index
->i_index_entry_count
)
372 msg_Warn( p_demux
, "Incomplete index" );
376 WaitKeyframe( p_demux
);
378 uint64_t i_offset
= (uint64_t)p_index
->index_entry
[i_entry
].i_packet_number
*
379 p_sys
->p_fp
->i_min_data_packet_size
;
381 if ( vlc_stream_Seek( p_demux
->s
, i_offset
+ p_sys
->i_data_begin
) == VLC_SUCCESS
)
383 es_out_Control( p_demux
->out
, ES_OUT_SET_NEXT_DISPLAY_TIME
, VLC_TS_0
+ i_date
);
386 else return VLC_EGENERIC
;
389 static void SeekPrepare( demux_t
*p_demux
)
391 demux_sys_t
*p_sys
= p_demux
->p_sys
;
393 p_sys
->b_eof
= false;
394 p_sys
->b_eos
= false;
396 p_sys
->i_sendtime
= -1;
397 p_sys
->i_preroll_start
= ASFPACKET_PREROLL_FROM_CURRENT
;
399 for( int i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
401 asf_track_t
*tk
= p_sys
->track
[i
];
409 es_out_Control( p_demux
->out
, ES_OUT_RESET_PCR
);
412 /*****************************************************************************
414 *****************************************************************************/
415 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
417 demux_sys_t
*p_sys
= p_demux
->p_sys
;
425 case DEMUX_GET_LENGTH
:
426 pi64
= va_arg( args
, int64_t * );
427 *pi64
= p_sys
->i_length
;
431 pi64
= va_arg( args
, int64_t * );
432 if( p_sys
->i_time
< 0 ) return VLC_EGENERIC
;
433 *pi64
= p_sys
->i_time
;
438 ! ( p_sys
->p_fp
->i_flags
& ASF_FILE_PROPERTIES_SEEKABLE
) )
441 SeekPrepare( p_demux
);
443 if( p_sys
->b_index
&& p_sys
->i_length
> 0 )
446 va_copy( acpy
, args
);
447 i64
= va_arg( acpy
, int64_t );
450 if( !SeekIndex( p_demux
, i64
, -1 ) )
453 return SeekPercent( p_demux
, i_query
, args
);
457 i
= va_arg( args
, int );
461 msg_Dbg( p_demux
, "Requesting access to enable stream %d", i
);
462 i_ret
= vlc_stream_Control( p_demux
->s
,
463 STREAM_SET_PRIVATE_ID_STATE
, i
, true );
466 { /* i contains -1 * es_category */
467 msg_Dbg( p_demux
, "Requesting access to disable stream %d", i
);
468 i_ret
= vlc_stream_Control( p_demux
->s
,
469 STREAM_SET_PRIVATE_ID_STATE
, i
,
473 if ( i_ret
== VLC_SUCCESS
)
478 tk
= p_sys
->track
[i
];
482 for( int j
= 0; j
< MAX_ASF_TRACKS
; j
++ )
484 tk
= p_sys
->track
[j
];
485 if( !tk
|| !tk
->p_fmt
|| tk
->i_cat
!= -1 * i
)
492 p_sys
->i_seek_track
= 0;
493 if ( ( tk
&& tk
->i_cat
== VIDEO_ES
) || i
== -1 * VIDEO_ES
)
494 WaitKeyframe( p_demux
);
499 case DEMUX_GET_POSITION
:
500 if( p_sys
->i_time
< 0 ) return VLC_EGENERIC
;
501 if( p_sys
->i_length
> 0 )
503 pf
= va_arg( args
, double * );
504 *pf
= p_sys
->i_time
/ (double)p_sys
->i_length
;
507 return demux_vaControlHelper( p_demux
->s
,
508 __MIN( INT64_MAX
, p_sys
->i_data_begin
),
509 __MIN( INT64_MAX
, p_sys
->i_data_end
),
510 __MIN( INT64_MAX
, p_sys
->i_bitrate
),
511 __MIN( INT16_MAX
, p_sys
->p_fp
->i_min_data_packet_size
),
514 case DEMUX_SET_POSITION
:
516 ! ( p_sys
->p_fp
->i_flags
& ASF_FILE_PROPERTIES_SEEKABLE
) )
519 SeekPrepare( p_demux
);
521 if( p_sys
->b_index
&& p_sys
->i_length
> 0 )
524 va_copy( acpy
, args
);
525 f
= va_arg( acpy
, double );
528 if( !SeekIndex( p_demux
, -1, f
) )
531 return SeekPercent( p_demux
, i_query
, args
);
534 p_meta
= va_arg( args
, vlc_meta_t
* );
535 vlc_meta_Merge( p_meta
, p_sys
->meta
);
540 ! ( p_sys
->p_fp
->i_flags
& ASF_FILE_PROPERTIES_SEEKABLE
) )
542 bool *pb_bool
= va_arg( args
, bool * );
548 return demux_vaControlHelper( p_demux
->s
,
549 __MIN( INT64_MAX
, p_sys
->i_data_begin
),
550 __MIN( INT64_MAX
, p_sys
->i_data_end
),
551 __MIN( INT64_MAX
, p_sys
->i_bitrate
),
552 ( p_sys
->p_fp
) ? __MIN( INT_MAX
, p_sys
->p_fp
->i_min_data_packet_size
) : 1,
557 /*****************************************************************************
559 *****************************************************************************/
560 static void Packet_SetAR( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
,
561 uint8_t i_ratio_x
, uint8_t i_ratio_y
)
563 demux_t
*p_demux
= p_packetsys
->p_demux
;
564 demux_sys_t
*p_sys
= p_demux
->p_sys
;
565 asf_track_t
*tk
= p_sys
->track
[i_stream_number
];
567 if ( !tk
->p_fmt
|| (tk
->p_fmt
->video
.i_sar_num
== i_ratio_x
&& tk
->p_fmt
->video
.i_sar_den
== i_ratio_y
) )
570 /* Only apply if origin pixel size >= 1x1, due to broken yacast */
571 if ( tk
->p_fmt
->video
.i_height
* i_ratio_x
> tk
->p_fmt
->video
.i_width
* i_ratio_y
)
573 vout_thread_t
*p_vout
= input_GetVout( p_demux
->p_input
);
576 msg_Info( p_demux
, "Changing aspect ratio to %i/%i", i_ratio_x
, i_ratio_y
);
577 vout_ChangeAspectRatio( p_vout
, i_ratio_x
, i_ratio_y
);
578 vlc_object_release( p_vout
);
581 tk
->p_fmt
->video
.i_sar_num
= i_ratio_x
;
582 tk
->p_fmt
->video
.i_sar_den
= i_ratio_y
;
585 static void Packet_SetSendTime( asf_packet_sys_t
*p_packetsys
, mtime_t i_time
)
587 demux_t
*p_demux
= p_packetsys
->p_demux
;
588 demux_sys_t
*p_sys
= p_demux
->p_sys
;
590 p_sys
->i_sendtime
= i_time
;
593 static void Packet_UpdateTime( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
,
596 demux_t
*p_demux
= p_packetsys
->p_demux
;
597 demux_sys_t
*p_sys
= p_demux
->p_sys
;
598 asf_track_t
*tk
= p_sys
->track
[i_stream_number
];
604 static asf_track_info_t
* Packet_GetTrackInfo( asf_packet_sys_t
*p_packetsys
,
605 uint8_t i_stream_number
)
607 demux_t
*p_demux
= p_packetsys
->p_demux
;
608 demux_sys_t
*p_sys
= p_demux
->p_sys
;
609 asf_track_t
*tk
= p_sys
->track
[i_stream_number
];
617 static bool Packet_DoSkip( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
, bool b_packet_keyframe
)
619 demux_t
*p_demux
= p_packetsys
->p_demux
;
620 demux_sys_t
*p_sys
= p_demux
->p_sys
;
621 const asf_track_t
*tk
= p_sys
->track
[i_stream_number
];
625 msg_Warn( p_demux
, "undeclared stream[Id 0x%x]", i_stream_number
);
629 if( p_sys
->i_wait_keyframe
)
631 if ( i_stream_number
== p_sys
->i_seek_track
)
633 if ( !b_packet_keyframe
)
635 p_sys
->i_wait_keyframe
--;
639 p_sys
->i_wait_keyframe
= 0;
651 static void Packet_Enqueue( asf_packet_sys_t
*p_packetsys
, uint8_t i_stream_number
, block_t
**pp_frame
)
653 demux_t
*p_demux
= p_packetsys
->p_demux
;
654 demux_sys_t
*p_sys
= p_demux
->p_sys
;
655 asf_track_t
*tk
= p_sys
->track
[i_stream_number
];
659 block_t
*p_gather
= block_ChainGather( *pp_frame
);
662 block_ChainLastAppend( & tk
->queue
.pp_last
, p_gather
);
664 msg_Dbg( p_demux
, " enqueue packet dts %"PRId64
" pts %"PRId64
" pcr %"PRId64
, p_gather
->i_dts
, p_gather
->i_pts
, p_sys
->i_time
);
671 static bool Block_Dequeue( demux_t
*p_demux
, mtime_t i_nexttime
)
673 demux_sys_t
*p_sys
= p_demux
->p_sys
;
674 bool b_tracks_have_data
= false;
675 for( int i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
677 asf_track_t
*tk
= p_sys
->track
[i
];
680 b_tracks_have_data
|= (tk
->queue
.p_first
!= NULL
);
681 while( tk
->queue
.p_first
&& tk
->queue
.p_first
->i_dts
<= i_nexttime
)
683 block_t
*p_block
= tk
->queue
.p_first
;
684 tk
->queue
.p_first
= p_block
->p_next
;
685 if( tk
->queue
.p_first
== NULL
)
686 tk
->queue
.pp_last
= &tk
->queue
.p_first
;
688 p_block
->p_next
= NULL
;
690 if( p_sys
->i_time
< VLC_TS_0
)
692 es_out_SetPCR( p_demux
->out
, VLC_TS_0
+ p_sys
->i_time
);
694 msg_Dbg( p_demux
, " dequeue setting PCR to %"PRId64
, VLC_TS_0
+ p_sys
->i_time
);
699 msg_Dbg( p_demux
, " sending packet dts %"PRId64
" pts %"PRId64
" pcr %"PRId64
, p_block
->i_dts
, p_block
->i_pts
, p_sys
->i_time
);
701 es_out_Send( p_demux
->out
, tk
->p_es
, p_block
);
704 return b_tracks_have_data
;
707 /*****************************************************************************
709 *****************************************************************************/
710 typedef struct asf_es_priorities_t
712 uint16_t *pi_stream_numbers
;
714 } asf_es_priorities_t
;
716 /* Fills up our exclusion list */
717 static void ASF_fillup_es_priorities_ex( demux_sys_t
*p_sys
, void *p_hdr
,
718 asf_es_priorities_t
*p_prios
)
720 /* Find stream exclusions */
721 asf_object_advanced_mutual_exclusion_t
*p_mutex
=
722 ASF_FindObject( p_hdr
, &asf_object_advanced_mutual_exclusion
, 0 );
723 if (! p_mutex
) return;
725 #if ( UINT_MAX > SIZE_MAX / 2 )
726 if ( p_sys
->i_track
> (size_t)SIZE_MAX
/ sizeof(uint16_t) )
729 p_prios
->pi_stream_numbers
= vlc_alloc( p_sys
->i_track
, sizeof(uint16_t) );
730 if ( !p_prios
->pi_stream_numbers
) return;
732 if ( p_mutex
->i_stream_number_count
)
734 /* Just set highest prio on highest in the group */
735 for ( uint16_t i
= 1; i
< p_mutex
->i_stream_number_count
; i
++ )
737 if ( p_prios
->i_count
> p_sys
->i_track
|| i
> p_sys
->i_track
) break;
738 p_prios
->pi_stream_numbers
[ p_prios
->i_count
++ ] = p_mutex
->pi_stream_number
[ i
];
743 /* Fills up our bitrate exclusion list */
744 static void ASF_fillup_es_bitrate_priorities_ex( demux_sys_t
*p_sys
, void *p_hdr
,
745 asf_es_priorities_t
*p_prios
)
747 /* Find bitrate exclusions */
748 asf_object_bitrate_mutual_exclusion_t
*p_bitrate_mutex
=
749 ASF_FindObject( p_hdr
, &asf_object_bitrate_mutual_exclusion_guid
, 0 );
750 if (! p_bitrate_mutex
) return;
752 #if ( UINT_MAX > SIZE_MAX / 2 )
753 if ( p_sys
->i_track
> (size_t)SIZE_MAX
/ sizeof(uint16_t) )
756 p_prios
->pi_stream_numbers
= vlc_alloc( p_sys
->i_track
, sizeof( uint16_t ) );
757 if ( !p_prios
->pi_stream_numbers
) return;
759 if ( p_bitrate_mutex
->i_stream_number_count
)
761 /* Just remove < highest */
762 for ( uint16_t i
= 1; i
< p_bitrate_mutex
->i_stream_number_count
; i
++ )
764 if ( p_prios
->i_count
> p_sys
->i_track
|| i
> p_sys
->i_track
) break;
765 p_prios
->pi_stream_numbers
[ p_prios
->i_count
++ ] = p_bitrate_mutex
->pi_stream_numbers
[ i
];
771 #define GET_CHECKED( target, getter, maxtarget, temp ) \
773 temp i_temp = getter;\
774 if ( i_temp > maxtarget ) {\
775 msg_Warn( p_demux, "rejecting stream %u : " #target " overflow", i_stream );\
776 es_format_Clean( &fmt );\
783 static int DemuxInit( demux_t
*p_demux
)
785 demux_sys_t
*p_sys
= p_demux
->p_sys
;
789 p_sys
->i_sendtime
= -1;
791 p_sys
->b_eos
= false;
792 p_sys
->b_eof
= false;
793 p_sys
->i_bitrate
= 0;
794 p_sys
->p_root
= NULL
;
798 p_sys
->i_seek_track
= 0;
799 p_sys
->i_wait_keyframe
= 0;
800 for( int i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
802 p_sys
->track
[i
] = NULL
;
804 p_sys
->i_data_begin
= 0;
805 p_sys
->i_data_end
= 0;
806 p_sys
->i_preroll_start
= 0;
809 /* Now load all object ( except raw data ) */
810 vlc_stream_Control( p_demux
->s
, STREAM_CAN_FASTSEEK
,
811 &p_sys
->b_canfastseek
);
812 if( !(p_sys
->p_root
= ASF_ReadObjectRoot(p_demux
->s
, p_sys
->b_canfastseek
)) )
814 msg_Warn( p_demux
, "ASF plugin discarded (not a valid file)" );
817 p_sys
->p_fp
= p_sys
->p_root
->p_fp
;
819 if( p_sys
->p_fp
->i_min_data_packet_size
!= p_sys
->p_fp
->i_max_data_packet_size
)
821 msg_Warn( p_demux
, "ASF plugin discarded (invalid file_properties object)" );
825 if ( ASF_FindObject( p_sys
->p_root
->p_hdr
,
826 &asf_object_content_encryption_guid
, 0 ) != NULL
827 || ASF_FindObject( p_sys
->p_root
->p_hdr
,
828 &asf_object_extended_content_encryption_guid
, 0 ) != NULL
829 || ASF_FindObject( p_sys
->p_root
->p_hdr
,
830 &asf_object_advanced_content_encryption_guid
, 0 ) != NULL
)
832 vlc_dialog_display_error( p_demux
, _("Could not demux ASF stream"), "%s",
833 ("DRM protected streams are not supported.") );
837 p_sys
->i_track
= ASF_CountObject( p_sys
->p_root
->p_hdr
,
838 &asf_object_stream_properties_guid
);
839 if( p_sys
->i_track
== 0 )
841 msg_Warn( p_demux
, "ASF plugin discarded (cannot find any stream!)" );
844 msg_Dbg( p_demux
, "found %u streams", p_sys
->i_track
);
846 /* check if index is available */
847 asf_object_index_t
*p_index
= ASF_FindObject( p_sys
->p_root
,
848 &asf_object_simple_index_guid
, 0 );
849 const bool b_index
= p_index
&& p_index
->i_index_entry_count
;
851 /* Find the extended header if any */
852 asf_object_t
*p_hdr_ext
= ASF_FindObject( p_sys
->p_root
->p_hdr
,
853 &asf_object_header_extension_guid
, 0 );
855 asf_object_language_list_t
*p_languages
= NULL
;
856 asf_es_priorities_t fmt_priorities_ex
= { NULL
, 0 };
857 asf_es_priorities_t fmt_priorities_bitrate_ex
= { NULL
, 0 };
861 p_languages
= ASF_FindObject( p_hdr_ext
, &asf_object_language_list
, 0 );
863 ASF_fillup_es_priorities_ex( p_sys
, p_hdr_ext
, &fmt_priorities_ex
);
864 ASF_fillup_es_bitrate_priorities_ex( p_sys
, p_hdr_ext
, &fmt_priorities_bitrate_ex
);
867 const bool b_mms
= !strncasecmp( p_demux
->psz_url
, "mms:", 4 );
868 bool b_dvrms
= false;
872 es_out_Control( p_demux
->out
, ES_OUT_SET_ES_CAT_POLICY
,
873 VIDEO_ES
, ES_OUT_ES_POLICY_EXCLUSIVE
);
876 for( unsigned i_stream
= 0; i_stream
< p_sys
->i_track
; i_stream
++ )
879 asf_object_stream_properties_t
*p_sp
;
880 asf_object_extended_stream_properties_t
*p_esp
;
881 bool b_access_selected
;
883 p_sp
= ASF_FindObject( p_sys
->p_root
->p_hdr
,
884 &asf_object_stream_properties_guid
,
888 tk
= p_sys
->track
[p_sp
->i_stream_number
] = malloc( sizeof( asf_track_t
) );
891 memset( tk
, 0, sizeof( asf_track_t
) );
894 tk
->info
.p_sp
= p_sp
;
896 tk
->info
.p_esp
= NULL
;
897 tk
->info
.p_frame
= NULL
;
898 tk
->info
.i_cat
= UNKNOWN_ES
;
899 tk
->queue
.p_first
= NULL
;
900 tk
->queue
.pp_last
= &tk
->queue
.p_first
;
904 /* Check (not mms) if this track is selected (ie will receive data) */
905 if( !vlc_stream_Control( p_demux
->s
, STREAM_GET_PRIVATE_ID_STATE
,
906 (int) p_sp
->i_stream_number
,
907 &b_access_selected
) &&
910 tk
->i_cat
= UNKNOWN_ES
;
911 msg_Dbg( p_demux
, "ignoring not selected stream(ID:%u) (by access)",
912 p_sp
->i_stream_number
);
917 /* Find the associated extended_stream_properties if any */
920 int i_ext_stream
= ASF_CountObject( p_hdr_ext
,
921 &asf_object_extended_stream_properties_guid
);
922 for( int i
= 0; i
< i_ext_stream
; i
++ )
924 asf_object_t
*p_tmp
=
925 ASF_FindObject( p_hdr_ext
,
926 &asf_object_extended_stream_properties_guid
, i
);
927 if( p_tmp
->ext_stream
.i_stream_number
== p_sp
->i_stream_number
)
929 p_esp
= &p_tmp
->ext_stream
;
930 tk
->info
.p_esp
= p_esp
;
936 /* Check for DVR-MS */
938 for( uint16_t i
=0; i
<p_esp
->i_payload_extension_system_count
&& !b_dvrms
; i
++ )
939 b_dvrms
= guidcmp( &p_esp
->p_ext
[i
].i_extension_id
, &asf_dvr_sampleextension_timing_rep_data_guid
);
943 if( guidcmp( &p_sp
->i_stream_type
, &asf_object_stream_type_audio
) &&
944 p_sp
->i_type_specific_data_length
>= sizeof( WAVEFORMATEX
) - 2 )
946 uint8_t *p_data
= p_sp
->p_type_specific_data
;
949 es_format_Init( &fmt
, AUDIO_ES
, 0 );
950 i_format
= GetWLE( &p_data
[0] );
951 wf_tag_to_fourcc( i_format
, &fmt
.i_codec
, NULL
);
953 GET_CHECKED( fmt
.audio
.i_channels
, GetWLE( &p_data
[2] ),
955 GET_CHECKED( fmt
.audio
.i_rate
, GetDWLE( &p_data
[4] ),
956 UINT_MAX
, uint32_t );
957 GET_CHECKED( fmt
.i_bitrate
, GetDWLE( &p_data
[8] ) * 8,
958 UINT_MAX
, uint32_t );
959 fmt
.audio
.i_blockalign
= GetWLE( &p_data
[12] );
960 fmt
.audio
.i_bitspersample
= GetWLE( &p_data
[14] );
962 if( p_sp
->i_type_specific_data_length
> sizeof( WAVEFORMATEX
) &&
963 i_format
!= WAVE_FORMAT_MPEGLAYER3
&&
964 i_format
!= WAVE_FORMAT_MPEG
)
966 GET_CHECKED( fmt
.i_extra
, __MIN( GetWLE( &p_data
[16] ),
967 p_sp
->i_type_specific_data_length
-
968 sizeof( WAVEFORMATEX
) ),
970 fmt
.p_extra
= malloc( fmt
.i_extra
);
971 memcpy( fmt
.p_extra
, &p_data
[sizeof( WAVEFORMATEX
)],
974 msg_Dbg( p_demux
, "added new audio stream (codec:%4.4s(0x%x),ID:%d)",
975 (char*)&fmt
.i_codec
, GetWLE( p_data
), p_sp
->i_stream_number
);
977 else if( guidcmp( &p_sp
->i_stream_type
,
978 &asf_object_stream_type_video
) &&
979 p_sp
->i_type_specific_data_length
>= 11 +
980 sizeof( VLC_BITMAPINFOHEADER
) )
982 uint8_t *p_data
= &p_sp
->p_type_specific_data
[11];
984 es_format_Init( &fmt
, VIDEO_ES
,
985 VLC_FOURCC( p_data
[16], p_data
[17],
986 p_data
[18], p_data
[19] ) );
988 GET_CHECKED( fmt
.video
.i_width
, GetDWLE( p_data
+ 4 ),
989 UINT_MAX
, uint32_t );
990 GET_CHECKED( fmt
.video
.i_height
, GetDWLE( p_data
+ 8 ),
991 UINT_MAX
, uint32_t );
992 fmt
.video
.i_visible_width
= fmt
.video
.i_width
;
993 fmt
.video
.i_visible_height
= fmt
.video
.i_height
;
995 if( p_esp
&& p_esp
->i_average_time_per_frame
> 0 )
997 fmt
.video
.i_frame_rate
= 10000000;
998 GET_CHECKED( fmt
.video
.i_frame_rate_base
,
999 p_esp
->i_average_time_per_frame
,
1000 UINT_MAX
, uint64_t );
1003 if( fmt
.i_codec
== VLC_FOURCC( 'D','V','R',' ') )
1005 /* DVR-MS special ASF */
1006 fmt
.i_codec
= VLC_CODEC_MPGV
;
1009 if( p_sp
->i_type_specific_data_length
> 11 +
1010 sizeof( VLC_BITMAPINFOHEADER
) )
1012 GET_CHECKED( fmt
.i_extra
, __MIN( GetDWLE( p_data
),
1013 p_sp
->i_type_specific_data_length
- 11 -
1014 sizeof( VLC_BITMAPINFOHEADER
) ),
1015 UINT_MAX
, uint32_t );
1016 fmt
.p_extra
= malloc( fmt
.i_extra
);
1017 memcpy( fmt
.p_extra
, &p_data
[sizeof( VLC_BITMAPINFOHEADER
)],
1021 /* Look for an aspect ratio */
1022 if( p_sys
->p_root
->p_metadata
)
1024 asf_object_metadata_t
*p_meta
= p_sys
->p_root
->p_metadata
;
1025 unsigned int i_aspect_x
= 0, i_aspect_y
= 0;
1027 for( i
= 0; i
< p_meta
->i_record_entries_count
; i
++ )
1029 if( !p_meta
->record
[i
].psz_name
)
1031 if( !strcmp( p_meta
->record
[i
].psz_name
, "AspectRatioX" ) )
1033 if( (!i_aspect_x
&& !p_meta
->record
[i
].i_stream
) ||
1034 p_meta
->record
[i
].i_stream
==
1035 p_sp
->i_stream_number
)
1036 GET_CHECKED( i_aspect_x
, p_meta
->record
[i
].i_val
,
1037 UINT_MAX
, uint64_t );
1039 if( !strcmp( p_meta
->record
[i
].psz_name
, "AspectRatioY" ) )
1041 if( (!i_aspect_y
&& !p_meta
->record
[i
].i_stream
) ||
1042 p_meta
->record
[i
].i_stream
==
1043 p_sp
->i_stream_number
)
1044 GET_CHECKED( i_aspect_y
, p_meta
->record
[i
].i_val
,
1045 UINT_MAX
, uint64_t );
1049 if( i_aspect_x
&& i_aspect_y
)
1051 fmt
.video
.i_sar_num
= i_aspect_x
;
1052 fmt
.video
.i_sar_den
= i_aspect_y
;
1056 /* If there is a video track then use the index for seeking */
1057 p_sys
->b_index
= b_index
;
1059 msg_Dbg( p_demux
, "added new video stream(codec:%4.4s,ID:%d)",
1060 (char*)&fmt
.i_codec
, p_sp
->i_stream_number
);
1062 else if( guidcmp( &p_sp
->i_stream_type
, &asf_object_stream_type_binary
) &&
1063 p_sp
->i_type_specific_data_length
>= 64 )
1065 guid_t i_major_media_type
;
1066 ASF_GetGUID( &i_major_media_type
, p_sp
->p_type_specific_data
);
1067 msg_Dbg( p_demux
, "stream(ID:%d) major type " GUID_FMT
, p_sp
->i_stream_number
,
1068 GUID_PRINT(i_major_media_type
) );
1070 guid_t i_media_subtype
;
1071 ASF_GetGUID( &i_media_subtype
, &p_sp
->p_type_specific_data
[16] );
1072 msg_Dbg( p_demux
, "stream(ID:%d) subtype " GUID_FMT
, p_sp
->i_stream_number
,
1073 GUID_PRINT(i_media_subtype
) );
1075 //uint32_t i_fixed_size_samples = GetDWBE( &p_sp->p_type_specific_data[32] );
1076 //uint32_t i_temporal_compression = GetDWBE( &p_sp->p_type_specific_data[36] );
1077 //uint32_t i_sample_size = GetDWBE( &p_sp->p_type_specific_data[40] );
1079 guid_t i_format_type
;
1080 ASF_GetGUID( &i_format_type
, &p_sp
->p_type_specific_data
[44] );
1081 msg_Dbg( p_demux
, "stream(ID:%d) format type " GUID_FMT
, p_sp
->i_stream_number
,
1082 GUID_PRINT(i_format_type
) );
1084 //uint32_t i_format_data_size = GetDWBE( &p_sp->p_type_specific_data[60] );
1085 uint8_t *p_data
= p_sp
->p_type_specific_data
+ 64;
1086 unsigned int i_data
= p_sp
->i_type_specific_data_length
- 64;
1088 msg_Dbg( p_demux
, "Ext stream header detected. datasize = %d", p_sp
->i_type_specific_data_length
);
1089 if( guidcmp( &i_major_media_type
, &asf_object_extended_stream_type_audio
) &&
1090 i_data
>= sizeof( WAVEFORMATEX
) - 2)
1093 es_format_Init( &fmt
, AUDIO_ES
, 0 );
1095 i_format
= GetWLE( &p_data
[0] );
1097 fmt
.i_codec
= VLC_CODEC_A52
;
1099 wf_tag_to_fourcc( i_format
, &fmt
.i_codec
, NULL
);
1101 GET_CHECKED( fmt
.audio
.i_channels
, GetWLE( &p_data
[2] ),
1103 GET_CHECKED( fmt
.audio
.i_rate
, GetDWLE( &p_data
[4] ),
1104 UINT_MAX
, uint32_t );
1105 GET_CHECKED( fmt
.i_bitrate
, GetDWLE( &p_data
[8] ) * 8,
1106 UINT_MAX
, uint32_t );
1107 fmt
.audio
.i_blockalign
= GetWLE( &p_data
[12] );
1108 fmt
.audio
.i_bitspersample
= GetWLE( &p_data
[14] );
1110 if( p_sp
->i_type_specific_data_length
> sizeof( WAVEFORMATEX
) &&
1111 i_format
!= WAVE_FORMAT_MPEGLAYER3
&&
1112 i_format
!= WAVE_FORMAT_MPEG
&& i_data
>= 19 )
1114 GET_CHECKED( fmt
.i_extra
, __MIN( GetWLE( &p_data
[16] ),
1115 p_sp
->i_type_specific_data_length
-
1116 sizeof( WAVEFORMATEX
) ),
1117 INT_MAX
, uint32_t );
1118 fmt
.p_extra
= malloc( fmt
.i_extra
);
1120 memcpy( fmt
.p_extra
, &p_data
[sizeof( WAVEFORMATEX
)], fmt
.i_extra
);
1125 msg_Dbg( p_demux
, "added new audio stream (codec:%4.4s(0x%x),ID:%d)",
1126 (char*)&fmt
.i_codec
, i_format
, p_sp
->i_stream_number
);
1130 es_format_Init( &fmt
, UNKNOWN_ES
, 0 );
1135 es_format_Init( &fmt
, UNKNOWN_ES
, 0 );
1140 fmt
.i_original_fourcc
= VLC_FOURCC( 'D','V','R',' ');
1141 fmt
.b_packetized
= false;
1144 if( fmt
.i_codec
== VLC_CODEC_MP4A
)
1145 fmt
.b_packetized
= false;
1147 tk
->i_cat
= tk
->info
.i_cat
= fmt
.i_cat
;
1148 if( fmt
.i_cat
!= UNKNOWN_ES
)
1150 if( p_esp
&& p_languages
&&
1151 p_esp
->i_language_index
< p_languages
->i_language
&&
1152 p_languages
->ppsz_language
[p_esp
->i_language_index
] )
1154 fmt
.psz_language
= strdup( p_languages
->ppsz_language
[p_esp
->i_language_index
] );
1156 if( fmt
.psz_language
&& (p
= strchr( fmt
.psz_language
, '-' )) )
1160 /* Set our priority so we won't get multiple videos */
1161 int i_priority
= ES_PRIORITY_SELECTABLE_MIN
;
1162 for( uint16_t i
= 0; i
< fmt_priorities_ex
.i_count
; i
++ )
1164 if ( fmt_priorities_ex
.pi_stream_numbers
[i
] == p_sp
->i_stream_number
)
1166 i_priority
= ES_PRIORITY_NOT_DEFAULTABLE
;
1170 for( uint16_t i
= 0; i
< fmt_priorities_bitrate_ex
.i_count
; i
++ )
1172 if ( fmt_priorities_bitrate_ex
.pi_stream_numbers
[i
] == p_sp
->i_stream_number
)
1174 i_priority
= ES_PRIORITY_NOT_DEFAULTABLE
;
1178 fmt
.i_priority
= i_priority
;
1180 if ( i_stream
<= INT_MAX
)
1181 fmt
.i_id
= i_stream
;
1183 msg_Warn( p_demux
, "Can't set fmt.i_id to match stream id %u", i_stream
);
1185 if ( fmt
.i_cat
== VIDEO_ES
)
1187 /* Backup our video format */
1188 tk
->p_fmt
= malloc( sizeof( es_format_t
) );
1190 es_format_Copy( tk
->p_fmt
, &fmt
);
1193 fmt
.i_id
= tk
->info
.p_sp
->i_stream_number
;
1195 tk
->p_es
= es_out_Add( p_demux
->out
, &fmt
);
1197 if( !vlc_stream_Control( p_demux
->s
, STREAM_GET_PRIVATE_ID_STATE
,
1198 (int) p_sp
->i_stream_number
,
1199 &b_access_selected
) &&
1202 p_sys
->i_access_selected_track
[fmt
.i_cat
] = p_sp
->i_stream_number
;
1208 msg_Dbg( p_demux
, "ignoring unknown stream(ID:%d)",
1209 p_sp
->i_stream_number
);
1212 es_format_Clean( &fmt
);
1215 free( fmt_priorities_ex
.pi_stream_numbers
);
1216 free( fmt_priorities_bitrate_ex
.pi_stream_numbers
);
1218 p_sys
->i_data_begin
= p_sys
->p_root
->p_data
->i_object_pos
+ 50;
1219 if( p_sys
->p_root
->p_data
->i_object_size
!= 0 )
1221 p_sys
->i_data_end
= p_sys
->p_root
->p_data
->i_object_pos
+
1222 p_sys
->p_root
->p_data
->i_object_size
;
1223 p_sys
->i_data_end
= __MIN( (uint64_t)stream_Size( p_demux
->s
), p_sys
->i_data_end
);
1226 { /* live/broacast */
1227 p_sys
->i_data_end
= 0;
1230 /* go to first packet */
1231 if( vlc_stream_Seek( p_demux
->s
, p_sys
->i_data_begin
) != VLC_SUCCESS
)
1234 /* try to calculate movie time */
1235 if( p_sys
->p_fp
->i_data_packets_count
> 0 )
1238 uint64_t i_size
= stream_Size( p_demux
->s
);
1240 if( p_sys
->i_data_end
> 0 && i_size
> p_sys
->i_data_end
)
1242 i_size
= p_sys
->i_data_end
;
1245 /* real number of packets */
1246 i_count
= ( i_size
- p_sys
->i_data_begin
) /
1247 p_sys
->p_fp
->i_min_data_packet_size
;
1249 /* calculate the time duration in micro-s */
1250 p_sys
->i_length
= (mtime_t
)p_sys
->p_fp
->i_play_duration
/ 10 *
1252 (mtime_t
)p_sys
->p_fp
->i_data_packets_count
- p_sys
->p_fp
->i_preroll
* 1000;
1253 if( p_sys
->i_length
< 0 )
1254 p_sys
->i_length
= 0;
1256 if( p_sys
->i_length
> 0 )
1258 p_sys
->i_bitrate
= 8 * i_size
* 1000000 / p_sys
->i_length
;
1262 /* Create meta information */
1263 p_sys
->meta
= vlc_meta_New();
1265 asf_object_content_description_t
*p_cd
;
1266 if( ( p_cd
= ASF_FindObject( p_sys
->p_root
->p_hdr
,
1267 &asf_object_content_description_guid
, 0 ) ) )
1269 if( p_cd
->psz_title
&& *p_cd
->psz_title
)
1271 vlc_meta_SetTitle( p_sys
->meta
, p_cd
->psz_title
);
1273 if( p_cd
->psz_artist
&& *p_cd
->psz_artist
)
1275 vlc_meta_SetArtist( p_sys
->meta
, p_cd
->psz_artist
);
1277 if( p_cd
->psz_copyright
&& *p_cd
->psz_copyright
)
1279 vlc_meta_SetCopyright( p_sys
->meta
, p_cd
->psz_copyright
);
1281 if( p_cd
->psz_description
&& *p_cd
->psz_description
)
1283 vlc_meta_SetDescription( p_sys
->meta
, p_cd
->psz_description
);
1285 if( p_cd
->psz_rating
&& *p_cd
->psz_rating
)
1287 vlc_meta_SetRating( p_sys
->meta
, p_cd
->psz_rating
);
1290 asf_object_extended_content_description_t
*p_ecd
;
1291 if( ( p_ecd
= ASF_FindObject( p_sys
->p_root
->p_hdr
,
1292 &asf_object_extended_content_description
, 0 ) ) )
1294 for( int i
= 0; i
< p_ecd
->i_count
; i
++ )
1297 #define set_meta( name, vlc_type ) \
1298 if( p_ecd->ppsz_name[i] && !strncmp( p_ecd->ppsz_name[i], name, strlen(name) ) ) \
1299 vlc_meta_Set( p_sys->meta, vlc_type, p_ecd->ppsz_value[i] );
1301 set_meta( "WM/AlbumTitle", vlc_meta_Album
)
1302 else set_meta( "WM/TrackNumber", vlc_meta_TrackNumber
)
1303 else set_meta( "WM/Year", vlc_meta_Date
)
1304 else set_meta( "WM/Genre", vlc_meta_Genre
)
1305 else set_meta( "WM/Genre", vlc_meta_Genre
)
1306 else set_meta( "WM/AlbumArtist", vlc_meta_AlbumArtist
)
1307 else set_meta( "WM/Publisher", vlc_meta_Publisher
)
1308 else set_meta( "WM/PartOfSet", vlc_meta_DiscNumber
)
1309 else if( p_ecd
->ppsz_value
[i
] != NULL
&& p_ecd
->ppsz_name
[i
] &&
1310 *p_ecd
->ppsz_value
[i
] != '\0' && /* no empty value */
1311 *p_ecd
->ppsz_value
[i
] != '{' && /* no guid value */
1312 *p_ecd
->ppsz_name
[i
] != '{' ) /* no guid name */
1313 vlc_meta_AddExtra( p_sys
->meta
, p_ecd
->ppsz_name
[i
], p_ecd
->ppsz_value
[i
] );
1314 /* TODO map WM/Composer, WM/Provider, WM/PartOfSet, PeakValue, AverageLevel */
1319 /// \tood Fix Child meta for ASF tracks
1321 for( i_stream
= 0, i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
1323 asf_object_codec_list_t
*p_cl
= ASF_FindObject( p_sys
->p_root
->p_hdr
,
1324 &asf_object_codec_list_guid
, 0 );
1326 if( p_sys
->track
[i
] )
1328 vlc_meta_t
*tk
= vlc_meta_New();
1329 TAB_APPEND( p_sys
->meta
->i_track
, p_sys
->meta
->track
, tk
);
1331 if( p_cl
&& i_stream
< p_cl
->i_codec_entries_count
)
1333 if( p_cl
->codec
[i_stream
].psz_name
&&
1334 *p_cl
->codec
[i_stream
].psz_name
)
1336 vlc_meta_Add( tk
, VLC_META_CODEC_NAME
,
1337 p_cl
->codec
[i_stream
].psz_name
);
1339 if( p_cl
->codec
[i_stream
].psz_description
&&
1340 *p_cl
->codec
[i_stream
].psz_description
)
1342 vlc_meta_Add( tk
, VLC_META_CODEC_DESCRIPTION
,
1343 p_cl
->codec
[i_stream
].psz_description
);
1351 p_sys
->packet_sys
.pi_preroll
= &p_sys
->p_fp
->i_preroll
;
1352 p_sys
->packet_sys
.pi_preroll_start
= &p_sys
->i_preroll_start
;
1357 DemuxEnd( p_demux
);
1358 return VLC_EGENERIC
;
1361 /*****************************************************************************
1362 * FlushQueues: flushes tail packets and send queues
1363 *****************************************************************************/
1364 static void FlushQueue( asf_track_t
*tk
)
1366 if( tk
->info
.p_frame
)
1368 block_ChainRelease( tk
->info
.p_frame
);
1369 tk
->info
.p_frame
= NULL
;
1371 if( tk
->queue
.p_first
)
1373 block_ChainRelease( tk
->queue
.p_first
);
1374 tk
->queue
.p_first
= NULL
;
1375 tk
->queue
.pp_last
= &tk
->queue
.p_first
;
1379 static void FlushQueues( demux_t
*p_demux
)
1381 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1382 for ( unsigned int i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
1384 asf_track_t
*tk
= p_sys
->track
[i
];
1391 /*****************************************************************************
1393 *****************************************************************************/
1394 static void DemuxEnd( demux_t
*p_demux
)
1396 demux_sys_t
*p_sys
= p_demux
->p_sys
;
1400 ASF_FreeObjectRoot( p_demux
->s
, p_sys
->p_root
);
1401 p_sys
->p_root
= NULL
;
1405 vlc_meta_Delete( p_sys
->meta
);
1409 FlushQueues( p_demux
);
1411 for( int i
= 0; i
< MAX_ASF_TRACKS
; i
++ )
1413 asf_track_t
*tk
= p_sys
->track
[i
];
1419 es_out_Del( p_demux
->out
, tk
->p_es
);
1423 es_format_Clean( tk
->p_fmt
);
1428 p_sys
->track
[i
] = 0;