1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2008 the VideoLAN team
7 * Authors: David Flynn <davidf@rd.bbc.co.uk>
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
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 *****************************************************************************/
24 /* Dirac packetizer, formed of three parts:
25 * 1) Bitstream synchroniser (dirac_DoSync)
26 * - Given an arbitrary sequence of bytes, extract whole Dirac Data Units
27 * - Maps timestamps in supplied block_t's to the extracted Data Unit
28 * A time stamp applies to the next Data Unit to commence at, or after
29 * the first byte of the block_t with the timestamp.
30 * 2) Encapsulation Unit generation (dirac_BuildEncapsulationUnit)
31 * - Takes multiple well formed Dirac Data Units and forms them into a
32 * single encapsulation unit, suitable for muxing.
33 * - Sorts out any time stamps so that they only apply to pictures.
34 * 3) Timestamp generator (dirac_TimeGenPush)
35 * - Many streams will not be correctly timestamped, ie, DTS&PTS for
36 * every encapsulation unit. Timestamp generator syncs to avaliable
37 * timestamps and produces DTS&PTS for each encapsulation unit.
38 * - For 'Occasional' missing PTS|DTS:
39 * Missing timestamp is generated using interpolation from last
41 * - for All PTS missing:
42 * It is assumed that DTS values are fake, and are actually
43 * in the sequence of the PTS values at the output of a decoder.
44 * Fill in PTS by copying from DTS (accounting for reordering,
45 * by simulating reorder buffer); adjust DTS to provide correct
46 * value. This is how demuxers like AVI work.
47 * - for All DTS missing:
48 * (Ie, PTS is present), reorder buffer is simulated to determine
49 * PTS for each encapsulation unit.
50 * - NB, doesn't handle all pts missing with real dts. (no way to
51 * distinguish from the fake dts case.)
53 * DIRAC_NON_DATED is used to show a block should not have a time stamp
54 * associated (ie, don't interpolate a counter). At the ouput, these
55 * blocks get dated with the last used timestamp (or are merged with
56 * another encapsulation unit).
59 /*****************************************************************************
61 *****************************************************************************/
68 #include <vlc_common.h>
69 #include <vlc_plugin.h>
70 #include <vlc_codec.h>
71 #include <vlc_block.h>
74 #include <vlc_block_helper.h>
76 #define SANITIZE_PREV_PARSE_OFFSET 1
78 /*****************************************************************************
80 *****************************************************************************/
81 static int Open ( vlc_object_t
* );
82 static void Close( vlc_object_t
* );
85 set_category( CAT_SOUT
)
86 set_subcategory( SUBCAT_SOUT_PACKETIZER
)
87 set_description( N_("Dirac packetizer") )
88 set_capability( "packetizer", 50 )
89 set_callbacks( Open
, Close
)
92 /*****************************************************************************
94 *****************************************************************************/
98 block_bytestream_t bytestream
;
102 /* recovered timestamp from bytesteram for use
103 * by synchroniser: should only get reset by the
104 * synchronizer upon a discontinuity sentinel */
108 /* build encapsulation unit state */
109 block_t
*p_eu
; /*< Current encapsulation unit being built */
110 block_t
**pp_eu_last
;
111 uint32_t u_eu_last_npo
; /* last next_parse_offset at input to encapsulation */
115 /* timestamp generator state */
116 date_t dts
; /*< timegen decode clock, increments at picture rate */
117 bool b_dts
; /*< timegen decode clock valid */
119 bool b_pts
; /*< timegen presentation time valid */
120 mtime_t i_pts
; /*< timegen presentation time of picture u_pts_picnum */
121 uint32_t u_pts_picnum
; /*< picture number of timegen presentation time */
123 mtime_t i_pts_offset
; /*< maximum time between pts and dts */
125 /* p_outqueue is the list of encapsulation units that have been
126 * fed to the timegenerator. the timegenerator stamps them in
127 * the order it solves the time. the main packetizer loop removes
128 * completed encapsulation units from the front */
130 block_t
**pp_outqueue_last
;
131 /* p_out_dts points to an element in p_outqueue. It is used for VLC's
132 * fake pts hidden in DTS hack, as used by AVI */
135 uint32_t u_tg_last_picnum
; /*< most recent picturenumber output from RoB */
136 bool b_tg_last_picnum
; /*< u_tg_last_picnum valid */
138 struct dirac_reorder_buffer
{
141 struct dirac_reorder_entry
{
142 struct dirac_reorder_entry
*p_next
;
145 } p_entries
[32], *p_head
, *p_empty
;
146 } reorder_buf
; /*< reorder buffer, used by timegenerator */
148 /* packetizer state */
149 mtime_t i_pts_last_out
; /*< last output [from packetizer] pts */
150 mtime_t i_dts_last_out
; /*< last output [from packetizer] dts */
157 enum picture_coding_mode_t
{
158 DIRAC_FRAME_CODING
=0,
159 DIRAC_FIELD_CODING
=1,
160 } u_picture_coding_mode
;
161 } seq_hdr
; /*< sequence header */
162 bool b_seen_seq_hdr
; /* sequence header valid */
163 bool b_seen_eos
; /* last data unit to be handled was an EOS */
167 uint32_t u_next_offset
;
168 uint32_t u_prev_offset
;
173 block_free_t pf_blk_release
;
174 /*> next_parse_offset of the final data unit in associated block_t */
175 uint32_t u_last_next_offset
;
176 /*> picture number is invalid if block has flags DIRAC_NON_DATED */
177 uint32_t u_picture_number
;
178 } dirac_block_encap_t
;
188 DIRAC_NON_DATED
= (1 << BLOCK_FLAG_PRIVATE_SHIFT
),
189 DIRAC_DISCARD
= (2 << BLOCK_FLAG_PRIVATE_SHIFT
),
198 * Block encapsulation functions.
199 * Things are greately simplified by associating some metadata
200 * with a block as it passes through the packetizer (saves having
201 * to determine it again)
203 * unfortunately p_block doesn't have a p_priv, so some fakage
205 * - Create a dummy block that has some extra storage, set up
206 * members to be identical to the actual block
207 * - Store private data there and pointer to orig block
208 * - modify block pointer to point to fake block
210 * NB, the add/new functions must not be used to blocks
211 * that are referenced in lists, etc., [in this code, this is ok]
212 * NB, don't call add on the same block multiple times (will leak)
214 * davidf has a patch that reverts this to use a p_priv in block_t.
222 static dirac_block_encap_t
*dirac_RemoveBlockEncap( block_t
*p_block
)
224 fake_block_t
*p_fake
= (fake_block_t
*)p_block
;
225 dirac_block_encap_t
*p_dbe
= p_fake
->p_priv
;
226 if( !p_dbe
) return NULL
;
227 p_fake
->p_priv
= NULL
;
228 p_dbe
->pf_blk_release
= NULL
;
232 static void dirac_ReleaseBlockAndEncap( block_t
*p_block
)
234 fake_block_t
*p_fake
= (fake_block_t
*)p_block
;
235 free( dirac_RemoveBlockEncap( p_block
) );
236 p_fake
->p_orig
->pf_release( p_fake
->p_orig
);
240 static void dirac_AddBlockEncap( block_t
**pp_block
, dirac_block_encap_t
*p_dbe
)
242 fake_block_t
*p_fake
= calloc( 1, sizeof( *p_fake
) );
243 assert( p_fake
); /* must not fail, fixby: adding a p_priv to block_t */
244 p_fake
->p_orig
= *pp_block
;
245 memcpy( &p_fake
->fake
, *pp_block
, sizeof( block_t
) );
246 *pp_block
= &p_fake
->fake
;
248 p_fake
->p_priv
= p_dbe
;
249 p_dbe
->pf_blk_release
= p_fake
->p_orig
->pf_release
;
250 p_fake
->fake
.pf_release
= dirac_ReleaseBlockAndEncap
;
253 static dirac_block_encap_t
*dirac_NewBlockEncap( block_t
**pp_block
)
255 dirac_block_encap_t
*p_dbe
= calloc( 1, sizeof( *p_dbe
) );
256 if( p_dbe
) dirac_AddBlockEncap( pp_block
, p_dbe
);
260 static dirac_block_encap_t
*dirac_GetBlockEncap( block_t
*p_block
)
262 return (dirac_block_encap_t
*) ((fake_block_t
*)p_block
)->p_priv
;
266 * General utility funcions
270 * given a chain of block_t, allocate and return an array containing
271 * pointers to all the blocks. (Acts as a replacement for the old p_prev
272 * member of block_t) */
273 static int block_ChainToArray( block_t
*p_block
, block_t
***ppp_array
)
279 block_ChainProperties( p_block
, &i_num_blocks
, NULL
, NULL
);
281 *ppp_array
= calloc( i_num_blocks
, sizeof( block_t
* ) );
282 if( !*ppp_array
) return 0;
284 for( int i
= 0; i
< i_num_blocks
; i
++ )
286 (*ppp_array
)[i
] = p_block
;
287 p_block
= p_block
->p_next
;
294 * Destructively find and recover the earliest timestamp from start of
295 * bytestream, upto i_length.
297 static void dirac_RecoverTimestamps ( decoder_t
*p_dec
, size_t i_length
)
299 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
300 block_t
*p_block
= p_sys
->bytestream
.p_block
;
302 /* Find the block with first non-flushed data */
303 size_t i_offset
= p_sys
->bytestream
.i_offset
;
304 for(; p_block
!= NULL
; p_block
= p_block
->p_next
)
306 if( i_offset
< p_block
->i_buffer
)
308 i_offset
-= p_block
->i_buffer
;
311 i_offset
+= i_length
;
312 for(; p_block
!= NULL
; p_block
= p_block
->p_next
)
314 if( p_sys
->i_sync_pts
<= VLC_TS_INVALID
&& p_sys
->i_sync_dts
<= VLC_TS_INVALID
)
316 /* oldest timestamp wins */
317 p_sys
->i_sync_pts
= p_block
->i_pts
;
318 p_sys
->i_sync_dts
= p_block
->i_dts
;
320 /* clear timestamps -- more than one data unit can come from a block */
321 p_block
->i_flags
= 0;
322 p_block
->i_pts
= p_block
->i_dts
= VLC_TS_INVALID
;
323 if( i_offset
< p_block
->i_buffer
)
325 i_offset
-= p_block
->i_buffer
;
329 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
330 static void dirac_BackdateDTS( block_t
*p_block
, block_t
*p_last
, date_t
*p_dts
)
332 /* Transverse p_last backwards. (no p_prev anymore) */
333 block_t
**pp_array
= NULL
;
334 int n
= block_ChainToArray( p_block
, &pp_array
);
335 while( n
) if( pp_array
[--n
] == p_last
) break;
336 /* want to start at p_last->p_prev */
339 if( pp_array
[n
]->i_flags
& DIRAC_NON_DATED
)
341 if( pp_array
[n
]->i_dts
<= VLC_TS_INVALID
)
342 pp_array
[n
]->i_dts
= date_Decrement( p_dts
, 1 );
347 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
348 static void dirac_BackdatePTS( block_t
*p_block
, block_t
*p_last
, date_t
*p_pts
, uint32_t u_pts_picnum
)
350 /* Transverse p_last backwards. (no p_prev anymore) */
351 block_t
**pp_array
= NULL
;
352 int n
= block_ChainToArray( p_block
, &pp_array
);
353 while( n
) if( pp_array
[--n
] == p_last
) break;
354 /* want to start at p_last->p_prev */
357 if( pp_array
[n
]->i_flags
& DIRAC_NON_DATED
)
359 if( pp_array
[n
]->i_dts
> VLC_TS_INVALID
)
361 dirac_block_encap_t
*dbe
= dirac_GetBlockEncap( pp_array
[n
] );
362 int32_t u_pic_num
= dbe
? dbe
->u_picture_number
: 0;
363 int32_t i_dist
= u_pic_num
- u_pts_picnum
;
366 pp_array
[n
]->i_pts
= date_Increment( &pts
, i_dist
);
368 pp_array
[n
]->i_pts
= date_Decrement( &pts
, -i_dist
);
374 * Dirac spec defined relations
377 static bool dirac_isEOS( uint8_t u_parse_code
) { return 0x10 == u_parse_code
; }
378 static bool dirac_isSeqHdr( uint8_t u_parse_code
) { return 0 == u_parse_code
; }
379 static bool dirac_isPicture( uint8_t u_parse_code
) { return 0x08 & u_parse_code
; }
380 static int dirac_numRefs( uint8_t u_parse_code
) { return 0x3 & u_parse_code
; }
382 static inline bool dirac_PictureNbeforeM( uint32_t u_n
, uint32_t u_m
)
384 /* specified as: u_n occurs before u_m if:
385 * (u_m - u_n) mod (1<<32) < D */
386 return (uint32_t)(u_m
- u_n
) < (1u<<31);
390 * Reorder buffer model
393 static void dirac_ReorderInit( struct dirac_reorder_buffer
*p_rb
)
395 memset( p_rb
, 0, sizeof(*p_rb
) );
396 p_rb
->u_size_max
= 2;
397 p_rb
->p_empty
= p_rb
->p_entries
;
398 p_rb
->p_entries
[31].p_next
= NULL
;
400 for( int i
= 0; i
< 31; i
++ )
401 p_rb
->p_entries
[i
].p_next
= &p_rb
->p_entries
[i
+1];
404 /* simulate the dirac picture reorder buffer */
405 static block_t
*dirac_Reorder( decoder_t
*p_dec
, block_t
*p_block_in
, uint32_t u_picnum
)
407 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
409 if( !p_sys
->reorder_buf
.u_size_max
)
410 /* reorder buffer disabled */
413 /* Modeling the reorder buffer:
414 * 1. If the reorder buffer is not full, insert picture for reordering.
415 * No picture is output by the system this picture period
416 * 2. If the reorder buffer is full:
417 * a. The picture decoded this period (u_picnum) bypasses the reorder
418 * buffer if it has a lower picture number than any entry in the
419 * reorder buffer. This picture is output by the system.
420 * b. Otherwise, the lowest picture number in the reorder buffer is
421 * removed from the buffer and output by the system. The current
422 * decoded picture (u_picnum) is inserted into the reorder buffer
425 block_t
*p_block
= NULL
;
426 /* Determine if the picture needs to be inserted */
427 if( p_sys
->reorder_buf
.u_size
== p_sys
->reorder_buf
.u_size_max
)
429 /* (2) reorder buffer is full */
430 if( !p_sys
->reorder_buf
.u_size_max
||
431 dirac_PictureNbeforeM( u_picnum
, p_sys
->reorder_buf
.p_head
->u_picnum
) )
433 /* (2a) current picture is first in order */
437 /* (2b) extract the youngest picture in the buffer */
438 p_block
= p_sys
->reorder_buf
.p_head
->p_eu
;
440 struct dirac_reorder_entry
*p_tmp
= p_sys
->reorder_buf
.p_head
;
441 p_sys
->reorder_buf
.p_head
= p_tmp
->p_next
;
442 p_tmp
->p_next
= p_sys
->reorder_buf
.p_empty
;
443 p_sys
->reorder_buf
.p_empty
= p_tmp
;
445 p_sys
->reorder_buf
.u_size
--;
448 /* (1) and (2b) both require u_picnum to be inserted */
449 struct dirac_reorder_entry
*p_current
= p_sys
->reorder_buf
.p_empty
;
450 p_sys
->reorder_buf
.p_empty
= p_current
->p_next
;
451 p_sys
->reorder_buf
.u_size
++;
453 /* insertion sort to keep p_head always sorted, earliest first */
454 struct dirac_reorder_entry
**pp_at
= &p_sys
->reorder_buf
.p_head
;
455 for( ; *pp_at
; pp_at
= &(*pp_at
)->p_next
)
456 if( dirac_PictureNbeforeM( u_picnum
, (*pp_at
)->u_picnum
) )
459 p_current
->u_picnum
= u_picnum
;
460 p_current
->p_eu
= p_block_in
;
461 p_current
->p_next
= *pp_at
;
468 * bytestream parsing and unmarshalling functions
471 static bool dirac_UnpackParseInfo( parse_info_t
*p_pi
, block_bytestream_t
*p_bs
,
475 if( VLC_SUCCESS
!= block_PeekOffsetBytes( p_bs
, u_offset
, p_d
, 13 ) )
478 if( p_d
[0] != 'B' || p_d
[1] != 'B' || p_d
[2] != 'C' || p_d
[3] != 'D' )
481 p_pi
->i_parse_code
= p_d
[4];
482 p_pi
->u_next_offset
= p_d
[5] << 24 | p_d
[6] << 16 | p_d
[7] << 8 | p_d
[8];
483 p_pi
->u_prev_offset
= p_d
[9] << 24 | p_d
[10] << 16 | p_d
[11] << 8 | p_d
[12];
487 static uint32_t dirac_uint( bs_t
*p_bs
)
489 uint32_t u_count
= 0, u_value
= 0;
490 while( !bs_eof( p_bs
) && !bs_read( p_bs
, 1 ) )
494 u_value
|= bs_read( p_bs
, 1 );
496 return (1 << u_count
) - 1 + u_value
;
499 static int dirac_bool( bs_t
*p_bs
)
501 return bs_read( p_bs
, 1 );
504 /* read in useful bits from sequence header */
505 static bool dirac_UnpackSeqHdr( struct seq_hdr_t
*p_sh
, block_t
*p_block
)
508 bs_init( &bs
, p_block
->p_buffer
, p_block
->i_buffer
);
509 bs_skip( &bs
, 13*8 ); /* parse_info_header */
510 dirac_uint( &bs
); /* major_version */
511 dirac_uint( &bs
); /* minor_version */
512 dirac_uint( &bs
); /* profile */
513 dirac_uint( &bs
); /* level */
515 uint32_t u_video_format
= dirac_uint( &bs
); /* index */
516 if( u_video_format
> 20 )
518 /* dont know how to parse this header */
522 static const struct {
524 } dirac_size_tbl
[] = {
525 {640,480}, {176,120}, {176,144}, {352,240}, {352,288}, {704,480},
526 {704,576}, {720,480}, {720,576}, {1280,720}, {1280,720}, {1920,1080},
527 {1920,1080}, {1920,1080}, {1920,1080}, {2048,1080}, {4096,2160},
528 {3840,2160}, {3840,2160}, {7680,4320}, {7680,4320},
531 p_sh
->u_width
= dirac_size_tbl
[u_video_format
].u_w
;
532 p_sh
->u_height
= dirac_size_tbl
[u_video_format
].u_h
;
533 if( dirac_bool( &bs
) )
535 p_sh
->u_width
= dirac_uint( &bs
); /* frame_width */
536 p_sh
->u_height
= dirac_uint( &bs
); /* frame_height */
539 if( dirac_bool( &bs
) )
541 dirac_uint( &bs
); /* chroma_format */
544 if( dirac_bool( &bs
) )
546 dirac_uint( &bs
); /* scan_format */
549 static const struct {
550 uint32_t u_n
/* numerator */, u_d
/* denominator */;
551 } dirac_frate_tbl
[] = { /* table 10.3 */
552 {1, 1}, /* this value is not used */
553 {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
554 {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
557 const unsigned dirac_frate_tbl_size
=
558 sizeof( dirac_frate_tbl
) / sizeof( *dirac_frate_tbl
);
560 static const uint32_t dirac_vidfmt_frate
[] = { /* table C.1 */
561 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
564 p_sh
->u_fps_num
= dirac_frate_tbl
[dirac_vidfmt_frate
[u_video_format
]].u_n
;
565 p_sh
->u_fps_den
= dirac_frate_tbl
[dirac_vidfmt_frate
[u_video_format
]].u_d
;
566 if( dirac_bool( &bs
) )
568 uint32_t frame_rate_index
= dirac_uint( &bs
);
569 p_sh
->u_fps_num
= dirac_frate_tbl
[frame_rate_index
].u_n
;
570 p_sh
->u_fps_den
= dirac_frate_tbl
[frame_rate_index
].u_d
;
571 if( frame_rate_index
>= dirac_frate_tbl_size
)
576 if( frame_rate_index
== 0 )
578 p_sh
->u_fps_num
= dirac_uint( &bs
); /* frame_rate_numerator */
579 p_sh
->u_fps_den
= dirac_uint( &bs
); /* frame_rate_denominator */
583 /* must have a valid framerate */
584 if( !p_sh
->u_fps_num
|| !p_sh
->u_fps_den
)
587 if( dirac_bool( &bs
) )
589 uint32_t par_index
= dirac_uint( &bs
);
592 dirac_uint( &bs
); /* par_num */
593 dirac_uint( &bs
); /* par_den */
597 if( dirac_bool( &bs
) )
599 dirac_uint( &bs
); /* clean_width */
600 dirac_uint( &bs
); /* clean_height */
601 dirac_uint( &bs
); /* clean_left_offset */
602 dirac_uint( &bs
); /* clean_top_offset */
605 if( dirac_bool( &bs
) )
607 uint32_t signal_range_index
= dirac_uint( &bs
);
608 if( !signal_range_index
)
610 dirac_uint( &bs
); /* luma_offset */
611 dirac_uint( &bs
); /* luma_excursion */
612 dirac_uint( &bs
); /* chroma_offset */
613 dirac_uint( &bs
); /* chroma_excursion */
617 if( dirac_bool( &bs
) )
619 uint32_t colour_spec_index
= dirac_uint( &bs
);
620 if( !colour_spec_index
)
622 if( dirac_bool( &bs
) )
624 dirac_uint( &bs
); /* colour_primaries_index */
626 if( dirac_bool( &bs
) )
628 dirac_uint( &bs
); /* colour_matrix_index */
630 if( dirac_bool( &bs
) )
632 dirac_uint( &bs
); /* transfer_function_index */
637 p_sh
->u_picture_coding_mode
= dirac_uint( &bs
);
643 * Data Unit marshalling functions
646 static block_t
*dirac_EmitEOS( decoder_t
*p_dec
, uint32_t i_prev_parse_offset
)
648 const uint8_t p_eos
[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
649 block_t
*p_block
= block_New( p_dec
, 13 );
652 memcpy( p_block
->p_buffer
, p_eos
, 13 );
654 SetDWBE( p_block
->p_buffer
+ 9, i_prev_parse_offset
);
656 p_block
->i_flags
= DIRAC_NON_DATED
;
664 * Bytestream synchronizer
665 * maps [Bytes] -> DataUnit
667 static block_t
*dirac_DoSync( decoder_t
*p_dec
)
669 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
672 static const uint8_t p_parsecode
[4] = {'B','B','C','D'};
674 switch( p_sys
->i_state
)
679 block_FindStartcodeFromOffset( &p_sys
->bytestream
, &p_sys
->i_offset
, p_parsecode
, 4 ) )
681 /* p_sys->i_offset will have been set to:
682 * end of bytestream - amount of prefix found
683 * can resume search from this point when more data arrives */
686 /* candidate parse_code_prefix has been found at p_sys->i_offset */
687 if( VLC_SUCCESS
!= block_PeekOffsetBytes( &p_sys
->bytestream
, p_sys
->i_offset
+ 12, NULL
, 0 ) )
689 /* insufficient data has been accumulated to fully extract
690 * a parse_info header. exit for now in the hope of more
691 * data later to retry at exactly the same point */
694 p_sys
->i_state
= TRY_SYNC
;
695 break; /* candidate found, try to sync */
697 case SYNCED
: /* -> TRY_SYNC | NOT_SYNCED */
698 /* sanity: can only reach this after having extracted a DU,
699 * which causes data to be consumed and local i_offset to be reset */
700 assert( p_sys
->i_offset
== 0 );
701 if( VLC_SUCCESS
!= block_PeekOffsetBytes( &p_sys
->bytestream
, 12, NULL
, 0 ) )
703 /* insufficient data has been accumulated to fully extract
704 * a parse_info header, retry later */
707 if( !dirac_UnpackParseInfo( &pu
, &p_sys
->bytestream
, 0 )
708 || !pu
.u_next_offset
|| (p_sys
->u_last_npo
!= pu
.u_prev_offset
) )
710 /* !a: not a valid parse info.
711 * !pu.u_next_offset: don't know the length of the data unit
712 * search for the next one that points back
713 * to this one to determine length.
714 * (p_sys->u_last_npo != pu.u_prev_offset): some desync
716 p_sys
->i_state
= NOT_SYNCED
;
719 if( pu
.u_next_offset
> 1024*1024 )
721 /* sanity check for erronious hugs next_parse_offsets
722 * (eg, 2^32-1) that would cause a very long wait
723 * and large space consumption: fall back to try sync */
724 p_sys
->i_state
= TRY_SYNC
;
727 /* check that the start of the next data unit is avaliable */
729 block_PeekOffsetBytes( &p_sys
->bytestream
, pu
.u_next_offset
+ 12, NULL
, 0 ) )
731 return NULL
; /* retry later */
733 /* attempt to syncronise backwards from pu.u_next_offset */
734 p_sys
->i_offset
= pu
.u_next_offset
;
736 case TRY_SYNC
: /* -> SYNCED | NOT_SYNCED */
738 if( !p_sys
->i_offset
)
739 goto sync_fail
; /* if a is at start of bytestream, b can't be in buffer */
742 bool a
= dirac_UnpackParseInfo( &pu_a
, &p_sys
->bytestream
, p_sys
->i_offset
);
743 if( !a
|| (pu_a
.u_prev_offset
> p_sys
->i_offset
) )
744 goto sync_fail
; /* b lies beyond start of bytestream: can't sync */
746 if( !pu_a
.u_prev_offset
)
748 if( p_sys
->i_state
== TRY_SYNC
)
750 goto sync_fail
; /* can't find different pu_b from pu_a */
752 /* state == SYNCED: already know where pu_b is.
753 * pu_a has probably been inserted by something that doesn't
754 * know what the last next_parse_offset was */
755 pu_a
.u_prev_offset
= pu
.u_next_offset
;
758 parse_info_t
*pu_b
= &pu
;
759 bool b
= dirac_UnpackParseInfo( pu_b
, &p_sys
->bytestream
, p_sys
->i_offset
- pu_a
.u_prev_offset
);
760 if( !b
|| (pu_b
->u_next_offset
&& pu_a
.u_prev_offset
!= pu_b
->u_next_offset
) )
762 /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
763 * just rely on finding a valid pu_b from pu_a. */
766 p_sys
->u_last_npo
= pu_b
->u_next_offset
;
767 if( !pu_b
->u_next_offset
) pu_b
->u_next_offset
= pu_a
.u_prev_offset
;
768 /* offset was pointing at pu_a, rewind to point at pu_b */
769 p_sys
->i_offset
-= pu_a
.u_prev_offset
;
770 p_sys
->i_state
= SYNCED
;
774 if( p_sys
->i_state
== SYNCED
) p_sys
->i_offset
= 0;
776 p_sys
->i_state
= NOT_SYNCED
;
777 break; /* find somewhere else to try again */
780 } while( SYNCED
!= p_sys
->i_state
);
783 * synced, attempt to extract a data unit
786 /* recover any timestamps from the data that is about to be flushed */
787 dirac_RecoverTimestamps( p_dec
, p_sys
->i_offset
);
789 /* flush everything upto the start of the DU */
790 block_SkipBytes( &p_sys
->bytestream
, p_sys
->i_offset
);
791 block_BytestreamFlush( &p_sys
->bytestream
);
794 /* setup the data unit buffer */
795 block_t
*p_block
= block_New( p_dec
, pu
.u_next_offset
);
799 p_block
->i_pts
= p_sys
->i_sync_pts
;
800 p_block
->i_dts
= p_sys
->i_sync_dts
;
801 p_sys
->i_sync_pts
= p_sys
->i_sync_dts
= VLC_TS_INVALID
;
803 /* recover any new timestamps from the data that is about to be consumed */
804 dirac_RecoverTimestamps( p_dec
, p_sys
->i_offset
);
806 block_GetBytes( &p_sys
->bytestream
, p_block
->p_buffer
, p_block
->i_buffer
);
808 /* save parse offset in private area for later use */
809 dirac_block_encap_t
*p_dbe
= dirac_NewBlockEncap( &p_block
);
810 if( p_dbe
) p_dbe
->u_last_next_offset
= pu
.u_next_offset
;
816 * Packet (Data Unit) inspection, learns parameters from sequence
817 * headers, sets up flags, drops unwanted data units, sets
818 * encapsulation unit termination policy
820 static int dirac_InspectDataUnit( decoder_t
*p_dec
, block_t
**pp_block
, block_t
*p_eu
)
822 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
823 block_t
*p_block
= *pp_block
;
824 uint8_t u_parse_code
= p_block
->p_buffer
[4];
826 if( dirac_isEOS( u_parse_code
) )
828 if( p_sys
->b_seen_eos
)
830 /* remove duplicate EOS packets */
831 block_Release( p_block
);
833 return DIRAC_DU_IN_EU
;
835 /* p_block is an EOS packet */
836 p_eu
->i_flags
|= BLOCK_FLAG_END_OF_SEQUENCE
;
837 /* for the moment, let this end an encapsulation unit */
838 /* seeing an eos packet requires a flush of the packetizer
839 * this is detected by the caller of this function */
840 p_sys
->b_seen_seq_hdr
= false;
841 p_sys
->b_seen_eos
= true;
842 return DIRAC_DU_ENDS_EU
;
844 /* let anything down streem know too */
846 Actually, this is a bad idea:
847 - It sets the discontinuity for every dirac EOS packet
848 which doesnt imply a time discontinuity.
849 - When the syncronizer detects a real discontinuity, it
850 should copy the flags through.
851 p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
855 p_sys
->b_seen_eos
= false;
857 if( dirac_isPicture( u_parse_code
) )
859 /* timestamps apply to pictures only */
860 p_eu
->i_dts
= p_sys
->i_eu_dts
;
861 p_eu
->i_pts
= p_sys
->i_eu_pts
;
862 p_sys
->i_eu_dts
= p_sys
->i_eu_pts
= VLC_TS_INVALID
;
864 if( !p_sys
->b_seen_seq_hdr
)
866 /* can't timestamp in this case, discard later
867 * so that the timestamps aren't lost */
868 p_eu
->i_flags
|= DIRAC_DISCARD
;
870 /* p_block is a picture -- it ends the 'encapsulation unit' */
871 if( dirac_numRefs( u_parse_code
) )
873 /* if this picture is not an I frame, ensure that the
874 * random access point flags are not set */
875 p_eu
->i_flags
&= ~BLOCK_FLAG_TYPE_I
;
877 dirac_block_encap_t
*p_dbe
= dirac_GetBlockEncap( p_block
);
878 if( p_dbe
&& p_block
->i_buffer
> 13+4 )
880 /* record the picture number to save the time gen functions
881 * from having to inspect the data for it */
882 p_dbe
->u_picture_number
= GetDWBE( p_block
->p_buffer
+ 13 );
884 return DIRAC_DU_ENDS_EU
;
887 if( dirac_isSeqHdr( u_parse_code
) )
889 if( !dirac_UnpackSeqHdr( &p_sys
->seq_hdr
, p_block
) )
891 /* couldn't parse the sequence header, just ignore it */
892 return DIRAC_DU_IN_EU
;
894 p_sys
->b_seen_seq_hdr
= true;
896 /* a sequence header followed by an I frame is a random
897 * access point; assume that this is the case */
898 p_eu
->i_flags
|= BLOCK_FLAG_TYPE_I
;
900 es_format_t
*p_es
= &p_dec
->fmt_out
;
902 p_es
->video
.i_width
= p_sys
->seq_hdr
.u_width
;
903 p_es
->video
.i_height
= p_sys
->seq_hdr
.u_height
;
905 vlc_ureduce( &p_es
->video
.i_frame_rate
, &p_es
->video
.i_frame_rate_base
906 , p_sys
->seq_hdr
.u_fps_num
, p_sys
->seq_hdr
.u_fps_den
, 0 );
908 /* when field coding, dts needs to be incremented in terms of field periods */
909 unsigned u_pics_per_sec
= p_sys
->seq_hdr
.u_fps_num
;
910 if( p_sys
->seq_hdr
.u_picture_coding_mode
== DIRAC_FIELD_CODING
)
914 date_Change( &p_sys
->dts
, u_pics_per_sec
, p_sys
->seq_hdr
.u_fps_den
);
916 /* TODO: set p_sys->reorder_buf.u_size_max */
917 p_sys
->i_pts_offset
= p_sys
->reorder_buf
.u_size_max
919 * p_es
->video
.i_frame_rate_base
/ p_es
->video
.i_frame_rate
+ 1;
921 /* stash a copy of the seqhdr
922 * - required for ogg muxing
923 * - useful for error checking
924 * - it isn't allowed to change until an eos */
925 free( p_es
->p_extra
);
926 p_es
->p_extra
= calloc( 1, p_block
->i_buffer
+ 13 );
930 return DIRAC_DU_IN_EU
;
932 p_es
->i_extra
= p_block
->i_buffer
;
933 memcpy( p_es
->p_extra
, p_block
->p_buffer
, p_block
->i_buffer
);
934 /* append EOS as per Ogg guidelines */
935 p_block
= dirac_EmitEOS( p_dec
, p_block
->i_buffer
);
938 memcpy( (uint8_t*)p_es
->p_extra
+ p_es
->i_extra
, p_block
->p_buffer
, 13 );
942 return DIRAC_DU_IN_EU
;
945 /* doesn't end an encapsulation unit */
946 return DIRAC_DU_IN_EU
;
950 * Encapsulation (packetization) suitable for all muxing standards
951 * maps [DataUnit] -> EncapsulationUnit
953 static block_t
*dirac_BuildEncapsulationUnit( decoder_t
*p_dec
, block_t
*p_block
)
955 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
957 assert(p_block
->i_buffer
>= 13 && 0x42424344 == GetDWBE( p_block
->p_buffer
));
959 if( p_sys
->i_eu_pts
<= VLC_TS_INVALID
&& p_sys
->i_eu_dts
<= VLC_TS_INVALID
)
961 /* earliest block with pts/dts gets to set the pts/dts for the dated
962 * encapsulation unit as a whole */
963 /* NB, the 'earliest block' criteria is aribtary */
964 if( p_block
->i_pts
> VLC_TS_INVALID
|| p_block
->i_dts
> VLC_TS_INVALID
)
966 p_sys
->i_eu_pts
= p_block
->i_pts
;
967 p_sys
->i_eu_dts
= p_block
->i_dts
;
971 /* inpectdataunit also updates flags for the EU.
972 * - if this is the first block in the EU, then it hasn't been added
973 * to the chain yet (so, p_block will become the front of the chain
974 * - otherwise, use the flags of the chain (first block) */
975 block_t
*p_eu
= p_sys
->p_eu
? p_sys
->p_eu
: p_block
;
976 int i_block
= dirac_InspectDataUnit( p_dec
, &p_block
, p_eu
);
980 /* block has been discarded during inspection */
981 /* becareful, don't discard anything that is dated,
982 * as this needs to go into the timegen loop. set
983 * the DIRAC_DISCARD block flag, and it'll be dropped
988 block_ChainLastAppend( &p_sys
->pp_eu_last
, p_block
);
990 dirac_block_encap_t
*p_dbe
= dirac_GetBlockEncap( p_block
);
991 #ifdef SANITIZE_PREV_PARSE_OFFSET
992 /* fixup prev_parse_offset to point to the last data unit
996 SetDWBE( p_block
->p_buffer
+ 9, p_sys
->u_eu_last_npo
);
997 p_sys
->u_eu_last_npo
= p_dbe
->u_last_next_offset
;
1001 if( i_block
!= DIRAC_DU_ENDS_EU
)
1003 /* encapsulation unit not ended */
1007 /* gather up encapsulation unit, reassociating the final
1008 * private state with the gathered block */
1009 block_t
*p_eu_last
= (block_t
*) p_sys
->pp_eu_last
- offsetof( block_t
, p_next
);
1010 p_dbe
= dirac_RemoveBlockEncap( p_eu_last
);
1012 uint8_t u_parse_code
= p_block
->p_buffer
[4];
1014 /* gather up the encapsulation unit */
1015 p_block
= block_ChainGather( p_sys
->p_eu
);
1016 assert( p_block
); /* block_ChainGather doesn't define when it frees chain */
1018 p_block
->i_flags
|= DIRAC_NON_DATED
;
1021 dirac_AddBlockEncap( &p_block
, p_dbe
);
1022 if( dirac_isPicture( u_parse_code
) ) p_block
->i_flags
&= ~DIRAC_NON_DATED
;
1025 p_sys
->pp_eu_last
= &p_sys
->p_eu
;
1030 * dirac_TimeGenPush:
1031 * @p_dec: vlc object
1032 * @p_block_in: whole encapsulation unit to generate timestamps for
1036 * 1: EOS occured, please flush and reset
1037 * 2: picture number discontinuity, please flush and reset
1039 static int dirac_TimeGenPush( decoder_t
*p_dec
, block_t
*p_block_in
)
1041 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1042 dirac_block_encap_t
*p_dbe
;
1044 if( p_block_in
->i_flags
& BLOCK_FLAG_END_OF_SEQUENCE
)
1046 /* NB, this test occurs after the timegen push, so as to
1047 * push the block into the output queue */
1051 if( p_block_in
->i_flags
& DIRAC_NON_DATED
)
1053 /* no picture found, which means p_block_in is a non-dated EU,
1054 * do not try and put a date on it */
1058 p_dbe
= dirac_GetBlockEncap( p_block_in
);
1059 uint32_t u_picnum
= p_dbe
? p_dbe
->u_picture_number
: 0;
1061 * Simple DTS regeneration:
1062 * - DTS values linearly increase in stream order.
1063 * - Every time a DTS occurs at the input, sync to it
1064 * - If this is the first DTS seen, backdate all the previous ones that are undated
1065 * - If a DTS is missing, guess that it increases by one picture period
1066 * - If never seen DTS, don't do anything
1069 * Simple PTS regeneration
1070 * - PTS values do not linearly increase in stream order.
1071 * - Every time a PTS occurs at the input, sync to it and record picture number
1072 * - If a PTS is missing, guess that it differs by the product of picture
1073 * period and difference between picture number of sync point and current picture
1074 * - If this is the first PTS seen, backdate all previous ones that are undated
1075 * - If never seen PTS, don't do anything
1078 * Stage 1, sync to input timestamps, backdate timestamps for old
1079 * EUs that are in the outqueue with missing dates
1081 if( p_block_in
->i_dts
> VLC_TS_INVALID
)
1083 /* if timestamps exist, sync to them */
1086 /* first dts seen, backdate any packets in outqueue */
1087 p_sys
->b_dts
= true;
1088 date_t dts
= p_sys
->dts
;
1089 dirac_BackdateDTS( p_sys
->p_outqueue
, p_block_in
, &dts
);
1092 if( p_block_in
->i_pts
> VLC_TS_INVALID
)
1094 /* if timestamps exist, sync to them */
1095 p_sys
->u_pts_picnum
= u_picnum
;
1096 p_sys
->i_pts
= p_block_in
->i_pts
;
1099 /* first pts seen, backdate any packets in outqueue */
1100 p_sys
->b_pts
= true;
1101 date_t pts
= p_sys
->dts
;
1102 date_Set( &pts
, p_sys
->i_pts
);
1103 dirac_BackdatePTS( p_sys
->p_outqueue
, p_block_in
, &pts
, p_sys
->u_pts_picnum
);
1107 * Stage 2, don't attempt to forwards interpolate timestamps for
1108 * blocks if the picture rates aren't known
1110 if( !p_sys
->b_seen_seq_hdr
)
1116 * Stage 3, for block_in, interpolate any missing timestamps
1118 if( p_sys
->b_dts
&& p_block_in
->i_dts
<= VLC_TS_INVALID
)
1120 /* dts has previously been seen, but not this time, interpolate */
1121 p_block_in
->i_dts
= date_Increment( &p_sys
->dts
, 1 );
1124 if( p_sys
->b_pts
&& p_block_in
->i_pts
<= VLC_TS_INVALID
)
1126 /* pts has previously been seen, but not this time, interpolate */
1127 date_t pts
= p_sys
->dts
;
1128 date_Set( &pts
, p_sys
->i_pts
);
1129 int32_t i_dist
= u_picnum
- p_sys
->u_pts_picnum
;
1131 p_block_in
->i_pts
= date_Increment( &pts
, i_dist
);
1133 p_block_in
->i_pts
= date_Decrement( &pts
, -i_dist
);
1136 /* If pts and dts have been seen, there is no need to simulate operation
1137 * of the decoder reorder buffer */
1138 /* If neither have been seen, there is little point in simulating */
1139 if( p_sys
->b_dts
== p_sys
->b_pts
)
1142 if( !p_sys
->p_out_dts
)
1143 p_sys
->p_out_dts
= p_sys
->p_outqueue
;
1145 /* model the reorder buffer */
1146 block_t
*p_block
= dirac_Reorder( p_dec
, p_block_in
, u_picnum
);
1150 /* A future ehancement is to stop modeling the reorder buffer as soon as
1151 * the first packet is output -- interpolate the past and freewheel for
1154 p_dbe
= dirac_GetBlockEncap( p_block
);
1155 u_picnum
= p_dbe
? p_dbe
->u_picture_number
: 0;
1156 if( p_sys
->b_tg_last_picnum
)
1158 if( dirac_PictureNbeforeM( u_picnum
, p_sys
->u_tg_last_picnum
) )
1160 msg_Warn( p_dec
, "stream jumped? %d < %d: resetting"
1161 , u_picnum
, p_sys
->u_tg_last_picnum
);
1162 /* pictures only emerge from the reorder buffer in sequence
1163 * if a stream suddenly jumped backwards without a signaling
1164 * a discontinuity, some pictures will get stuck in the RoB.
1166 /* this could be a bit less indiscriminate */
1167 p_dbe
= dirac_GetBlockEncap( p_sys
->p_outqueue
);
1168 uint32_t u_prev_parse_offset
= p_dbe
? p_dbe
->u_last_next_offset
: 0;
1169 block_ChainRelease( p_sys
->p_outqueue
);
1170 p_sys
->p_outqueue
= dirac_EmitEOS( p_dec
, u_prev_parse_offset
);
1171 if( p_sys
->p_outqueue
)
1172 p_sys
->p_outqueue
->i_flags
= BLOCK_FLAG_DISCONTINUITY
| DIRAC_NON_DATED
;
1173 /* return 2, so as not to reset the b_dts flags -- needed if
1174 * using the rawdirac demuxer with broken stream */
1178 p_sys
->b_tg_last_picnum
= true;
1179 p_sys
->u_tg_last_picnum
= u_picnum
;
1183 /* some demuxers (eg, AVI) will provide a series of fake dts values,
1184 * which are actually inorder pts values (ie, what should be seen at
1185 * the output of a decoder. A main reason for simulating the reorder
1186 * buffer is to turn the inorder fakedts into an out-of-order pts */
1187 p_block
->i_pts
= p_sys
->p_out_dts
->i_dts
;
1188 p_sys
->p_out_dts
->i_dts
= VLC_TS_INVALID
;
1191 /* If pts was copied from dts, the dts needs to be corrected to account for reordering*/
1192 /* If dts has never been seen, the same needs to happen */
1193 p_sys
->p_out_dts
->i_dts
= p_block
->i_pts
- p_sys
->i_pts_offset
;
1195 /* move dts pointer */
1196 if( p_sys
->p_out_dts
)
1197 p_sys
->p_out_dts
= p_sys
->p_out_dts
->p_next
;
1202 /*****************************************************************************
1203 * Packetize: form dated encapsulation units from anything
1204 *****************************************************************************/
1205 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
1207 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1208 block_t
*p_block
= NULL
;
1211 if( pp_block
&& *pp_block
)
1213 p_block
= *pp_block
;
1216 if( p_block
->i_flags
& BLOCK_FLAG_DISCONTINUITY
)
1218 /* pre-emptively insert an EOS at a discontinuity, protects
1219 * any decoders from any sudden changes */
1220 block_Release( p_block
);
1221 p_block
= dirac_EmitEOS( p_dec
, 0 );
1224 p_block
->p_next
= dirac_EmitEOS( p_dec
, 13 );
1225 /* need two EOS to ensure it gets detected by syncro
1226 * duplicates get discarded in forming encapsulation unit */
1229 else if( p_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
1231 /* silently discard corruption sentinels,
1232 * synchronizer will then discard affected data units.
1233 * do not produce an EOS data unit as this is very
1234 * disruptive to the stream (and may make a larger error). */
1235 block_Release( p_block
);
1239 block_BytestreamPush( &p_sys
->bytestream
, p_block
);
1242 /* form as many encapsulation units as possible, give up
1243 * when the syncronizer runs out of input data */
1244 while( ( p_block
= dirac_DoSync( p_dec
) ) )
1246 p_block
= dirac_BuildEncapsulationUnit( p_dec
, p_block
);
1249 /* add to tail of output queue (ie, not reordered) */
1250 block_ChainLastAppend( &p_sys
->pp_outqueue_last
, p_block
);
1251 /* insert encapsulation unit into timestamp generator
1252 * which then calculates some timestamps if required */
1253 i_flushing
= dirac_TimeGenPush( p_dec
, p_block
);
1258 block_t
*p_output
= NULL
;
1259 block_t
**pp_output
= &p_output
;
1261 /* extract all the dated packets from the head of the ouput queue */
1262 /* explicitly nondated packets repeat the previous timestamps to
1263 * stop vlc discarding them */
1264 while( (p_block
= p_sys
->p_outqueue
) )
1266 if( p_block
->i_flags
& DIRAC_DISCARD
)
1268 p_sys
->p_outqueue
= p_block
->p_next
;
1269 p_block
->p_next
= NULL
;
1270 block_Release( p_block
);
1274 if( i_flushing
|| p_block
->i_flags
& DIRAC_NON_DATED
)
1276 p_block
->i_dts
= p_sys
->i_dts_last_out
;
1277 p_block
->i_pts
= p_sys
->i_pts_last_out
;
1279 else if( p_block
->i_pts
<= VLC_TS_INVALID
) break;
1280 else if( p_block
->i_dts
<= VLC_TS_INVALID
) break;
1282 p_sys
->i_dts_last_out
= p_block
->i_dts
;
1283 p_sys
->i_pts_last_out
= p_block
->i_pts
;
1285 p_sys
->p_outqueue
= p_block
->p_next
;
1286 p_block
->p_next
= NULL
;
1287 /* clear any flags we set */
1288 p_block
->i_flags
&= ~BLOCK_FLAG_PRIVATE_MASK
;
1289 block_ChainLastAppend( &pp_output
, p_block
);
1291 mtime_t i_delay
= p_block
->i_pts
- p_block
->i_dts
;
1293 msg_Err( p_dec
, "pts - dts is negative(%"PRId64
"): incorrect RoB size", i_delay
);
1298 p_sys
->i_eu_dts
= p_sys
->i_eu_pts
= VLC_TS_INVALID
;
1300 /* reset timegen state (except synchronizer) */
1301 p_sys
->b_seen_seq_hdr
= false;
1302 if( i_flushing
< 2 )
1304 /* this state isn't safe to loose if there was
1305 * an unsignalled discontinuity */
1306 p_sys
->b_pts
= p_sys
->b_dts
= false;
1308 p_sys
->b_tg_last_picnum
= false;
1309 dirac_ReorderInit( &p_sys
->reorder_buf
);
1311 assert( p_sys
->p_outqueue
== NULL
);
1312 p_sys
->p_out_dts
= NULL
;
1315 /* perform sanity check:
1316 * if there were a block at the front of outqueue that never
1317 * satisfied the extraction criteria, but all blocks after did,
1318 * the output queue would grow bounded by the stream length.
1319 * If there are 10 data units in the output queue, assume this
1320 * has happened and purge all blocks that fail extraction criteria */
1322 block_ChainProperties( p_sys
->p_outqueue
, &i_count
, NULL
, NULL
);
1325 p_block
= p_sys
->p_outqueue
;
1328 block_t
*p_block_next
= p_block
->p_next
;
1329 if( p_block
->i_pts
> VLC_TS_INVALID
&& p_block
->i_dts
> VLC_TS_INVALID
)
1331 block_Release( p_block
);
1332 p_sys
->p_outqueue
= p_block
= p_block_next
;
1336 if( !p_sys
->p_outqueue
)
1338 p_sys
->pp_outqueue_last
= &p_sys
->p_outqueue
;
1343 /*****************************************************************************
1344 * Open: probe the packetizer and return score
1345 *****************************************************************************/
1346 static int Open( vlc_object_t
*p_this
)
1348 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1349 decoder_sys_t
*p_sys
;
1351 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_DIRAC
)
1352 return VLC_EGENERIC
;
1354 p_dec
->pf_packetize
= Packetize
;
1356 /* Create the output format */
1357 es_format_Copy( &p_dec
->fmt_out
, &p_dec
->fmt_in
);
1358 p_dec
->p_sys
= p_sys
= calloc( 1, sizeof( decoder_sys_t
) );
1363 p_sys
->i_eu_pts
= p_sys
->i_eu_dts
= VLC_TS_INVALID
;
1364 p_sys
->i_sync_pts
= p_sys
->i_sync_dts
= VLC_TS_INVALID
;
1365 p_sys
->i_dts_last_out
= p_sys
->i_pts_last_out
= VLC_TS_INVALID
;
1367 p_sys
->i_state
= NOT_SYNCED
;
1368 p_sys
->bytestream
= block_BytestreamInit();
1370 p_sys
->pp_outqueue_last
= &p_sys
->p_outqueue
;
1371 p_sys
->pp_eu_last
= &p_sys
->p_eu
;
1373 date_Init( &p_sys
->dts
, 1, 1 );
1374 dirac_ReorderInit( &p_sys
->reorder_buf
);
1376 if( p_dec
->fmt_in
.i_extra
> 0 )
1378 /* handle hacky systems like ogg that dump some headers
1379 * in p_extra. and packetizers that expect it to be filled
1380 * in before real startup */
1381 block_t
*p_init
= block_New( p_dec
, p_dec
->fmt_in
.i_extra
);
1384 /* memory might be avaliable soon. it isn't the end of
1385 * the world that fmt_in.i_extra isn't handled */
1388 memcpy( p_init
->p_buffer
, p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
);
1389 /* in theory p_extra should contain just a seqhdr&EOS. if just a
1390 * seqhdr, ensure it is extracted by appending an EOS with
1391 * prev_offset = seqhdr length, ie i_extra. If all were actually
1392 * ok, this won't do anything bad */
1393 if( ( p_init
->p_next
= dirac_EmitEOS( p_dec
, p_dec
->fmt_in
.i_extra
) ) )
1395 /* to ensure that one of these two EOS dataunits gets extracted,
1396 * send a second one */
1397 p_init
->p_next
->p_next
= dirac_EmitEOS( p_dec
, 13 );
1401 while( ( p_block
= Packetize( p_dec
, &p_init
) ) )
1402 block_Release( p_block
);
1408 /*****************************************************************************
1410 *****************************************************************************/
1411 static void Close( vlc_object_t
*p_this
)
1413 decoder_t
*p_dec
= (decoder_t
*)p_this
;
1414 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
1416 block_BytestreamRelease( &p_sys
->bytestream
);
1417 if( p_sys
->p_outqueue
)
1418 block_ChainRelease( p_sys
->p_outqueue
);
1420 block_ChainRelease( p_sys
->p_eu
);