1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001 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 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_demux.h> /* stream_*, *_ES */
30 #include <vlc_codecs.h> /* VLC_BITMAPINFOHEADER */
38 #define __EVEN( x ) (((x) + 1) & ~1)
40 static vlc_fourcc_t
GetFOURCC( const uint8_t *p_buff
)
42 return VLC_FOURCC( p_buff
[0], p_buff
[1], p_buff
[2], p_buff
[3] );
45 /****************************************************************************
47 * Basics functions to manipulates chunks
49 ****************************************************************************/
50 static int AVI_ChunkReadCommon( stream_t
*s
, avi_chunk_t
*p_chk
)
52 const uint8_t *p_peek
;
54 memset( p_chk
, 0, sizeof( avi_chunk_t
) );
56 if( vlc_stream_Peek( s
, &p_peek
, 8 ) < 8 )
59 p_chk
->common
.i_chunk_fourcc
= GetFOURCC( p_peek
);
60 p_chk
->common
.i_chunk_size
= GetDWLE( p_peek
+ 4 );
61 p_chk
->common
.i_chunk_pos
= vlc_stream_Tell( s
);
63 p_chk
->common
.p_father
= NULL
;
64 p_chk
->common
.p_next
= NULL
;
65 p_chk
->common
.p_first
= NULL
;
66 p_chk
->common
.p_next
= NULL
;
69 msg_Dbg( (vlc_object_t
*)s
,
70 "found chunk, fourcc: %4.4s size:%"PRId64
" pos:%"PRId64
,
71 (char*)&p_chk
->common
.i_chunk_fourcc
,
72 p_chk
->common
.i_chunk_size
,
73 p_chk
->common
.i_chunk_pos
);
78 static int AVI_NextChunk( stream_t
*s
, avi_chunk_t
*p_chk
)
84 if( AVI_ChunkReadCommon( s
, &chk
) )
91 if( p_chk
->common
.p_father
)
93 if( p_chk
->common
.p_father
->common
.i_chunk_pos
+
94 __EVEN( p_chk
->common
.p_father
->common
.i_chunk_size
) + 8 <
95 p_chk
->common
.i_chunk_pos
+
96 __EVEN( p_chk
->common
.i_chunk_size
) + 8 )
102 bool b_seekable
= false;
103 uint64_t i_offset
= p_chk
->common
.i_chunk_pos
+
104 __EVEN( p_chk
->common
.i_chunk_size
) + 8;
105 if ( !vlc_stream_Control(s
, STREAM_CAN_SEEK
, &b_seekable
) && b_seekable
)
107 return vlc_stream_Seek( s
, i_offset
);
111 ssize_t i_read
= i_offset
- vlc_stream_Tell( s
);
112 return (i_read
>=0 && vlc_stream_Read( s
, NULL
, i_read
) == i_read
) ?
113 VLC_SUCCESS
: VLC_EGENERIC
;
117 /****************************************************************************
119 * Functions to read chunks
121 ****************************************************************************/
122 static int AVI_ChunkRead_list( stream_t
*s
, avi_chunk_t
*p_container
)
125 const uint8_t *p_peek
;
127 int i_ret
= VLC_SUCCESS
;
129 if( p_container
->common
.i_chunk_size
> 0 && p_container
->common
.i_chunk_size
< 4 )
132 msg_Warn( (vlc_object_t
*)s
, "empty list chunk" );
135 if( vlc_stream_Peek( s
, &p_peek
, 12 ) < 12 )
137 msg_Warn( (vlc_object_t
*)s
, "cannot peek while reading list chunk" );
141 vlc_stream_Control( s
, STREAM_CAN_SEEK
, &b_seekable
);
143 p_container
->list
.i_type
= GetFOURCC( p_peek
+ 8 );
145 /* XXX fixed for on2 hack */
146 if( p_container
->common
.i_chunk_fourcc
== AVIFOURCC_ON2
&& p_container
->list
.i_type
== AVIFOURCC_ON2f
)
148 p_container
->common
.i_chunk_fourcc
= AVIFOURCC_RIFF
;
149 p_container
->list
.i_type
= AVIFOURCC_AVI
;
152 if( p_container
->common
.i_chunk_fourcc
== AVIFOURCC_LIST
&&
153 p_container
->list
.i_type
== AVIFOURCC_movi
)
157 msg_Dbg( (vlc_object_t
*)s
, "skipping movi chunk" );
158 return AVI_NextChunk( s
, p_container
); /* points at begining of LIST-movi if not seekable */
161 if( vlc_stream_Read( s
, NULL
, 12 ) != 12 )
163 msg_Warn( (vlc_object_t
*)s
, "cannot enter chunk" );
168 msg_Dbg( (vlc_object_t
*)s
,
169 "found LIST chunk: \'%4.4s\'",
170 (char*)&p_container
->list
.i_type
);
172 msg_Dbg( (vlc_object_t
*)s
, "<list \'%4.4s\'>", (char*)&p_container
->list
.i_type
);
175 p_chk
= xmalloc( sizeof( avi_chunk_t
) );
176 memset( p_chk
, 0, sizeof( avi_chunk_t
) );
177 if( !p_container
->common
.p_first
)
179 p_container
->common
.p_first
= p_chk
;
183 p_container
->common
.p_last
->common
.p_next
= p_chk
;
185 p_container
->common
.p_last
= p_chk
;
187 i_ret
= AVI_ChunkRead( s
, p_chk
, p_container
);
192 if( p_chk
->common
.p_father
->common
.i_chunk_size
> 0 &&
193 ( vlc_stream_Tell( s
) >
194 (off_t
)p_chk
->common
.p_father
->common
.i_chunk_pos
+
195 (off_t
)__EVEN( p_chk
->common
.p_father
->common
.i_chunk_size
) ) )
200 /* If we can't seek then stop when we 've found LIST-movi */
201 if( p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_LIST
&&
202 p_chk
->list
.i_type
== AVIFOURCC_movi
&&
203 ( !b_seekable
|| p_chk
->common
.i_chunk_size
== 0 ) )
209 msg_Dbg( (vlc_object_t
*)s
, "</list \'%4.4s\'>", (char*)&p_container
->list
.i_type
);
211 if ( i_ret
== AVI_ZERO_FOURCC
) return i_ret
;
215 /* Allow to append indexes after starting playback */
216 int AVI_ChunkFetchIndexes( stream_t
*s
, avi_chunk_t
*p_riff
)
218 avi_chunk_t
*p_movi
= AVI_ChunkFind( p_riff
, AVIFOURCC_movi
, 0 );
223 uint64_t i_indexpos
= 8 + p_movi
->common
.i_chunk_pos
+ p_movi
->common
.i_chunk_size
;
224 bool b_seekable
= false;
225 int i_ret
= VLC_SUCCESS
;
227 vlc_stream_Control( s
, STREAM_CAN_SEEK
, &b_seekable
);
228 if ( !b_seekable
|| vlc_stream_Seek( s
, i_indexpos
) )
233 p_chk
= xmalloc( sizeof( avi_chunk_t
) );
234 memset( p_chk
, 0, sizeof( avi_chunk_t
) );
235 if (unlikely( !p_riff
->common
.p_first
))
236 p_riff
->common
.p_first
= p_chk
;
238 p_riff
->common
.p_last
->common
.p_next
= p_chk
;
239 p_riff
->common
.p_last
= p_chk
;
241 i_ret
= AVI_ChunkRead( s
, p_chk
, p_riff
);
245 if( p_chk
->common
.p_father
->common
.i_chunk_size
> 0 &&
246 ( vlc_stream_Tell( s
) >
247 (off_t
)p_chk
->common
.p_father
->common
.i_chunk_pos
+
248 (off_t
)__EVEN( p_chk
->common
.p_father
->common
.i_chunk_size
) ) )
253 /* If we can't seek then stop when we 've found any index */
254 if( p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_indx
||
255 p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_idx1
)
265 #define AVI_READCHUNK_ENTER \
266 int64_t i_read = __EVEN(p_chk->common.i_chunk_size ) + 8; \
267 if( i_read > 100000000 ) \
269 msg_Err( s, "Big chunk ignored" ); \
270 return VLC_EGENERIC; \
272 uint8_t *p_read, *p_buff; \
273 if( !( p_read = p_buff = malloc(i_read ) ) ) \
275 return VLC_EGENERIC; \
277 i_read = vlc_stream_Read( s, p_read, i_read ); \
278 if( i_read < (int64_t)__EVEN(p_chk->common.i_chunk_size ) + 8 ) \
281 return VLC_EGENERIC; \
286 #define AVI_READ( res, func, size ) \
287 if( i_read < size ) { \
289 return VLC_EGENERIC; \
292 res = func( p_read ); \
295 #define AVI_READCHUNK_EXIT( code ) \
299 static inline uint8_t GetB( uint8_t *ptr
)
304 #define AVI_READ1BYTE( i_byte ) \
305 AVI_READ( i_byte, GetB, 1 )
307 #define AVI_READ2BYTES( i_word ) \
308 AVI_READ( i_word, GetWLE, 2 )
310 #define AVI_READ4BYTES( i_dword ) \
311 AVI_READ( i_dword, GetDWLE, 4 )
313 #define AVI_READ8BYTES( i_qword ) \
314 AVI_READ( i_qword, GetQWLE, 8 )
316 #define AVI_READFOURCC( i_dword ) \
317 AVI_READ( i_dword, GetFOURCC, 4 )
319 static int AVI_ChunkRead_avih( stream_t
*s
, avi_chunk_t
*p_chk
)
323 p_chk
->common
.i_chunk_fourcc
= AVIFOURCC_avih
;
324 AVI_READ4BYTES( p_chk
->avih
.i_microsecperframe
);
325 AVI_READ4BYTES( p_chk
->avih
.i_maxbytespersec
);
326 AVI_READ4BYTES( p_chk
->avih
.i_reserved1
);
327 AVI_READ4BYTES( p_chk
->avih
.i_flags
);
328 AVI_READ4BYTES( p_chk
->avih
.i_totalframes
);
329 AVI_READ4BYTES( p_chk
->avih
.i_initialframes
);
330 AVI_READ4BYTES( p_chk
->avih
.i_streams
);
331 AVI_READ4BYTES( p_chk
->avih
.i_suggestedbuffersize
);
332 AVI_READ4BYTES( p_chk
->avih
.i_width
);
333 AVI_READ4BYTES( p_chk
->avih
.i_height
);
334 AVI_READ4BYTES( p_chk
->avih
.i_scale
);
335 AVI_READ4BYTES( p_chk
->avih
.i_rate
);
336 AVI_READ4BYTES( p_chk
->avih
.i_start
);
337 AVI_READ4BYTES( p_chk
->avih
.i_length
);
339 msg_Dbg( (vlc_object_t
*)s
,
340 "avih: streams:%d flags:%s%s%s%s %dx%d",
341 p_chk
->avih
.i_streams
,
342 p_chk
->avih
.i_flags
&AVIF_HASINDEX
?" HAS_INDEX":"",
343 p_chk
->avih
.i_flags
&AVIF_MUSTUSEINDEX
?" MUST_USE_INDEX":"",
344 p_chk
->avih
.i_flags
&AVIF_ISINTERLEAVED
?" IS_INTERLEAVED":"",
345 p_chk
->avih
.i_flags
&AVIF_TRUSTCKTYPE
?" TRUST_CKTYPE":"",
346 p_chk
->avih
.i_width
, p_chk
->avih
.i_height
);
348 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
351 static int AVI_ChunkRead_strh( stream_t
*s
, avi_chunk_t
*p_chk
)
355 AVI_READFOURCC( p_chk
->strh
.i_type
);
356 AVI_READFOURCC( p_chk
->strh
.i_handler
);
357 AVI_READ4BYTES( p_chk
->strh
.i_flags
);
358 AVI_READ4BYTES( p_chk
->strh
.i_reserved1
);
359 AVI_READ4BYTES( p_chk
->strh
.i_initialframes
);
360 AVI_READ4BYTES( p_chk
->strh
.i_scale
);
361 AVI_READ4BYTES( p_chk
->strh
.i_rate
);
362 AVI_READ4BYTES( p_chk
->strh
.i_start
);
363 AVI_READ4BYTES( p_chk
->strh
.i_length
);
364 AVI_READ4BYTES( p_chk
->strh
.i_suggestedbuffersize
);
365 AVI_READ4BYTES( p_chk
->strh
.i_quality
);
366 AVI_READ4BYTES( p_chk
->strh
.i_samplesize
);
368 msg_Dbg( (vlc_object_t
*)s
,
369 "strh: type:%4.4s handler:0x%8.8x samplesize:%d %.2ffps",
370 (char*)&p_chk
->strh
.i_type
,
371 p_chk
->strh
.i_handler
,
372 p_chk
->strh
.i_samplesize
,
373 ( p_chk
->strh
.i_scale
?
374 (float)p_chk
->strh
.i_rate
/ (float)p_chk
->strh
.i_scale
: -1) );
377 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
380 static int AVI_ChunkRead_strf( stream_t
*s
, avi_chunk_t
*p_chk
)
385 if( p_chk
->common
.p_father
== NULL
)
387 msg_Err( (vlc_object_t
*)s
, "malformed avi file" );
388 AVI_READCHUNK_EXIT( VLC_EGENERIC
);
390 if( !( p_strh
= AVI_ChunkFind( p_chk
->common
.p_father
, AVIFOURCC_strh
, 0 ) ) )
392 msg_Err( (vlc_object_t
*)s
, "malformed avi file" );
393 AVI_READCHUNK_EXIT( p_chk
->common
.i_chunk_size
> 0 ? VLC_EGENERIC
: AVI_ZEROSIZED_CHUNK
);
396 switch( p_strh
->strh
.i_type
)
398 case( AVIFOURCC_auds
):
399 p_chk
->strf
.auds
.i_cat
= AUDIO_ES
;
400 p_chk
->strf
.auds
.p_wf
= xmalloc( __MAX( p_chk
->common
.i_chunk_size
, sizeof( WAVEFORMATEX
) ) );
401 if ( !p_chk
->strf
.auds
.p_wf
)
403 AVI_READCHUNK_EXIT( VLC_ENOMEM
);
405 AVI_READ2BYTES( p_chk
->strf
.auds
.p_wf
->wFormatTag
);
406 AVI_READ2BYTES( p_chk
->strf
.auds
.p_wf
->nChannels
);
407 AVI_READ4BYTES( p_chk
->strf
.auds
.p_wf
->nSamplesPerSec
);
408 AVI_READ4BYTES( p_chk
->strf
.auds
.p_wf
->nAvgBytesPerSec
);
409 AVI_READ2BYTES( p_chk
->strf
.auds
.p_wf
->nBlockAlign
);
410 AVI_READ2BYTES( p_chk
->strf
.auds
.p_wf
->wBitsPerSample
);
412 if( p_chk
->strf
.auds
.p_wf
->wFormatTag
!= WAVE_FORMAT_PCM
413 && p_chk
->common
.i_chunk_size
> sizeof( WAVEFORMATEX
) )
415 AVI_READ2BYTES( p_chk
->strf
.auds
.p_wf
->cbSize
);
417 /* prevent segfault */
418 if( p_chk
->strf
.auds
.p_wf
->cbSize
>
419 p_chk
->common
.i_chunk_size
- sizeof( WAVEFORMATEX
) )
421 p_chk
->strf
.auds
.p_wf
->cbSize
=
422 p_chk
->common
.i_chunk_size
- sizeof( WAVEFORMATEX
);
425 if( p_chk
->strf
.auds
.p_wf
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
427 msg_Dbg( s
, "Extended header found" );
432 p_chk
->strf
.auds
.p_wf
->cbSize
= 0;
434 if( p_chk
->strf
.auds
.p_wf
->cbSize
> 0 )
436 memcpy( &p_chk
->strf
.auds
.p_wf
[1] ,
437 p_buff
+ 8 + sizeof( WAVEFORMATEX
), /* 8=fourcc+size */
438 p_chk
->strf
.auds
.p_wf
->cbSize
);
441 msg_Dbg( (vlc_object_t
*)s
,
442 "strf: audio:0x%4.4x channels:%d %dHz %dbits/sample %dkbps",
443 p_chk
->strf
.auds
.p_wf
->wFormatTag
,
444 p_chk
->strf
.auds
.p_wf
->nChannels
,
445 p_chk
->strf
.auds
.p_wf
->nSamplesPerSec
,
446 p_chk
->strf
.auds
.p_wf
->wBitsPerSample
,
447 p_chk
->strf
.auds
.p_wf
->nAvgBytesPerSec
* 8 / 1000 );
450 case( AVIFOURCC_vids
):
451 p_strh
->strh
.i_samplesize
= 0; /* XXX for ffmpeg avi file */
452 p_chk
->strf
.vids
.i_cat
= VIDEO_ES
;
453 p_chk
->strf
.vids
.p_bih
= xmalloc( __MAX( p_chk
->common
.i_chunk_size
,
454 sizeof( *p_chk
->strf
.vids
.p_bih
) ) );
455 if ( !p_chk
->strf
.vids
.p_bih
)
457 AVI_READCHUNK_EXIT( VLC_ENOMEM
);
459 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biSize
);
460 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biWidth
);
461 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biHeight
);
462 AVI_READ2BYTES( p_chk
->strf
.vids
.p_bih
->biPlanes
);
463 AVI_READ2BYTES( p_chk
->strf
.vids
.p_bih
->biBitCount
);
464 AVI_READFOURCC( p_chk
->strf
.vids
.p_bih
->biCompression
);
465 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biSizeImage
);
466 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biXPelsPerMeter
);
467 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biYPelsPerMeter
);
468 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biClrUsed
);
469 AVI_READ4BYTES( p_chk
->strf
.vids
.p_bih
->biClrImportant
);
470 if( p_chk
->strf
.vids
.p_bih
->biSize
> p_chk
->common
.i_chunk_size
)
472 p_chk
->strf
.vids
.p_bih
->biSize
= p_chk
->common
.i_chunk_size
;
474 if ( p_chk
->common
.i_chunk_size
> sizeof(VLC_BITMAPINFOHEADER
) )
476 uint64_t i_extrasize
= p_chk
->common
.i_chunk_size
- sizeof(VLC_BITMAPINFOHEADER
);
478 /* There's a color palette appended, set up VLC_BITMAPINFO */
479 memcpy( &p_chk
->strf
.vids
.p_bih
[1],
480 p_buff
+ 8 + sizeof(VLC_BITMAPINFOHEADER
), /* 8=fourrc+size */
483 if ( !p_chk
->strf
.vids
.p_bih
->biClrUsed
)
484 p_chk
->strf
.vids
.p_bih
->biClrUsed
= (1 << p_chk
->strf
.vids
.p_bih
->biBitCount
);
486 if( i_extrasize
/ sizeof(uint32_t) > UINT32_MAX
)
487 p_chk
->strf
.vids
.p_bih
->biClrUsed
= UINT32_MAX
;
490 p_chk
->strf
.vids
.p_bih
->biClrUsed
=
491 __MIN( i_extrasize
/ sizeof(uint32_t),
492 p_chk
->strf
.vids
.p_bih
->biClrUsed
);
495 /* stay within VLC's limits */
496 p_chk
->strf
.vids
.p_bih
->biClrUsed
=
497 __MIN( VIDEO_PALETTE_COLORS_MAX
, p_chk
->strf
.vids
.p_bih
->biClrUsed
);
499 else p_chk
->strf
.vids
.p_bih
->biClrUsed
= 0;
501 msg_Dbg( (vlc_object_t
*)s
,
502 "strf: video:%4.4s %"PRIu32
"x%"PRIu32
" planes:%d %dbpp",
503 (char*)&p_chk
->strf
.vids
.p_bih
->biCompression
,
504 (uint32_t)p_chk
->strf
.vids
.p_bih
->biWidth
,
505 (uint32_t)p_chk
->strf
.vids
.p_bih
->biHeight
,
506 p_chk
->strf
.vids
.p_bih
->biPlanes
,
507 p_chk
->strf
.vids
.p_bih
->biBitCount
);
512 p_chk
->strf
.common
.i_cat
= UNKNOWN_ES
;
514 case( AVIFOURCC_txts
):
515 p_chk
->strf
.common
.i_cat
= SPU_ES
;
518 msg_Warn( (vlc_object_t
*)s
, "unknown stream type: %4.4s",
519 (char*)&p_strh
->strh
.i_type
);
520 p_chk
->strf
.common
.i_cat
= UNKNOWN_ES
;
523 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
525 static void AVI_ChunkFree_strf( avi_chunk_t
*p_chk
)
527 avi_chunk_strf_t
*p_strf
= (avi_chunk_strf_t
*)p_chk
;
528 if( p_strf
->common
.i_cat
== AUDIO_ES
)
530 FREENULL( p_strf
->auds
.p_wf
);
532 else if( p_strf
->common
.i_cat
== VIDEO_ES
)
534 FREENULL( p_strf
->vids
.p_bih
);
538 static int AVI_ChunkRead_strd( stream_t
*s
, avi_chunk_t
*p_chk
)
540 if ( p_chk
->common
.i_chunk_size
== 0 )
542 msg_Dbg( (vlc_object_t
*)s
, "Zero sized pre-JUNK section met" );
543 return AVI_ZEROSIZED_CHUNK
;
547 p_chk
->strd
.p_data
= xmalloc( p_chk
->common
.i_chunk_size
);
548 memcpy( p_chk
->strd
.p_data
, p_buff
+ 8, p_chk
->common
.i_chunk_size
);
549 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
552 static void AVI_ChunkFree_strd( avi_chunk_t
*p_chk
)
554 free( p_chk
->strd
.p_data
);
557 static int AVI_ChunkRead_idx1( stream_t
*s
, avi_chunk_t
*p_chk
)
559 unsigned int i_count
, i_index
;
563 i_count
= __MIN( (int64_t)p_chk
->common
.i_chunk_size
, i_read
) / 16;
565 p_chk
->idx1
.i_entry_count
= i_count
;
566 p_chk
->idx1
.i_entry_max
= i_count
;
569 p_chk
->idx1
.entry
= xcalloc( i_count
, sizeof( idx1_entry_t
) );
571 for( i_index
= 0; i_index
< i_count
; i_index
++ )
573 AVI_READFOURCC( p_chk
->idx1
.entry
[i_index
].i_fourcc
);
574 AVI_READ4BYTES( p_chk
->idx1
.entry
[i_index
].i_flags
);
575 AVI_READ4BYTES( p_chk
->idx1
.entry
[i_index
].i_pos
);
576 AVI_READ4BYTES( p_chk
->idx1
.entry
[i_index
].i_length
);
581 p_chk
->idx1
.entry
= NULL
;
584 msg_Dbg( (vlc_object_t
*)s
, "idx1: index entry:%d", i_count
);
586 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
589 static void AVI_ChunkFree_idx1( avi_chunk_t
*p_chk
)
591 p_chk
->idx1
.i_entry_count
= 0;
592 p_chk
->idx1
.i_entry_max
= 0;
593 FREENULL( p_chk
->idx1
.entry
);
598 static int AVI_ChunkRead_indx( stream_t
*s
, avi_chunk_t
*p_chk
)
600 unsigned int i_count
, i
;
602 avi_chunk_indx_t
*p_indx
= (avi_chunk_indx_t
*)p_chk
;
606 AVI_READ2BYTES( p_indx
->i_longsperentry
);
607 AVI_READ1BYTE ( p_indx
->i_indexsubtype
);
608 AVI_READ1BYTE ( p_indx
->i_indextype
);
609 AVI_READ4BYTES( p_indx
->i_entriesinuse
);
611 AVI_READ4BYTES( p_indx
->i_id
);
612 p_indx
->idx
.std
= NULL
;
613 p_indx
->idx
.field
= NULL
;
614 p_indx
->idx
.super
= NULL
;
616 if( p_indx
->i_indextype
== AVI_INDEX_OF_CHUNKS
&& p_indx
->i_indexsubtype
== 0 )
618 AVI_READ8BYTES( p_indx
->i_baseoffset
);
619 AVI_READ4BYTES( i_dummy
);
621 i_count
= __MIN( p_indx
->i_entriesinuse
, i_read
/ 8 );
622 p_indx
->i_entriesinuse
= i_count
;
623 p_indx
->idx
.std
= xcalloc( i_count
, sizeof( indx_std_entry_t
) );
625 for( i
= 0; i
< i_count
; i
++ )
627 AVI_READ4BYTES( p_indx
->idx
.std
[i
].i_offset
);
628 AVI_READ4BYTES( p_indx
->idx
.std
[i
].i_size
);
631 else if( p_indx
->i_indextype
== AVI_INDEX_OF_CHUNKS
&& p_indx
->i_indexsubtype
== AVI_INDEX_2FIELD
)
633 AVI_READ8BYTES( p_indx
->i_baseoffset
);
634 AVI_READ4BYTES( i_dummy
);
636 i_count
= __MIN( p_indx
->i_entriesinuse
, i_read
/ 12 );
637 p_indx
->i_entriesinuse
= i_count
;
638 p_indx
->idx
.field
= xcalloc( i_count
, sizeof( indx_field_entry_t
) );
639 for( i
= 0; i
< i_count
; i
++ )
641 AVI_READ4BYTES( p_indx
->idx
.field
[i
].i_offset
);
642 AVI_READ4BYTES( p_indx
->idx
.field
[i
].i_size
);
643 AVI_READ4BYTES( p_indx
->idx
.field
[i
].i_offsetfield2
);
646 else if( p_indx
->i_indextype
== AVI_INDEX_OF_INDEXES
)
648 p_indx
->i_baseoffset
= 0;
649 AVI_READ4BYTES( i_dummy
);
650 AVI_READ4BYTES( i_dummy
);
651 AVI_READ4BYTES( i_dummy
);
653 i_count
= __MIN( p_indx
->i_entriesinuse
, i_read
/ 16 );
654 p_indx
->i_entriesinuse
= i_count
;
655 p_indx
->idx
.super
= xcalloc( i_count
, sizeof( indx_super_entry_t
) );
657 for( i
= 0; i
< i_count
; i
++ )
659 AVI_READ8BYTES( p_indx
->idx
.super
[i
].i_offset
);
660 AVI_READ4BYTES( p_indx
->idx
.super
[i
].i_size
);
661 AVI_READ4BYTES( p_indx
->idx
.super
[i
].i_duration
);
666 msg_Warn( (vlc_object_t
*)s
, "unknown type/subtype index" );
670 msg_Dbg( (vlc_object_t
*)s
, "indx: type=%d subtype=%d entry=%d", p_indx
->i_indextype
, p_indx
->i_indexsubtype
, p_indx
->i_entriesinuse
);
672 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
674 static void AVI_ChunkFree_indx( avi_chunk_t
*p_chk
)
676 avi_chunk_indx_t
*p_indx
= (avi_chunk_indx_t
*)p_chk
;
678 FREENULL( p_indx
->idx
.std
);
679 FREENULL( p_indx
->idx
.field
);
680 FREENULL( p_indx
->idx
.super
);
683 static int AVI_ChunkRead_vprp( stream_t
*s
, avi_chunk_t
*p_chk
)
685 avi_chunk_vprp_t
*p_vprp
= (avi_chunk_vprp_t
*)p_chk
;
689 AVI_READ4BYTES( p_vprp
->i_video_format_token
);
690 AVI_READ4BYTES( p_vprp
->i_video_standard
);
691 AVI_READ4BYTES( p_vprp
->i_vertical_refresh
);
692 AVI_READ4BYTES( p_vprp
->i_h_total_in_t
);
693 AVI_READ4BYTES( p_vprp
->i_v_total_in_lines
);
694 AVI_READ4BYTES( p_vprp
->i_frame_aspect_ratio
);
695 AVI_READ4BYTES( p_vprp
->i_frame_width_in_pixels
);
696 AVI_READ4BYTES( p_vprp
->i_frame_height_in_pixels
);
697 AVI_READ4BYTES( p_vprp
->i_nb_fields_per_frame
);
698 for( unsigned i
= 0; i
< __MIN( p_vprp
->i_nb_fields_per_frame
, 2 ); i
++ )
700 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_compressed_bm_height
);
701 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_compressed_bm_width
);
702 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_valid_bm_height
);
703 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_valid_bm_width
);
704 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_valid_bm_x_offset
);
705 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_valid_bm_y_offset
);
706 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_video_x_offset_in_t
);
707 AVI_READ4BYTES( p_vprp
->field_info
[i
].i_video_y_valid_start_line
);
711 msg_Dbg( (vlc_object_t
*)s
, "vprp: format:%d standard:%d",
712 p_vprp
->i_video_format_token
, p_vprp
->i_video_standard
);
714 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
717 static int AVI_ChunkRead_dmlh( stream_t
*s
, avi_chunk_t
*p_chk
)
719 avi_chunk_dmlh_t
*p_dmlh
= (avi_chunk_dmlh_t
*)p_chk
;
723 AVI_READ4BYTES( p_dmlh
->dwTotalFrames
);
726 msg_Dbg( (vlc_object_t
*)s
, "dmlh: dwTotalFrames %d",
727 p_dmlh
->dwTotalFrames
);
729 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
734 vlc_fourcc_t i_fourcc
;
735 const char *psz_type
;
738 { AVIFOURCC_IARL
, "Archive location" },
739 { AVIFOURCC_IART
, "Artist" },
740 { AVIFOURCC_ICMS
, "Commisioned" },
741 { AVIFOURCC_ICMT
, "Comments" },
742 { AVIFOURCC_ICOP
, "Copyright" },
743 { AVIFOURCC_ICRD
, "Creation date" },
744 { AVIFOURCC_ICRP
, "Cropped" },
745 { AVIFOURCC_IDIM
, "Dimensions" },
746 { AVIFOURCC_IDPI
, "Dots per inch" },
747 { AVIFOURCC_IENG
, "Engineer" },
748 { AVIFOURCC_IGNR
, "Genre" },
749 { AVIFOURCC_ISGN
, "Secondary Genre" },
750 { AVIFOURCC_IKEY
, "Keywords" },
751 { AVIFOURCC_ILGT
, "Lightness" },
752 { AVIFOURCC_IMED
, "Medium" },
753 { AVIFOURCC_INAM
, "Name" },
754 { AVIFOURCC_IPLT
, "Palette setting" },
755 { AVIFOURCC_IPRD
, "Product" },
756 { AVIFOURCC_ISBJ
, "Subject" },
757 { AVIFOURCC_ISFT
, "Software" },
758 { AVIFOURCC_ISHP
, "Sharpness" },
759 { AVIFOURCC_ISRC
, "Source" },
760 { AVIFOURCC_ISRF
, "Source form" },
761 { AVIFOURCC_ITCH
, "Technician" },
762 { AVIFOURCC_ISMP
, "Time code" },
763 { AVIFOURCC_IDIT
, "Digitalization time" },
764 { AVIFOURCC_IWRI
, "Writer" },
765 { AVIFOURCC_IPRO
, "Producer" },
766 { AVIFOURCC_ICNM
, "Cinematographer" },
767 { AVIFOURCC_IPDS
, "Production designer" },
768 { AVIFOURCC_IEDT
, "Editor" },
769 { AVIFOURCC_ICDS
, "Costume designer" },
770 { AVIFOURCC_IMUS
, "Music" },
771 { AVIFOURCC_ISTD
, "Production studio" },
772 { AVIFOURCC_IDST
, "Distributor" },
773 { AVIFOURCC_ICNT
, "Country" },
774 { AVIFOURCC_ISTR
, "Starring" },
775 { AVIFOURCC_IFRM
, "Total number of parts" },
776 { AVIFOURCC_strn
, "Stream name" },
777 { AVIFOURCC_IAS1
, "First Language" },
778 { AVIFOURCC_IAS2
, "Second Language" },
779 { AVIFOURCC_IAS3
, "Third Language" },
780 { AVIFOURCC_IAS4
, "Fourth Language" },
781 { AVIFOURCC_IAS5
, "Fifth Language" },
782 { AVIFOURCC_IAS6
, "Sixth Language" },
783 { AVIFOURCC_IAS7
, "Seventh Language" },
784 { AVIFOURCC_IAS8
, "Eighth Language" },
785 { AVIFOURCC_IAS9
, "Ninth Language" },
790 static int AVI_ChunkRead_strz( stream_t
*s
, avi_chunk_t
*p_chk
)
793 avi_chunk_STRING_t
*p_strz
= (avi_chunk_STRING_t
*)p_chk
;
796 for( i_index
= 0;; i_index
++)
798 if( !AVI_strz_type
[i_index
].i_fourcc
||
799 AVI_strz_type
[i_index
].i_fourcc
== p_strz
->i_chunk_fourcc
)
804 p_strz
->p_type
= strdup( AVI_strz_type
[i_index
].psz_type
);
805 p_strz
->p_str
= xmalloc( p_strz
->i_chunk_size
+ 1);
807 if( p_strz
->i_chunk_size
)
809 memcpy( p_strz
->p_str
, p_read
, p_strz
->i_chunk_size
);
811 p_strz
->p_str
[p_strz
->i_chunk_size
] = 0;
814 msg_Dbg( (vlc_object_t
*)s
, "%4.4s: %s : %s",
815 (char*)&p_strz
->i_chunk_fourcc
, p_strz
->p_type
, p_strz
->p_str
);
817 AVI_READCHUNK_EXIT( VLC_SUCCESS
);
819 static void AVI_ChunkFree_strz( avi_chunk_t
*p_chk
)
821 avi_chunk_STRING_t
*p_strz
= (avi_chunk_STRING_t
*)p_chk
;
822 FREENULL( p_strz
->p_type
);
823 FREENULL( p_strz
->p_str
);
826 static int AVI_ChunkRead_nothing( stream_t
*s
, avi_chunk_t
*p_chk
)
828 return AVI_NextChunk( s
, p_chk
);
830 static void AVI_ChunkFree_nothing( avi_chunk_t
*p_chk
)
837 vlc_fourcc_t i_fourcc
;
838 int (*AVI_ChunkRead_function
)( stream_t
*s
, avi_chunk_t
*p_chk
);
839 void (*AVI_ChunkFree_function
)( avi_chunk_t
*p_chk
);
840 } AVI_Chunk_Function
[] =
842 { AVIFOURCC_RIFF
, AVI_ChunkRead_list
, AVI_ChunkFree_nothing
},
843 { AVIFOURCC_ON2
, AVI_ChunkRead_list
, AVI_ChunkFree_nothing
},
844 { AVIFOURCC_LIST
, AVI_ChunkRead_list
, AVI_ChunkFree_nothing
},
845 { AVIFOURCC_avih
, AVI_ChunkRead_avih
, AVI_ChunkFree_nothing
},
846 { AVIFOURCC_ON2h
, AVI_ChunkRead_avih
, AVI_ChunkFree_nothing
},
847 { AVIFOURCC_strh
, AVI_ChunkRead_strh
, AVI_ChunkFree_nothing
},
848 { AVIFOURCC_strf
, AVI_ChunkRead_strf
, AVI_ChunkFree_strf
},
849 { AVIFOURCC_strd
, AVI_ChunkRead_strd
, AVI_ChunkFree_strd
},
850 { AVIFOURCC_idx1
, AVI_ChunkRead_idx1
, AVI_ChunkFree_idx1
},
851 { AVIFOURCC_indx
, AVI_ChunkRead_indx
, AVI_ChunkFree_indx
},
852 { AVIFOURCC_vprp
, AVI_ChunkRead_vprp
, AVI_ChunkFree_nothing
},
853 { AVIFOURCC_JUNK
, AVI_ChunkRead_nothing
, AVI_ChunkFree_nothing
},
854 { AVIFOURCC_dmlh
, AVI_ChunkRead_dmlh
, AVI_ChunkFree_nothing
},
856 { AVIFOURCC_IARL
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
857 { AVIFOURCC_IART
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
858 { AVIFOURCC_ICMS
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
859 { AVIFOURCC_ICMT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
860 { AVIFOURCC_ICOP
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
861 { AVIFOURCC_ICRD
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
862 { AVIFOURCC_ICRP
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
863 { AVIFOURCC_IDIM
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
864 { AVIFOURCC_IDPI
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
865 { AVIFOURCC_IENG
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
866 { AVIFOURCC_IGNR
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
867 { AVIFOURCC_ISGN
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
868 { AVIFOURCC_IKEY
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
869 { AVIFOURCC_ILGT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
870 { AVIFOURCC_IMED
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
871 { AVIFOURCC_INAM
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
872 { AVIFOURCC_IPLT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
873 { AVIFOURCC_IPRD
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
874 { AVIFOURCC_ISBJ
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
875 { AVIFOURCC_ISFT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
876 { AVIFOURCC_ISHP
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
877 { AVIFOURCC_ISRC
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
878 { AVIFOURCC_ISRF
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
879 { AVIFOURCC_ITCH
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
880 { AVIFOURCC_ISMP
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
881 { AVIFOURCC_IDIT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
882 { AVIFOURCC_ILNG
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
883 { AVIFOURCC_IRTD
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
884 { AVIFOURCC_IWEB
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
885 { AVIFOURCC_IPRT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
886 { AVIFOURCC_IWRI
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
887 { AVIFOURCC_IPRO
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
888 { AVIFOURCC_ICNM
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
889 { AVIFOURCC_IPDS
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
890 { AVIFOURCC_IEDT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
891 { AVIFOURCC_ICDS
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
892 { AVIFOURCC_IMUS
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
893 { AVIFOURCC_ISTD
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
894 { AVIFOURCC_IDST
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
895 { AVIFOURCC_ICNT
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
896 { AVIFOURCC_ISTR
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
897 { AVIFOURCC_IFRM
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
898 { AVIFOURCC_IAS1
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
899 { AVIFOURCC_IAS2
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
900 { AVIFOURCC_IAS3
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
901 { AVIFOURCC_IAS4
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
902 { AVIFOURCC_IAS5
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
903 { AVIFOURCC_IAS6
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
904 { AVIFOURCC_IAS7
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
905 { AVIFOURCC_IAS8
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
906 { AVIFOURCC_IAS9
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
909 { AVIFOURCC_strn
, AVI_ChunkRead_strz
, AVI_ChunkFree_strz
},
913 static int AVI_ChunkFunctionFind( vlc_fourcc_t i_fourcc
)
915 unsigned int i_index
;
916 for( i_index
= 0; ; i_index
++ )
918 if( ( AVI_Chunk_Function
[i_index
].i_fourcc
== i_fourcc
)||
919 ( AVI_Chunk_Function
[i_index
].i_fourcc
== 0 ) )
926 int AVI_ChunkRead( stream_t
*s
, avi_chunk_t
*p_chk
, avi_chunk_t
*p_father
)
932 msg_Warn( (vlc_object_t
*)s
, "cannot read null chunk" );
936 if( AVI_ChunkReadCommon( s
, p_chk
) )
938 msg_Warn( (vlc_object_t
*)s
, "cannot read one chunk" );
942 if( p_chk
->common
.i_chunk_fourcc
== VLC_FOURCC( 0, 0, 0, 0 ) )
944 msg_Warn( (vlc_object_t
*)s
, "found null fourcc chunk (corrupted file?)" );
945 return AVI_ZERO_FOURCC
;
947 p_chk
->common
.p_father
= p_father
;
949 i_index
= AVI_ChunkFunctionFind( p_chk
->common
.i_chunk_fourcc
);
950 if( AVI_Chunk_Function
[i_index
].AVI_ChunkRead_function
)
952 int i_return
= AVI_Chunk_Function
[i_index
].AVI_ChunkRead_function( s
, p_chk
);
953 if ( i_return
== AVI_ZEROSIZED_CHUNK
|| i_return
== AVI_ZERO_FOURCC
)
957 return AVI_NextChunk( s
, ( i_return
== AVI_ZEROSIZED_CHUNK
) ? p_chk
: p_father
);
961 else if( ( ((char*)&p_chk
->common
.i_chunk_fourcc
)[0] == 'i' &&
962 ((char*)&p_chk
->common
.i_chunk_fourcc
)[1] == 'x' ) ||
963 ( ((char*)&p_chk
->common
.i_chunk_fourcc
)[2] == 'i' &&
964 ((char*)&p_chk
->common
.i_chunk_fourcc
)[3] == 'x' ) )
966 p_chk
->common
.i_chunk_fourcc
= AVIFOURCC_indx
;
967 return AVI_ChunkRead_indx( s
, p_chk
);
970 msg_Warn( (vlc_object_t
*)s
, "unknown chunk: %4.4s (not loaded)",
971 (char*)&p_chk
->common
.i_chunk_fourcc
);
972 return AVI_NextChunk( s
, p_chk
);
975 void AVI_ChunkFree( stream_t
*s
,
979 avi_chunk_t
*p_child
, *p_next
;
986 /* Free all child chunk */
987 p_child
= p_chk
->common
.p_first
;
990 p_next
= p_child
->common
.p_next
;
991 AVI_ChunkFree( s
, p_child
);
996 i_index
= AVI_ChunkFunctionFind( p_chk
->common
.i_chunk_fourcc
);
997 if( AVI_Chunk_Function
[i_index
].AVI_ChunkFree_function
)
1000 msg_Dbg( (vlc_object_t
*)s
, "free chunk %4.4s",
1001 (char*)&p_chk
->common
.i_chunk_fourcc
);
1003 AVI_Chunk_Function
[i_index
].AVI_ChunkFree_function( p_chk
);
1007 msg_Warn( (vlc_object_t
*)s
, "unknown chunk: %4.4s (not unloaded)",
1008 (char*)&p_chk
->common
.i_chunk_fourcc
);
1010 p_chk
->common
.p_first
= NULL
;
1011 p_chk
->common
.p_last
= NULL
;
1016 static void AVI_ChunkDumpDebug_level( vlc_object_t
*p_obj
,
1017 avi_chunk_t
*p_chk
, unsigned i_level
)
1019 avi_chunk_t
*p_child
;
1022 if( i_level
>= (sizeof(str
) - 1)/4 )
1025 memset( str
, ' ', sizeof( str
) );
1026 for( unsigned i
= 1; i
< i_level
; i
++ )
1030 if( p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_RIFF
||
1031 p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_ON2
||
1032 p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_LIST
)
1034 snprintf( &str
[i_level
* 4], sizeof(str
) - 4*i_level
,
1035 "%c %4.4s-%4.4s size:%"PRIu64
" pos:%"PRIu64
,
1036 i_level
? '+' : '*',
1037 (char*)&p_chk
->common
.i_chunk_fourcc
,
1038 (char*)&p_chk
->list
.i_type
,
1039 p_chk
->common
.i_chunk_size
,
1040 p_chk
->common
.i_chunk_pos
);
1044 snprintf( &str
[i_level
* 4], sizeof(str
) - 4*i_level
,
1045 "+ %4.4s size:%"PRIu64
" pos:%"PRIu64
,
1046 (char*)&p_chk
->common
.i_chunk_fourcc
,
1047 p_chk
->common
.i_chunk_size
,
1048 p_chk
->common
.i_chunk_pos
);
1050 msg_Dbg( p_obj
, "%s", str
);
1052 p_child
= p_chk
->common
.p_first
;
1055 AVI_ChunkDumpDebug_level( p_obj
, p_child
, i_level
+ 1 );
1056 p_child
= p_child
->common
.p_next
;
1060 int AVI_ChunkReadRoot( stream_t
*s
, avi_chunk_t
*p_root
)
1062 avi_chunk_list_t
*p_list
= (avi_chunk_list_t
*)p_root
;
1066 vlc_stream_Control( s
, STREAM_CAN_SEEK
, &b_seekable
);
1068 p_list
->i_chunk_pos
= 0;
1069 p_list
->i_chunk_size
= stream_Size( s
);
1070 p_list
->i_chunk_fourcc
= AVIFOURCC_LIST
;
1071 p_list
->p_father
= NULL
;
1072 p_list
->p_next
= NULL
;
1073 p_list
->p_first
= NULL
;
1074 p_list
->p_last
= NULL
;
1076 p_list
->i_type
= VLC_FOURCC( 'r', 'o', 'o', 't' );
1080 p_chk
= xmalloc( sizeof( avi_chunk_t
) );
1081 memset( p_chk
, 0, sizeof( avi_chunk_t
) );
1082 if( !p_root
->common
.p_first
)
1084 p_root
->common
.p_first
= p_chk
;
1088 p_root
->common
.p_last
->common
.p_next
= p_chk
;
1090 p_root
->common
.p_last
= p_chk
;
1092 if( AVI_ChunkRead( s
, p_chk
, p_root
) ||
1093 ( vlc_stream_Tell( s
) >=
1094 (off_t
)p_chk
->common
.p_father
->common
.i_chunk_pos
+
1095 (off_t
)__EVEN( p_chk
->common
.p_father
->common
.i_chunk_size
) ) )
1099 /* If we can't seek then stop when we 've found first RIFF-AVI */
1100 if( p_chk
->common
.i_chunk_fourcc
== AVIFOURCC_RIFF
&&
1101 p_chk
->list
.i_type
== AVIFOURCC_AVI
&& !b_seekable
)
1107 AVI_ChunkDumpDebug_level( (vlc_object_t
*)s
, p_root
, 0 );
1111 void AVI_ChunkFreeRoot( stream_t
*s
,
1112 avi_chunk_t
*p_chk
)
1114 AVI_ChunkFree( s
, p_chk
);
1118 int AVI_ChunkCount_( avi_chunk_t
*p_chk
, vlc_fourcc_t i_fourcc
)
1121 avi_chunk_t
*p_child
;
1129 p_child
= p_chk
->common
.p_first
;
1132 if( p_child
->common
.i_chunk_fourcc
== i_fourcc
||
1133 ( p_child
->common
.i_chunk_fourcc
== AVIFOURCC_LIST
&&
1134 p_child
->list
.i_type
== i_fourcc
) )
1138 p_child
= p_child
->common
.p_next
;
1143 void *AVI_ChunkFind_( avi_chunk_t
*p_chk
,
1144 vlc_fourcc_t i_fourcc
, int i_number
)
1146 avi_chunk_t
*p_child
;
1151 p_child
= p_chk
->common
.p_first
;
1155 if( p_child
->common
.i_chunk_fourcc
== i_fourcc
||
1156 ( p_child
->common
.i_chunk_fourcc
== AVIFOURCC_LIST
&&
1157 p_child
->list
.i_type
== i_fourcc
) )
1167 p_child
= p_child
->common
.p_next
;