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>
34 static int CmpGuid( const guid_t
*p_guid1
, const guid_t
*p_guid2
)
36 return( ( p_guid1
->v1
== p_guid2
->v1
&&
37 p_guid1
->v2
== p_guid2
->v2
&&
38 p_guid1
->v3
== p_guid2
->v3
&&
39 p_guid1
->v4
[0] == p_guid2
->v4
[0] &&
40 p_guid1
->v4
[1] == p_guid2
->v4
[1] &&
41 p_guid1
->v4
[2] == p_guid2
->v4
[2] &&
42 p_guid1
->v4
[3] == p_guid2
->v4
[3] &&
43 p_guid1
->v4
[4] == p_guid2
->v4
[4] &&
44 p_guid1
->v4
[5] == p_guid2
->v4
[5] &&
45 p_guid1
->v4
[6] == p_guid2
->v4
[6] &&
46 p_guid1
->v4
[7] == p_guid2
->v4
[7] ) ? 1 : 0 );
49 void GenerateGuid ( guid_t
*p_guid
)
51 p_guid
->v1
= 0xbabac001;
52 vlc_rand_bytes(&p_guid
->v2
, sizeof(p_guid
->v2
));
53 vlc_rand_bytes(&p_guid
->v3
, sizeof(p_guid
->v3
));
54 vlc_rand_bytes(p_guid
->v4
, sizeof(p_guid
->v4
));
57 void asf_HeaderParse ( asf_header_t
*hdr
,
58 uint8_t *p_header
, int i_header
)
66 hdr
->i_data_packets_count
= 0;
67 hdr
->i_min_data_packet_size
= 0;
68 for( i
= 0; i
< 128; i
++ )
70 hdr
->stream
[i
].i_cat
= ASF_STREAM_UNKNOWN
;
71 hdr
->stream
[i
].i_selected
= 0;
72 hdr
->stream
[i
].i_bitrate
= -1;
75 var_buffer_initread( &buffer
, p_header
, i_header
);
76 var_buffer_getguid( &buffer
, &guid
);
78 if( !CmpGuid( &guid
, &asf_object_header_guid
) )
82 var_buffer_getmemory( &buffer
, NULL
, 30 - 16 );
86 var_buffer_getguid( &buffer
, &guid
);
87 i_size
= var_buffer_get64( &buffer
);
89 if( CmpGuid( &guid
, &asf_object_file_properties_guid
) )
91 var_buffer_getmemory( &buffer
, NULL
, 16 );
92 hdr
->i_file_size
= var_buffer_get64( &buffer
);
93 var_buffer_getmemory( &buffer
, NULL
, 8 );
94 hdr
->i_data_packets_count
= var_buffer_get64( &buffer
);
95 var_buffer_getmemory( &buffer
, NULL
, 8+8+8+4);
96 hdr
->i_min_data_packet_size
= var_buffer_get32( &buffer
);
98 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 - 16 - 8 - 8 - 8 - 8-8-8-4 - 4);
100 else if( CmpGuid( &guid
, &asf_object_header_extension_guid
) )
103 var_buffer_getmemory( &buffer
, NULL
, 46 - 24 );
105 else if( CmpGuid( &guid
, &asf_object_extended_stream_properties_guid
) )
108 int16_t i_count1
, i_count2
;
112 var_buffer_getmemory( &buffer
, NULL
, 84 - 24 );
114 i_count1
= var_buffer_get16( &buffer
);
115 i_count2
= var_buffer_get16( &buffer
);
118 for( i
= 0; i
< i_count1
; i
++ )
122 var_buffer_get16( &buffer
);
123 i_len
= var_buffer_get16( &buffer
);
124 var_buffer_getmemory( &buffer
, NULL
, i_len
);
126 i_subsize
= 4 + i_len
;
129 for( i
= 0; i
< i_count2
; i
++ )
132 var_buffer_getmemory( &buffer
, NULL
, 16 + 2 );
133 i_len
= var_buffer_get32( &buffer
);
134 var_buffer_getmemory( &buffer
, NULL
, i_len
);
136 i_subsize
+= 16 + 6 + i_len
;
139 if( i_size
- i_subsize
<= 24 )
141 var_buffer_getmemory( &buffer
, NULL
, i_size
- i_subsize
);
143 /* It's a hack we just skip the first part of the object until
144 * the embed stream properties if any (ugly, but whose fault ?) */
146 else if( CmpGuid( &guid
, &asf_object_stream_properties_guid
) )
151 var_buffer_getguid( &buffer
, &stream_type
);
152 var_buffer_getmemory( &buffer
, NULL
, 32 );
154 i_stream_id
= var_buffer_get8( &buffer
) & 0x7f;
155 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 - 32 - 16 - 1);
157 if( CmpGuid( &stream_type
, &asf_object_stream_type_video
) )
159 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_VIDEO
;
161 else if( CmpGuid( &stream_type
, &asf_object_stream_type_audio
) )
163 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_AUDIO
;
167 hdr
->stream
[i_stream_id
].i_cat
= ASF_STREAM_UNKNOWN
;
170 else if ( CmpGuid( &guid
, &asf_object_bitrate_properties_guid
) )
175 i_count
= var_buffer_get16( &buffer
);
179 i_stream_id
= var_buffer_get16( &buffer
)&0x7f;
180 hdr
->stream
[i_stream_id
].i_bitrate
= var_buffer_get32( &buffer
);
184 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 );
189 var_buffer_getmemory( &buffer
, NULL
, i_size
- 24 );
192 if( var_buffer_readempty( &buffer
) )
197 void asf_StreamSelect ( asf_header_t
*hdr
,
199 bool b_all
, bool b_audio
, bool b_video
)
201 /* XXX FIXME use mututal eclusion information */
203 int i_audio
, i_video
;
214 /* select all valid stream */
215 for( i
= 1; i
< 128; i
++ )
217 if( hdr
->stream
[i
].i_cat
!= ASF_STREAM_UNKNOWN
)
219 hdr
->stream
[i
].i_selected
= 1;
226 for( i
= 0; i
< 128; i
++ )
228 /* by default, not selected */
229 hdr
->stream
[i
].i_selected
= 0;
235 * - no audio nor video stream
237 * - if i_bitrate_max not set keep the highest bitrate
238 * - if i_bitrate_max is set, keep stream that make we used best
239 * quality regarding i_bitrate_max
242 * - it doesn't use mutual exclusion info..
243 * - when selecting a better stream we could select
244 * something that make i_bitrate_total> i_bitrate_max
246 for( i
= 1; i
< 128; i
++ )
248 if( hdr
->stream
[i
].i_cat
== ASF_STREAM_UNKNOWN
)
252 else if( hdr
->stream
[i
].i_cat
== ASF_STREAM_AUDIO
&& b_audio
&&
254 ( ( ( hdr
->stream
[i
].i_bitrate
> hdr
->stream
[i_audio
].i_bitrate
&&
255 ( i_bitrate_total
+ hdr
->stream
[i
].i_bitrate
- hdr
->stream
[i_audio
].i_bitrate
256 < i_bitrate_max
|| !i_bitrate_max
) ) ||
257 ( hdr
->stream
[i
].i_bitrate
< hdr
->stream
[i_audio
].i_bitrate
&&
258 i_bitrate_max
!= 0 && i_bitrate_total
> i_bitrate_max
)
261 /* unselect old stream */
264 hdr
->stream
[i_audio
].i_selected
= 0;
265 if( hdr
->stream
[i_audio
].i_bitrate
> 0 )
267 i_bitrate_total
-= hdr
->stream
[i_audio
].i_bitrate
;
271 hdr
->stream
[i
].i_selected
= 1;
272 if( hdr
->stream
[i
].i_bitrate
> 0 )
274 i_bitrate_total
+= hdr
->stream
[i
].i_bitrate
;
278 else if( hdr
->stream
[i
].i_cat
== ASF_STREAM_VIDEO
&& b_video
&&
281 ( ( hdr
->stream
[i
].i_bitrate
> hdr
->stream
[i_video
].i_bitrate
&&
282 ( i_bitrate_total
+ hdr
->stream
[i
].i_bitrate
- hdr
->stream
[i_video
].i_bitrate
283 < i_bitrate_max
|| !i_bitrate_max
) ) ||
284 ( hdr
->stream
[i
].i_bitrate
< hdr
->stream
[i_video
].i_bitrate
&&
285 i_bitrate_max
!= 0 && i_bitrate_total
> i_bitrate_max
)
288 /* unselect old stream */
291 hdr
->stream
[i_video
].i_selected
= 0;
292 if( hdr
->stream
[i_video
].i_bitrate
> 0 )
294 i_bitrate_total
-= hdr
->stream
[i_video
].i_bitrate
;
298 hdr
->stream
[i
].i_selected
= 1;
299 if( hdr
->stream
[i
].i_bitrate
> 0 )
301 i_bitrate_total
+= hdr
->stream
[i
].i_bitrate
;