1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2011-2014 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
28 #define LSMASH_IMPORTER_INTERNAL
31 /***************************************************************************
32 SMPTE VC-1 importer (only for Advanced Profile)
35 ***************************************************************************/
36 #include "codecs/vc1.h"
41 vc1_sequence_header_t first_sequence
;
42 lsmash_media_ts_list_t ts_list
;
43 uint8_t composition_reordering_present
;
44 uint32_t max_au_length
;
45 uint32_t num_undecodable
;
46 uint64_t last_ref_intra_cts
;
49 static void remove_vc1_importer( vc1_importer_t
*vc1_imp
)
53 vc1_cleanup_parser( &vc1_imp
->info
);
54 lsmash_free( vc1_imp
->ts_list
.timestamp
);
55 lsmash_free( vc1_imp
);
58 static void vc1_importer_cleanup( importer_t
*importer
)
60 debug_if( importer
&& importer
->info
)
61 remove_vc1_importer( importer
->info
);
64 static vc1_importer_t
*create_vc1_importer( importer_t
*importer
)
66 vc1_importer_t
*vc1_imp
= lsmash_malloc_zero( sizeof(vc1_importer_t
) );
69 if( vc1_setup_parser( &vc1_imp
->info
, 0 ) < 0 )
71 remove_vc1_importer( vc1_imp
);
77 static inline int vc1_complete_au( vc1_access_unit_t
*access_unit
, vc1_picture_info_t
*picture
, int probe
)
79 if( !picture
->present
)
82 memcpy( access_unit
->data
, access_unit
->incomplete_data
, access_unit
->incomplete_data_length
);
83 access_unit
->data_length
= access_unit
->incomplete_data_length
;
84 access_unit
->incomplete_data_length
= 0;
85 vc1_update_au_property( access_unit
, picture
);
89 static inline void vc1_append_ebdu_to_au( vc1_access_unit_t
*access_unit
, uint8_t *ebdu
, uint32_t ebdu_length
, int probe
)
92 memcpy( access_unit
->incomplete_data
+ access_unit
->incomplete_data_length
, ebdu
, ebdu_length
);
93 /* Note: access_unit->incomplete_data_length shall be 0 immediately after AU has completed.
94 * Therefore, possible_au_length in vc1_get_access_unit_internal() can't be used here
95 * to avoid increasing AU length monotonously through the entire stream. */
96 access_unit
->incomplete_data_length
+= ebdu_length
;
99 static int vc1_get_au_internal_succeeded( vc1_importer_t
*vc1_imp
)
101 vc1_access_unit_t
*access_unit
= &vc1_imp
->info
.access_unit
;
102 access_unit
->number
+= 1;
106 static int vc1_get_au_internal_failed( vc1_importer_t
*vc1_imp
, int complete_au
, int ret
)
108 vc1_access_unit_t
*access_unit
= &vc1_imp
->info
.access_unit
;
110 access_unit
->number
+= 1;
114 static int vc1_importer_get_access_unit_internal( importer_t
*importer
, int probe
)
116 vc1_importer_t
*vc1_imp
= (vc1_importer_t
*)importer
->info
;
117 vc1_info_t
*info
= &vc1_imp
->info
;
118 vc1_stream_buffer_t
*sb
= &info
->buffer
;
119 vc1_access_unit_t
*access_unit
= &info
->access_unit
;
120 lsmash_bs_t
*bs
= importer
->bs
;
122 access_unit
->data_length
= 0;
127 uint64_t trailing_zero_bytes
;
128 uint64_t ebdu_length
= vc1_find_next_start_code_prefix( bs
, &bdu_type
, &trailing_zero_bytes
);
129 if( ebdu_length
<= VC1_START_CODE_LENGTH
&& lsmash_bs_is_end( bs
, ebdu_length
) )
131 /* For the last EBDU.
132 * This EBDU already has been appended into the latest access unit and parsed. */
133 vc1_complete_au( access_unit
, &info
->picture
, probe
);
134 return vc1_get_au_internal_succeeded( vc1_imp
);
136 else if( bdu_type
== 0xFF )
138 lsmash_log( importer
, LSMASH_LOG_ERROR
, "a forbidden BDU type is detected.\n" );
139 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, LSMASH_ERR_INVALID_DATA
);
141 uint64_t next_ebdu_head_pos
= info
->ebdu_head_pos
143 + trailing_zero_bytes
;
147 fprintf( stderr
, "BDU type: %"PRIu8
" \n", bdu_type
);
148 fprintf( stderr
, " EBDU position: %"PRIx64
" \n", info
->ebdu_head_pos
);
149 fprintf( stderr
, " EBDU length: %"PRIx64
" (%"PRIu64
")\n", ebdu_length
, ebdu_length
);
150 fprintf( stderr
, " trailing_zero_bytes: %"PRIx64
" \n", trailing_zero_bytes
);
151 fprintf( stderr
, " Next EBDU position: %"PRIx64
" \n", next_ebdu_head_pos
);
154 if( bdu_type
>= 0x0A && bdu_type
<= 0x0F )
156 /* Complete the current access unit if encountered delimiter of current access unit. */
157 if( vc1_find_au_delimit_by_bdu_type( bdu_type
, info
->prev_bdu_type
) )
158 /* The last video coded EBDU belongs to the access unit you want at this time. */
159 complete_au
= vc1_complete_au( access_unit
, &info
->picture
, probe
);
160 /* Increase the buffer if needed. */
161 uint64_t possible_au_length
= access_unit
->incomplete_data_length
+ ebdu_length
;
162 if( sb
->bank
->buffer_size
< possible_au_length
163 && (err
= vc1_supplement_buffer( sb
, access_unit
, 2 * possible_au_length
)) < 0 )
165 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to increase the buffer size.\n" );
166 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, err
);
168 /* Process EBDU by its BDU type and append it to access unit. */
169 uint8_t *ebdu
= lsmash_bs_get_buffer_data( bs
);
172 /* FRM_SC: Frame start code
173 * FLD_SC: Field start code
174 * SLC_SC: Slice start code
175 * SEQ_SC: Sequence header start code
176 * EP_SC: Entry-point start code
177 * PIC_L: Picture layer
179 * SEQ_L: Sequence layer
180 * EP_L: Entry-point layer */
182 * For the Progressive or Frame Interlace mode, shall signal the beginning of a new video frame.
183 * For the Field Interlace mode, shall signal the beginning of a sequence of two independently coded video fields.
184 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][[SLC_SC][SLC_L] (optional)] ... */
185 if( (err
= vc1_parse_advanced_picture( info
->bits
, &info
->sequence
, &info
->picture
, sb
->rbdu
, ebdu
, ebdu_length
)) < 0 )
187 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to parse a frame.\n" );
188 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, err
);
191 * Shall only be used for Field Interlaced frames
192 * and shall only be used to signal the beginning of the second field of the frame.
193 * [FRM_SC][PIC_L][FLD_SC][PIC_L][[SLC_SC][SLC_L] (optional)] ...
194 * Field start code is followed by INTERLACE_FIELD_PICTURE_FIELD2() which doesn't have info of its field picture type.*/
197 * Shall not be used for start code of the first slice of a frame.
198 * Shall not be used for start code of the first slice of an interlace field coded picture.
199 * [FRM_SC][PIC_L][[FLD_SC][PIC_L] (optional)][SLC_SC][SLC_L][[SLC_SC][SLC_L] (optional)] ...
200 * Slice layer may repeat frame header. We just ignore it. */
201 info
->dvc1_param
.slice_present
= 1;
203 case 0x0E : /* Entry-point header
204 * Entry-point indicates the direct followed frame is a start of group of frames.
205 * Entry-point doesn't indicates the frame is a random access point when multiple sequence headers are present,
206 * since it is necessary to decode sequence header which subsequent frames belong to for decoding them.
207 * Entry point shall be followed by
208 * 1. I-picture - progressive or frame interlace
209 * 2. I/I-picture, I/P-picture, or P/I-picture - field interlace
210 * [[SEQ_SC][SEQ_L] (optional)][EP_SC][EP_L][FRM_SC][PIC_L] ... */
211 if( (err
= vc1_parse_entry_point_header( info
, ebdu
, ebdu_length
, probe
)) < 0 )
213 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to parse an entry point.\n" );
214 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, err
);
216 /* Signal random access type of the frame that follows this entry-point header. */
217 info
->picture
.closed_gop
= info
->entry_point
.closed_entry_point
;
218 info
->picture
.random_accessible
= info
->dvc1_param
.multiple_sequence
? info
->picture
.start_of_sequence
: 1;
220 case 0x0F : /* Sequence header
221 * [SEQ_SC][SEQ_L][EP_SC][EP_L][FRM_SC][PIC_L] ... */
222 if( (err
= vc1_parse_sequence_header( info
, ebdu
, ebdu_length
, probe
)) < 0 )
224 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to parse a sequence header.\n" );
225 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, err
);
227 /* The frame that is the first frame after this sequence header shall be a random accessible point. */
228 info
->picture
.start_of_sequence
= 1;
229 if( probe
&& !vc1_imp
->first_sequence
.present
)
230 vc1_imp
->first_sequence
= info
->sequence
;
232 default : /* End-of-sequence (0x0A) */
235 /* Append the current EBDU into the end of an incomplete access unit. */
236 vc1_append_ebdu_to_au( access_unit
, ebdu
, ebdu_length
, probe
);
238 else /* We don't support other BDU types such as user data yet. */
239 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, LSMASH_ERR_PATCH_WELCOME
);
240 /* Move to the first byte of the next EBDU. */
241 info
->prev_bdu_type
= bdu_type
;
242 if( lsmash_bs_read_seek( bs
, next_ebdu_head_pos
, SEEK_SET
) != next_ebdu_head_pos
)
244 lsmash_log( importer
, LSMASH_LOG_ERROR
, "failed to seek the next start code suffix.\n" );
245 return vc1_get_au_internal_failed( vc1_imp
, complete_au
, LSMASH_ERR_NAMELESS
);
247 /* Check if no more data to read from the stream. */
248 if( !lsmash_bs_is_end( bs
, VC1_START_CODE_PREFIX_LENGTH
) )
249 info
->ebdu_head_pos
= next_ebdu_head_pos
;
250 /* If there is no more data in the stream, and flushed chunk of EBDUs, flush it as complete AU here. */
251 else if( access_unit
->incomplete_data_length
&& access_unit
->data_length
== 0 )
253 vc1_complete_au( access_unit
, &info
->picture
, probe
);
254 return vc1_get_au_internal_succeeded( vc1_imp
);
257 return vc1_get_au_internal_succeeded( vc1_imp
);
261 static inline void vc1_importer_check_eof( importer_t
*importer
, vc1_access_unit_t
*access_unit
)
263 if( lsmash_bs_is_end( importer
->bs
, 0 ) && access_unit
->incomplete_data_length
== 0 )
264 importer
->status
= IMPORTER_EOF
;
266 importer
->status
= IMPORTER_OK
;
269 static int vc1_importer_get_accessunit( importer_t
*importer
, uint32_t track_number
, lsmash_sample_t
**p_sample
)
271 if( !importer
->info
)
272 return LSMASH_ERR_NAMELESS
;
273 if( track_number
!= 1 )
274 return LSMASH_ERR_FUNCTION_PARAM
;
275 vc1_importer_t
*vc1_imp
= (vc1_importer_t
*)importer
->info
;
276 vc1_info_t
*info
= &vc1_imp
->info
;
277 importer_status current_status
= importer
->status
;
278 if( current_status
== IMPORTER_ERROR
)
279 return LSMASH_ERR_NAMELESS
;
280 if( current_status
== IMPORTER_EOF
)
282 int err
= vc1_importer_get_access_unit_internal( importer
, 0 );
285 importer
->status
= IMPORTER_ERROR
;
288 lsmash_sample_t
*sample
= lsmash_create_sample( vc1_imp
->max_au_length
);
290 return LSMASH_ERR_MEMORY_ALLOC
;
292 vc1_access_unit_t
*access_unit
= &info
->access_unit
;
293 vc1_importer_check_eof( importer
, access_unit
);
294 sample
->dts
= vc1_imp
->ts_list
.timestamp
[ access_unit
->number
- 1 ].dts
;
295 sample
->cts
= vc1_imp
->ts_list
.timestamp
[ access_unit
->number
- 1 ].cts
;
296 sample
->prop
.leading
= access_unit
->independent
297 || access_unit
->non_bipredictive
298 || sample
->cts
>= vc1_imp
->last_ref_intra_cts
299 ? ISOM_SAMPLE_IS_NOT_LEADING
: ISOM_SAMPLE_IS_UNDECODABLE_LEADING
;
300 if( access_unit
->independent
&& !access_unit
->disposable
)
301 vc1_imp
->last_ref_intra_cts
= sample
->cts
;
302 if( vc1_imp
->composition_reordering_present
&& !access_unit
->disposable
&& !access_unit
->closed_gop
)
303 sample
->prop
.allow_earlier
= QT_SAMPLE_EARLIER_PTS_ALLOWED
;
304 sample
->prop
.independent
= access_unit
->independent
? ISOM_SAMPLE_IS_INDEPENDENT
: ISOM_SAMPLE_IS_NOT_INDEPENDENT
;
305 sample
->prop
.disposable
= access_unit
->disposable
? ISOM_SAMPLE_IS_DISPOSABLE
: ISOM_SAMPLE_IS_NOT_DISPOSABLE
;
306 sample
->prop
.redundant
= ISOM_SAMPLE_HAS_NO_REDUNDANCY
;
307 if( access_unit
->random_accessible
)
308 /* All random access point is a sync sample even if it's an open RAP. */
309 sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
310 sample
->length
= access_unit
->data_length
;
311 memcpy( sample
->data
, access_unit
->data
, access_unit
->data_length
);
312 return current_status
;
315 static lsmash_video_summary_t
*vc1_create_summary( vc1_info_t
*info
, vc1_sequence_header_t
*sequence
, uint32_t max_au_length
)
317 if( !info
->sequence
.present
|| !info
->entry_point
.present
)
319 lsmash_video_summary_t
*summary
= (lsmash_video_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_VIDEO
);
322 lsmash_codec_specific_t
*specific
= lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_ISOM_VIDEO_VC_1
,
323 LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
);
324 specific
->data
.unstructured
= lsmash_create_vc1_specific_info( &info
->dvc1_param
, &specific
->size
);
325 if( !specific
->data
.unstructured
326 || lsmash_add_entry( &summary
->opaque
->list
, specific
) < 0 )
328 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
329 lsmash_destroy_codec_specific_data( specific
);
332 summary
->sample_type
= ISOM_CODEC_TYPE_VC_1_VIDEO
;
333 summary
->max_au_length
= max_au_length
;
334 summary
->timescale
= sequence
->framerate_numerator
;
335 summary
->timebase
= sequence
->framerate_denominator
;
336 summary
->vfr
= !sequence
->framerate_flag
;
337 summary
->sample_per_field
= 0;
338 summary
->width
= sequence
->disp_horiz_size
;
339 summary
->height
= sequence
->disp_vert_size
;
340 summary
->par_h
= sequence
->aspect_width
;
341 summary
->par_v
= sequence
->aspect_height
;
342 summary
->color
.primaries_index
= sequence
->color_prim
;
343 summary
->color
.transfer_index
= sequence
->transfer_char
;
344 summary
->color
.matrix_index
= sequence
->matrix_coef
;
348 static int vc1_analyze_whole_stream
353 /* Parse all EBDU in the stream for preparation of calculating timestamps. */
354 uint32_t cts_alloc
= (1 << 12) * sizeof(uint64_t);
355 uint64_t *cts
= lsmash_malloc( cts_alloc
);
357 return LSMASH_ERR_MEMORY_ALLOC
; /* Failed to allocate CTS list */
358 uint32_t num_access_units
= 0;
359 uint32_t num_consecutive_b
= 0;
360 lsmash_class_t
*logger
= &(lsmash_class_t
){ "VC-1" };
361 lsmash_log( &logger
, LSMASH_LOG_INFO
, "Analyzing stream as VC-1\r" );
362 vc1_importer_t
*vc1_imp
= (vc1_importer_t
*)importer
->info
;
363 vc1_info_t
*info
= &vc1_imp
->info
;
364 importer
->status
= IMPORTER_OK
;
366 while( importer
->status
!= IMPORTER_EOF
)
369 lsmash_log( &logger
, LSMASH_LOG_INFO
, "Analyzing stream as VC-1: %"PRIu32
"\n", num_access_units
+ 1 );
371 if( (err
= vc1_importer_get_access_unit_internal( importer
, 1 )) < 0 )
373 vc1_importer_check_eof( importer
, &info
->access_unit
);
374 /* In the case where B-pictures exist
376 * I[0]P[1]P[2]B[3]B[4]P[5]...
380 * I[0]P[1]B[3]B[4]P[2]P[5]...
383 * We assumes B or BI-pictures always be present in the stream here. */
384 if( !info
->access_unit
.disposable
)
386 /* Apply CTS of the last B-picture plus 1 to the last non-B-picture. */
387 if( num_access_units
> num_consecutive_b
)
388 cts
[ num_access_units
- num_consecutive_b
- 1 ] = num_access_units
;
389 num_consecutive_b
= 0;
391 else /* B or BI-picture */
393 /* B and BI-pictures shall be output or displayed in the same order as they are encoded. */
394 cts
[ num_access_units
] = num_access_units
;
396 info
->dvc1_param
.bframe_present
= 1;
398 if( cts_alloc
<= num_access_units
* sizeof(uint64_t) )
400 uint32_t alloc
= 2 * num_access_units
* sizeof(uint64_t);
401 uint64_t *temp
= lsmash_realloc( cts
, alloc
);
404 err
= LSMASH_ERR_MEMORY_ALLOC
;
405 goto fail
; /* Failed to re-allocate CTS list */
410 vc1_imp
->max_au_length
= LSMASH_MAX( info
->access_unit
.data_length
, vc1_imp
->max_au_length
);
413 if( num_access_units
> num_consecutive_b
)
414 cts
[ num_access_units
- num_consecutive_b
- 1 ] = num_access_units
;
417 err
= LSMASH_ERR_INVALID_DATA
;
420 /* Construct timestamps. */
421 lsmash_media_ts_t
*timestamp
= lsmash_malloc( num_access_units
* sizeof(lsmash_media_ts_t
) );
424 err
= LSMASH_ERR_MEMORY_ALLOC
;
425 goto fail
; /* Failed to allocate timestamp list */
427 for( uint32_t i
= 1; i
< num_access_units
; i
++ )
428 if( cts
[i
] < cts
[i
- 1] )
430 vc1_imp
->composition_reordering_present
= 1;
433 if( vc1_imp
->composition_reordering_present
)
434 for( uint32_t i
= 0; i
< num_access_units
; i
++ )
436 timestamp
[i
].cts
= cts
[i
];
437 timestamp
[i
].dts
= i
;
440 for( uint32_t i
= 0; i
< num_access_units
; i
++ )
441 timestamp
[i
].cts
= timestamp
[i
].dts
= i
;
443 lsmash_log_refresh_line( &logger
);
445 for( uint32_t i
= 0; i
< num_access_units
; i
++ )
446 fprintf( stderr
, "Timestamp[%"PRIu32
"]: DTS=%"PRIu64
", CTS=%"PRIu64
"\n", i
, timestamp
[i
].dts
, timestamp
[i
].cts
);
448 vc1_imp
->ts_list
.sample_count
= num_access_units
;
449 vc1_imp
->ts_list
.timestamp
= timestamp
;
452 lsmash_log_refresh_line( &logger
);
457 static int vc1_importer_probe( importer_t
*importer
)
459 /* Find the first start code. */
460 vc1_importer_t
*vc1_imp
= create_vc1_importer( importer
);
462 return LSMASH_ERR_MEMORY_ALLOC
;
463 lsmash_bs_t
*bs
= importer
->bs
;
464 uint64_t first_ebdu_head_pos
= 0;
468 /* The first EBDU in decoding order of the stream shall have start code (0x000001). */
469 if( 0x000001 == lsmash_bs_show_be24( bs
, first_ebdu_head_pos
) )
471 /* Invalid if encountered any value of non-zero before the first start code. */
472 if( lsmash_bs_show_byte( bs
, first_ebdu_head_pos
) )
474 err
= LSMASH_ERR_INVALID_DATA
;
477 ++first_ebdu_head_pos
;
479 /* OK. It seems the stream has a sequence header of VC-1. */
480 importer
->info
= vc1_imp
;
481 vc1_info_t
*info
= &vc1_imp
->info
;
482 lsmash_bs_read_seek( bs
, first_ebdu_head_pos
, SEEK_SET
);
483 info
->ebdu_head_pos
= first_ebdu_head_pos
;
484 if( (err
= vc1_analyze_whole_stream( importer
)) < 0 )
486 lsmash_video_summary_t
*summary
= vc1_create_summary( info
, &vc1_imp
->first_sequence
, vc1_imp
->max_au_length
);
489 err
= LSMASH_ERR_NAMELESS
;
492 if( lsmash_add_entry( importer
->summaries
, summary
) < 0 )
494 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
495 err
= LSMASH_ERR_MEMORY_ALLOC
;
498 /* Go back to layer of the first EBDU. */
499 importer
->status
= IMPORTER_OK
;
500 lsmash_bs_read_seek( bs
, first_ebdu_head_pos
, SEEK_SET
);
501 info
->prev_bdu_type
= 0xFF; /* 0xFF is a forbidden value. */
502 info
->ebdu_head_pos
= first_ebdu_head_pos
;
503 uint8_t *temp_access_unit
= info
->access_unit
.data
;
504 uint8_t *temp_incomplete_access_unit
= info
->access_unit
.incomplete_data
;
505 memset( &info
->access_unit
, 0, sizeof(vc1_access_unit_t
) );
506 info
->access_unit
.data
= temp_access_unit
;
507 info
->access_unit
.incomplete_data
= temp_incomplete_access_unit
;
508 memset( &info
->picture
, 0, sizeof(vc1_picture_info_t
) );
511 remove_vc1_importer( vc1_imp
);
512 importer
->info
= NULL
;
513 lsmash_remove_entries( importer
->summaries
, lsmash_cleanup_summary
);
517 static uint32_t vc1_importer_get_last_delta( importer_t
*importer
, uint32_t track_number
)
519 debug_if( !importer
|| !importer
->info
)
521 vc1_importer_t
*vc1_imp
= (vc1_importer_t
*)importer
->info
;
522 if( !vc1_imp
|| track_number
!= 1 || importer
->status
!= IMPORTER_EOF
)
524 return vc1_imp
->ts_list
.sample_count
526 : UINT32_MAX
; /* arbitrary */
529 const importer_functions vc1_importer
=
531 { "VC-1", offsetof( importer_t
, log_level
) },
534 vc1_importer_get_accessunit
,
535 vc1_importer_get_last_delta
,