1 /*****************************************************************************
2 * asf.c: MMS access plug-in
3 *****************************************************************************
4 * Copyright (C) 2001-2004 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_common.h>
30 #include <vlc_codecs.h>
35 void GenerateGuid ( guid_t
*p_guid
)
37 p_guid
->Data1
= 0xbabac001;
38 vlc_rand_bytes(&p_guid
->Data2
, sizeof(p_guid
->Data2
));
39 vlc_rand_bytes(&p_guid
->Data3
, sizeof(p_guid
->Data3
));
40 vlc_rand_bytes(p_guid
->Data4
, sizeof(p_guid
->Data4
));
43 void asf_HeaderParse ( asf_header_t
*hdr
,
44 uint8_t *p_header
, int i_header
)
51 hdr
->i_data_packets_count
= 0;
52 hdr
->i_min_data_packet_size
= 0;
53 for( unsigned i
= 0; i
< 128; i
++ )
55 hdr
->stream
[i
].i_cat
= ASF_STREAM_UNKNOWN
;
56 hdr
->stream
[i
].i_selected
= 0;
57 hdr
->stream
[i
].i_bitrate
= -1;
60 var_buffer_initread( &buffer
, p_header
, i_header
);
61 var_buffer_getguid( &buffer
, &guid
);
63 if( !guidcmp( &guid
, &asf_object_header_guid
) )
67 var_buffer_getmemory( &buffer
, NULL
, 30 - 16 );
71 var_buffer_getguid( &buffer
, &guid
);
72 i_size
= var_buffer_get64( &buffer
);
74 if( guidcmp( &guid
, &asf_object_file_properties_guid
) )
76 var_buffer_getmemory( &buffer
, NULL
, 16 );
77 hdr
->i_file_size
= var_buffer_get64( &buffer
);
78 var_buffer_getmemory( &buffer
, NULL
, 8 );
79 hdr
->i_data_packets_count
= var_buffer_get64( &buffer
);
80 var_buffer_getmemory( &buffer
, NULL
, 8+8+8+4);
81 hdr
->i_min_data_packet_size
= var_buffer_get32( &buffer
);
83 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 - 16 - 8 - 8 - 8 - 8-8-8-4 - 4);
85 else if( guidcmp( &guid
, &asf_object_header_extension_guid
) )
88 var_buffer_getmemory( &buffer
, NULL
, 46 - 24 );
90 else if( guidcmp( &guid
, &asf_object_extended_stream_properties_guid
) )
93 int16_t i_count1
, i_count2
;
96 var_buffer_getmemory( &buffer
, NULL
, 84 - 24 );
98 i_count1
= var_buffer_get16( &buffer
);
99 i_count2
= var_buffer_get16( &buffer
);
102 for( int i
= 0; i
< i_count1
; i
++ )
106 var_buffer_get16( &buffer
);
107 i_len
= var_buffer_get16( &buffer
);
108 var_buffer_getmemory( &buffer
, NULL
, i_len
);
110 i_subsize
+= 4 + i_len
;
113 for( int i
= 0; i
< i_count2
; i
++ )
116 var_buffer_getmemory( &buffer
, NULL
, 16 + 2 );
117 i_len
= var_buffer_get32( &buffer
);
118 var_buffer_getmemory( &buffer
, NULL
, i_len
);
120 i_subsize
+= 16 + 6 + i_len
;
123 if( i_size
- i_subsize
<= 24 )
125 var_buffer_getmemory( &buffer
, NULL
, i_size
- i_subsize
);
127 /* It's a hack we just skip the first part of the object until
128 * the embed stream properties if any (ugly, but whose fault ?) */
130 else if( guidcmp( &guid
, &asf_object_stream_properties_guid
) )
135 var_buffer_getguid( &buffer
, &stream_type
);
136 var_buffer_getmemory( &buffer
, NULL
, 32 );
138 i_stream_id
= var_buffer_get8( &buffer
) & 0x7f;
139 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 - 32 - 16 - 1);
141 if( guidcmp( &stream_type
, &asf_object_stream_type_video
) )
143 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_VIDEO
;
145 else if( guidcmp( &stream_type
, &asf_object_stream_type_audio
) )
147 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_AUDIO
;
151 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_UNKNOWN
;
154 else if ( guidcmp( &guid
, &asf_object_stream_bitrate_properties
) )
159 i_count
= var_buffer_get16( &buffer
);
163 i_stream_id
= var_buffer_get16( &buffer
)&0x7f;
164 hdr
->stream
[i_stream_id
].i_bitrate
= var_buffer_get32( &buffer
);
168 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 );
173 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 );
176 if( var_buffer_readempty( &buffer
) )
181 void asf_StreamSelect ( asf_header_t
*hdr
,
183 bool b_all
, bool b_audio
, bool b_video
)
185 /* XXX FIXME use mututal eclusion information */
187 int i_audio
, i_video
;
198 /* select all valid stream */
199 for( i
= 1; i
< 128; i
++ )
201 if( hdr
->stream
[i
].i_cat
!= ASF_STREAM_UNKNOWN
)
203 hdr
->stream
[i
].i_selected
= 1;
210 for( i
= 0; i
< 128; i
++ )
212 /* by default, not selected */
213 hdr
->stream
[i
].i_selected
= 0;
219 * - no audio nor video stream
221 * - if i_bitrate_max not set keep the highest bitrate
222 * - if i_bitrate_max is set, keep stream that make we used best
223 * quality regarding i_bitrate_max
226 * - it doesn't use mutual exclusion info..
227 * - when selecting a better stream we could select
228 * something that make i_bitrate_total> i_bitrate_max
230 for( i
= 1; i
< 128; i
++ )
232 if( hdr
->stream
[i
].i_cat
== ASF_STREAM_UNKNOWN
)
236 else if( hdr
->stream
[i
].i_cat
== ASF_STREAM_AUDIO
&& b_audio
&&
238 ( ( ( hdr
->stream
[i
].i_bitrate
> hdr
->stream
[i_audio
].i_bitrate
&&
239 ( i_bitrate_total
+ hdr
->stream
[i
].i_bitrate
- hdr
->stream
[i_audio
].i_bitrate
240 < i_bitrate_max
|| !i_bitrate_max
) ) ||
241 ( hdr
->stream
[i
].i_bitrate
< hdr
->stream
[i_audio
].i_bitrate
&&
242 i_bitrate_max
!= 0 && i_bitrate_total
> i_bitrate_max
)
245 /* unselect old stream */
248 hdr
->stream
[i_audio
].i_selected
= 0;
249 if( hdr
->stream
[i_audio
].i_bitrate
> 0 )
251 i_bitrate_total
-= hdr
->stream
[i_audio
].i_bitrate
;
255 hdr
->stream
[i
].i_selected
= 1;
256 if( hdr
->stream
[i
].i_bitrate
> 0 )
258 i_bitrate_total
+= hdr
->stream
[i
].i_bitrate
;
262 else if( hdr
->stream
[i
].i_cat
== ASF_STREAM_VIDEO
&& b_video
&&
265 ( ( hdr
->stream
[i
].i_bitrate
> hdr
->stream
[i_video
].i_bitrate
&&
266 ( i_bitrate_total
+ hdr
->stream
[i
].i_bitrate
- hdr
->stream
[i_video
].i_bitrate
267 < i_bitrate_max
|| !i_bitrate_max
) ) ||
268 ( hdr
->stream
[i
].i_bitrate
< hdr
->stream
[i_video
].i_bitrate
&&
269 i_bitrate_max
!= 0 && i_bitrate_total
> i_bitrate_max
)
272 /* unselect old stream */
275 hdr
->stream
[i_video
].i_selected
= 0;
276 if( hdr
->stream
[i_video
].i_bitrate
> 0 )
278 i_bitrate_total
-= hdr
->stream
[i_video
].i_bitrate
;
282 hdr
->stream
[i
].i_selected
= 1;
283 if( hdr
->stream
[i
].i_bitrate
> 0 )
285 i_bitrate_total
+= hdr
->stream
[i
].i_bitrate
;