Update translations from 2.2.x branch
[vlc.git] / modules / packetizer / dirac.c
blobfc4a0ded8e6b9676c572072220820a18be9805fb
1 /*****************************************************************************
2 * dirac.c
3 *****************************************************************************
4 * Copyright (C) 2008 VLC authors and VideoLAN
5 * $Id$
7 * Authors: David Flynn <davidf@rd.bbc.co.uk>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * 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
40 * known good values.
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 output, these
55 * blocks get dated with the last used timestamp (or are merged with
56 * another encapsulation unit).
59 /*****************************************************************************
60 * Preamble
61 *****************************************************************************/
63 #ifdef HAVE_CONFIG_H
64 # include "config.h"
65 #endif
67 #include <assert.h>
68 #include <vlc_common.h>
69 #include <vlc_plugin.h>
70 #include <vlc_codec.h>
71 #include <vlc_block.h>
73 #include <vlc_bits.h>
74 #include <vlc_block_helper.h>
76 #define SANITIZE_PREV_PARSE_OFFSET 1
78 /*****************************************************************************
79 * Module descriptor
80 *****************************************************************************/
81 static int Open ( vlc_object_t * );
82 static void Close( vlc_object_t * );
84 vlc_module_begin()
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 )
90 vlc_module_end()
92 /*****************************************************************************
93 * Local prototypes
94 *****************************************************************************/
95 struct decoder_sys_t
97 /* sync state */
98 block_bytestream_t bytestream;
99 int i_state;
100 size_t i_offset;
101 uint32_t u_last_npo;
102 /* recovered timestamp from bytesteram for use
103 * by synchroniser: should only get reset by the
104 * synchronizer upon a discontinuity sentinel */
105 mtime_t i_sync_pts;
106 mtime_t i_sync_dts;
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 */
112 mtime_t i_eu_pts;
113 mtime_t i_eu_dts;
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 */
129 block_t *p_outqueue;
130 block_t **pp_outqueue_last;
132 uint32_t u_tg_last_picnum; /*< most recent picturenumber output from RoB */
133 bool b_tg_last_picnum; /*< u_tg_last_picnum valid */
135 struct dirac_reorder_buffer {
136 int u_size_max;
137 int u_size;
138 struct dirac_reorder_entry {
139 struct dirac_reorder_entry *p_next;
140 block_t *p_eu;
141 uint32_t u_picnum;
142 } p_entries[32], *p_head, *p_empty;
143 } reorder_buf; /*< reorder buffer, used by timegenerator */
145 /* packetizer state */
146 mtime_t i_pts_last_out; /*< last output [from packetizer] pts */
147 mtime_t i_dts_last_out; /*< last output [from packetizer] dts */
149 struct seq_hdr_t {
150 uint32_t u_width;
151 uint32_t u_height;
152 uint32_t u_fps_num;
153 uint32_t u_fps_den;
154 enum picture_coding_mode_t {
155 DIRAC_FRAME_CODING=0,
156 DIRAC_FIELD_CODING=1,
157 } u_picture_coding_mode;
158 } seq_hdr; /*< sequence header */
159 bool b_seen_seq_hdr; /* sequence header valid */
160 bool b_seen_eos; /* last data unit to be handled was an EOS */
163 typedef struct {
164 uint32_t u_next_offset;
165 uint32_t u_prev_offset;
166 int i_parse_code;
167 } parse_info_t;
169 typedef struct {
170 /*> next_parse_offset of the final data unit in associated block_t */
171 uint32_t u_last_next_offset;
172 /*> picture number is invalid if block has flags DIRAC_NON_DATED */
173 uint32_t u_picture_number;
174 } dirac_block_encap_t;
176 enum {
177 NOT_SYNCED=0,
178 TRY_SYNC,
179 SYNCED,
180 SYNCED_INCOMPLETEDU,
183 enum {
184 DIRAC_NON_DATED = (1 << BLOCK_FLAG_PRIVATE_SHIFT),
185 DIRAC_DISCARD = (2 << BLOCK_FLAG_PRIVATE_SHIFT),
188 enum {
189 DIRAC_DU_IN_EU,
190 DIRAC_DU_ENDS_EU,
193 /***
194 * Block encapsulation functions.
195 * Things are greately simplified by associating some metadata
196 * with a block as it passes through the packetizer (saves having
197 * to determine it again)
199 * unfortunately p_block doesn't have a p_priv, so some fakage
200 * needs to happen:
201 * - Create a dummy block that has some extra storage, set up
202 * members to be identical to the actual block
203 * - Store private data there and pointer to orig block
204 * - modify block pointer to point to fake block
206 * NB, the add/new functions must not be used to blocks
207 * that are referenced in lists, etc., [in this code, this is ok]
208 * NB, don't call add on the same block multiple times (will leak)
210 * davidf has a patch that reverts this to use a p_priv in block_t.
212 typedef struct {
213 block_t fake;
214 block_t *p_orig;
215 dirac_block_encap_t *p_dbe;
216 } fake_block_t;
218 static dirac_block_encap_t *dirac_RemoveBlockEncap( block_t *p_block )
220 fake_block_t *p_fake = (fake_block_t *)p_block;
221 dirac_block_encap_t *p_dbe = p_fake->p_dbe;
223 p_fake->p_dbe = NULL;
224 return p_dbe;
227 static void dirac_ReleaseBlockAndEncap( block_t *p_block )
229 fake_block_t *p_fake = (fake_block_t *)p_block;
231 free( dirac_RemoveBlockEncap( p_block ) );
232 block_Release( p_fake->p_orig );
233 free( p_fake );
236 static void dirac_AddBlockEncap( block_t **pp_block, dirac_block_encap_t *p_dbe )
238 /* must not fail, fixby: adding a p_priv to block_t */
239 fake_block_t *p_fake = xcalloc( 1, sizeof( *p_fake ) );
240 block_t *in = *pp_block, *out = &p_fake->fake;
242 block_Init( out, in->p_buffer, in->i_buffer );
243 out->i_flags = in->i_flags;
244 out->i_nb_samples = in->i_nb_samples;
245 out->i_pts = in->i_pts;
246 out->i_dts = in->i_dts;
247 out->i_length = in->i_length;
248 out->pf_release = dirac_ReleaseBlockAndEncap;
249 p_fake->p_orig = in;
250 p_fake->p_dbe = p_dbe;
252 *pp_block = out;
255 static dirac_block_encap_t *dirac_NewBlockEncap( block_t **pp_block )
257 dirac_block_encap_t *p_dbe = calloc( 1, sizeof( *p_dbe ) );
258 if( p_dbe ) dirac_AddBlockEncap( pp_block, p_dbe );
259 return p_dbe;
262 static dirac_block_encap_t *dirac_GetBlockEncap( block_t *p_block )
264 return ((fake_block_t *)p_block)->p_dbe;
267 /***
268 * General utility funcions
272 * given a chain of block_t, allocate and return an array containing
273 * pointers to all the blocks. (Acts as a replacement for the old p_prev
274 * member of block_t) */
275 static int block_ChainToArray( block_t *p_block, block_t ***ppp_array)
277 if( !ppp_array )
278 return 0;
280 int i_num_blocks;
281 block_ChainProperties( p_block, &i_num_blocks, NULL, NULL );
283 *ppp_array = calloc( i_num_blocks, sizeof( block_t* ) );
284 if( !*ppp_array ) return 0;
286 for( int i = 0; i < i_num_blocks; i++ )
288 (*ppp_array)[i] = p_block;
289 p_block = p_block->p_next;
292 return i_num_blocks;
296 * Destructively find and recover the earliest timestamp from start of
297 * bytestream, up to i_length.
299 static void dirac_RecoverTimestamps ( decoder_t *p_dec, size_t i_length )
301 decoder_sys_t *p_sys = p_dec->p_sys;
302 block_t *p_block = p_sys->bytestream.p_block;
304 /* Find the block with first non-flushed data */
305 size_t i_offset = p_sys->bytestream.i_block_offset;
306 for(; p_block != NULL; p_block = p_block->p_next )
308 if( i_offset < p_block->i_buffer )
309 break;
310 i_offset -= p_block->i_buffer;
313 i_offset += i_length;
314 for(; p_block != NULL; p_block = p_block->p_next )
316 if( p_sys->i_sync_pts <= VLC_TS_INVALID && p_sys->i_sync_dts <= VLC_TS_INVALID )
318 /* oldest timestamp wins */
319 p_sys->i_sync_pts = p_block->i_pts;
320 p_sys->i_sync_dts = p_block->i_dts;
322 /* clear timestamps -- more than one data unit can come from a block */
323 p_block->i_flags = 0;
324 p_block->i_pts = p_block->i_dts = VLC_TS_INVALID;
325 if( i_offset < p_block->i_buffer )
326 break;
327 i_offset -= p_block->i_buffer;
331 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
332 static void dirac_BackdateDTS( block_t *p_block, block_t *p_last, date_t *p_dts )
334 /* Transverse p_last backwards. (no p_prev anymore) */
335 block_t **pp_array = NULL;
336 int n = block_ChainToArray( p_block, &pp_array );
337 while( n ) if( pp_array[--n] == p_last ) break;
338 /* want to start at p_last->p_prev */
339 while( n-- )
341 if( pp_array[n]->i_flags & DIRAC_NON_DATED )
342 continue;
343 if( pp_array[n]->i_dts <= VLC_TS_INVALID )
344 pp_array[n]->i_dts = date_Decrement( p_dts, 1 );
346 free( pp_array );
349 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
350 static void dirac_BackdatePTS( block_t *p_block, block_t *p_last, date_t *p_pts, uint32_t u_pts_picnum )
352 /* Transverse p_last backwards. (no p_prev anymore) */
353 block_t **pp_array = NULL;
354 int n = block_ChainToArray( p_block, &pp_array );
355 while( n ) if( pp_array[--n] == p_last ) break;
356 /* want to start at p_last->p_prev */
357 while( n-- )
359 if( pp_array[n]->i_flags & DIRAC_NON_DATED )
360 continue;
361 if( pp_array[n]->i_dts > VLC_TS_INVALID )
362 continue;
363 dirac_block_encap_t *dbe = dirac_GetBlockEncap( pp_array[n] );
364 int32_t u_pic_num = dbe ? dbe->u_picture_number : 0;
365 int32_t i_dist = u_pic_num - u_pts_picnum;
366 date_t pts = *p_pts;
367 if( i_dist >= 0 )
368 pp_array[n]->i_pts = date_Increment( &pts, i_dist );
369 else
370 pp_array[n]->i_pts = date_Decrement( &pts, -i_dist );
372 free( pp_array );
375 /***
376 * Dirac spec defined relations
379 static bool dirac_isEOS( uint8_t u_parse_code ) { return 0x10 == u_parse_code; }
380 static bool dirac_isSeqHdr( uint8_t u_parse_code ) { return 0 == u_parse_code; }
381 static bool dirac_isPicture( uint8_t u_parse_code ) { return 0x08 & u_parse_code; }
382 static int dirac_numRefs( uint8_t u_parse_code ) { return 0x3 & u_parse_code; }
384 static inline bool dirac_PictureNbeforeM( uint32_t u_n, uint32_t u_m )
386 /* specified as: u_n occurs before u_m if:
387 * (u_m - u_n) mod (1<<32) < D */
388 return (uint32_t)(u_m - u_n) < (1u<<31);
391 /***
392 * Reorder buffer model
395 static void dirac_ReorderInit( struct dirac_reorder_buffer *p_rb )
397 memset( p_rb, 0, sizeof(*p_rb) );
398 p_rb->u_size_max = 2;
399 p_rb->p_empty = p_rb->p_entries;
400 p_rb->p_entries[31].p_next = NULL;
402 for( int i = 0; i < 31; i++ )
403 p_rb->p_entries[i].p_next = &p_rb->p_entries[i+1];
406 /* simulate the dirac picture reorder buffer */
407 static block_t *dirac_Reorder( decoder_t *p_dec, block_t *p_block_in, uint32_t u_picnum )
409 decoder_sys_t *p_sys = p_dec->p_sys;
411 if( !p_sys->reorder_buf.u_size_max )
412 /* reorder buffer disabled */
413 return p_block_in;
415 /* Modeling the reorder buffer:
416 * 1. If the reorder buffer is not full, insert picture for reordering.
417 * No picture is output by the system this picture period
418 * 2. If the reorder buffer is full:
419 * a. The picture decoded this period (u_picnum) bypasses the reorder
420 * buffer if it has a lower picture number than any entry in the
421 * reorder buffer. This picture is output by the system.
422 * b. Otherwise, the lowest picture number in the reorder buffer is
423 * removed from the buffer and output by the system. The current
424 * decoded picture (u_picnum) is inserted into the reorder buffer
427 block_t *p_block = NULL;
428 /* Determine if the picture needs to be inserted */
429 if( p_sys->reorder_buf.u_size == p_sys->reorder_buf.u_size_max )
431 /* (2) reorder buffer is full */
432 if( !p_sys->reorder_buf.u_size_max ||
433 dirac_PictureNbeforeM( u_picnum, p_sys->reorder_buf.p_head->u_picnum ) )
435 /* (2a) current picture is first in order */
436 return p_block_in;
439 /* (2b) extract the youngest picture in the buffer */
440 p_block = p_sys->reorder_buf.p_head->p_eu;
442 struct dirac_reorder_entry *p_tmp = p_sys->reorder_buf.p_head;
443 p_sys->reorder_buf.p_head = p_tmp->p_next;
444 p_tmp->p_next = p_sys->reorder_buf.p_empty;
445 p_sys->reorder_buf.p_empty = p_tmp;
447 p_sys->reorder_buf.u_size--;
450 /* (1) and (2b) both require u_picnum to be inserted */
451 struct dirac_reorder_entry *p_current = p_sys->reorder_buf.p_empty;
452 p_sys->reorder_buf.p_empty = p_current->p_next;
453 p_sys->reorder_buf.u_size++;
455 /* insertion sort to keep p_head always sorted, earliest first */
456 struct dirac_reorder_entry **pp_at = &p_sys->reorder_buf.p_head;
457 for( ; *pp_at; pp_at = &(*pp_at)->p_next )
458 if( dirac_PictureNbeforeM( u_picnum, (*pp_at)->u_picnum ) )
459 break;
461 p_current->u_picnum = u_picnum;
462 p_current->p_eu = p_block_in;
463 p_current->p_next = *pp_at;
464 *pp_at = p_current;
466 return p_block;
469 /***
470 * bytestream parsing and unmarshalling functions
473 static bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs,
474 size_t u_offset )
476 uint8_t p_d[13];
477 if( VLC_SUCCESS != block_PeekOffsetBytes( p_bs, u_offset, p_d, 13 ) )
478 return false;
480 if( p_d[0] != 'B' || p_d[1] != 'B' || p_d[2] != 'C' || p_d[3] != 'D' )
481 return false;
483 p_pi->i_parse_code = p_d[4];
484 p_pi->u_next_offset = GetDWBE( &p_d[5] );
485 p_pi->u_prev_offset = GetDWBE( &p_d[9] );
486 return true;
489 static uint32_t dirac_uint( bs_t *p_bs )
491 uint32_t u_count = 0, u_value = 0;
492 while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
494 u_count++;
495 u_value <<= 1;
496 u_value |= bs_read( p_bs, 1 );
498 return (1 << u_count) - 1 + u_value;
501 static int dirac_bool( bs_t *p_bs )
503 return bs_read( p_bs, 1 );
506 /* read in useful bits from sequence header */
507 static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
509 bs_t bs;
510 bs_init( &bs, p_block->p_buffer, p_block->i_buffer );
511 bs_skip( &bs, 13*8 ); /* parse_info_header */
512 dirac_uint( &bs ); /* major_version */
513 dirac_uint( &bs ); /* minor_version */
514 dirac_uint( &bs ); /* profile */
515 dirac_uint( &bs ); /* level */
517 uint32_t u_video_format = dirac_uint( &bs ); /* index */
518 if( u_video_format > 20 )
520 /* don't know how to parse this header */
521 return false;
524 static const struct {
525 uint32_t u_w, u_h;
526 } dirac_size_tbl[] = {
527 {640,480}, {176,120}, {176,144}, {352,240}, {352,288}, {704,480},
528 {704,576}, {720,480}, {720,576}, {1280,720}, {1280,720}, {1920,1080},
529 {1920,1080}, {1920,1080}, {1920,1080}, {2048,1080}, {4096,2160},
530 {3840,2160}, {3840,2160}, {7680,4320}, {7680,4320},
533 p_sh->u_width = dirac_size_tbl[u_video_format].u_w;
534 p_sh->u_height = dirac_size_tbl[u_video_format].u_h;
535 if( dirac_bool( &bs ) )
537 p_sh->u_width = dirac_uint( &bs ); /* frame_width */
538 p_sh->u_height = dirac_uint( &bs ); /* frame_height */
541 if( dirac_bool( &bs ) )
543 dirac_uint( &bs ); /* chroma_format */
546 if( dirac_bool( &bs ) )
548 dirac_uint( &bs ); /* scan_format */
551 static const struct {
552 uint32_t u_n /* numerator */, u_d /* denominator */;
553 } dirac_frate_tbl[] = { /* table 10.3 */
554 {1, 1}, /* this value is not used */
555 {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
556 {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
559 const unsigned dirac_frate_tbl_size =
560 sizeof( dirac_frate_tbl ) / sizeof( *dirac_frate_tbl );
562 static const uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
563 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
566 p_sh->u_fps_num = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_n;
567 p_sh->u_fps_den = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_d;
568 if( dirac_bool( &bs ) )
570 uint32_t frame_rate_index = dirac_uint( &bs );
571 if( frame_rate_index >= dirac_frate_tbl_size )
573 /* invalid header */
574 return false;
576 p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n;
577 p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d;
578 if( frame_rate_index == 0 )
580 p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */
581 p_sh->u_fps_den = dirac_uint( &bs ); /* frame_rate_denominator */
585 /* must have a valid framerate */
586 if( !p_sh->u_fps_num || !p_sh->u_fps_den )
587 return false;
589 if( dirac_bool( &bs ) )
591 uint32_t par_index = dirac_uint( &bs );
592 if( !par_index )
594 dirac_uint( &bs ); /* par_num */
595 dirac_uint( &bs ); /* par_den */
599 if( dirac_bool( &bs ) )
601 dirac_uint( &bs ); /* clean_width */
602 dirac_uint( &bs ); /* clean_height */
603 dirac_uint( &bs ); /* clean_left_offset */
604 dirac_uint( &bs ); /* clean_top_offset */
607 if( dirac_bool( &bs ) )
609 uint32_t signal_range_index = dirac_uint( &bs );
610 if( !signal_range_index )
612 dirac_uint( &bs ); /* luma_offset */
613 dirac_uint( &bs ); /* luma_excursion */
614 dirac_uint( &bs ); /* chroma_offset */
615 dirac_uint( &bs ); /* chroma_excursion */
619 if( dirac_bool( &bs ) )
621 uint32_t colour_spec_index = dirac_uint( &bs );
622 if( !colour_spec_index )
624 if( dirac_bool( &bs ) )
626 dirac_uint( &bs ); /* colour_primaries_index */
628 if( dirac_bool( &bs ) )
630 dirac_uint( &bs ); /* colour_matrix_index */
632 if( dirac_bool( &bs ) )
634 dirac_uint( &bs ); /* transfer_function_index */
639 p_sh->u_picture_coding_mode = dirac_uint( &bs );
641 return true;
644 /***
645 * Data Unit marshalling functions
648 static block_t *dirac_EmitEOS( decoder_t *p_dec, uint32_t i_prev_parse_offset )
650 const uint8_t p_eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
651 block_t *p_block = block_Alloc( 13 );
652 if( !p_block )
653 return NULL;
654 memcpy( p_block->p_buffer, p_eos, 13 );
656 SetDWBE( p_block->p_buffer + 9, i_prev_parse_offset );
658 p_block->i_flags = DIRAC_NON_DATED;
660 (void) p_dec;
661 return p_block;
664 /***
665 * Bytestream synchronizer
666 * maps [Bytes] -> DataUnit
668 static block_t *dirac_DoSync( decoder_t *p_dec )
670 decoder_sys_t *p_sys = p_dec->p_sys;
671 parse_info_t pu;
673 static const uint8_t p_parsecode[4] = {'B','B','C','D'};
674 do {
675 switch( p_sys->i_state )
677 case NOT_SYNCED:
679 if( VLC_SUCCESS !=
680 block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset,
681 p_parsecode, 4, NULL, NULL ) )
683 /* p_sys->i_offset will have been set to:
684 * end of bytestream - amount of prefix found
685 * can resume search from this point when more data arrives */
686 return NULL;
688 /* candidate parse_code_prefix has been found at p_sys->i_offset */
689 if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_offset + 12, NULL, 0 ) )
691 /* insufficient data has been accumulated to fully extract
692 * a parse_info header. exit for now in the hope of more
693 * data later to retry at exactly the same point */
694 return NULL;
696 p_sys->i_state = TRY_SYNC;
697 break; /* candidate found, try to sync */
699 case SYNCED: /* -> TRY_SYNC | NOT_SYNCED */
700 /* sanity: can only reach this after having extracted a DU,
701 * which causes data to be consumed and local i_offset to be reset */
702 assert( p_sys->i_offset == 0 );
703 if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, 12, NULL, 0 ) )
705 /* insufficient data has been accumulated to fully extract
706 * a parse_info header, retry later */
707 return NULL;
709 if( !dirac_UnpackParseInfo( &pu, &p_sys->bytestream, 0 )
710 || !pu.u_next_offset || (p_sys->u_last_npo != pu.u_prev_offset) )
712 /* !a: not a valid parse info.
713 * !pu.u_next_offset: don't know the length of the data unit
714 * search for the next one that points back
715 * to this one to determine length.
716 * (p_sys->u_last_npo != pu.u_prev_offset): some desync
718 p_sys->i_state = NOT_SYNCED;
719 break;
721 if( pu.u_next_offset > 1024*1024 )
723 /* sanity check for erronious hugs next_parse_offsets
724 * (eg, 2^32-1) that would cause a very long wait
725 * and large space consumption: fall back to try sync */
726 p_sys->i_state = TRY_SYNC;
727 break;
729 /* check that the start of the next data unit is avaliable */
730 if( VLC_SUCCESS !=
731 block_PeekOffsetBytes( &p_sys->bytestream, pu.u_next_offset + 12, NULL, 0 ) )
733 return NULL; /* retry later */
735 /* attempt to synchronise backwards from pu.u_next_offset */
736 p_sys->i_offset = pu.u_next_offset;
737 /* fall through */
738 case TRY_SYNC: /* -> SYNCED | NOT_SYNCED */
740 if( !p_sys->i_offset )
741 goto sync_fail; /* if a is at start of bytestream, b can't be in buffer */
743 parse_info_t pu_a;
744 bool a = dirac_UnpackParseInfo( &pu_a, &p_sys->bytestream, p_sys->i_offset );
745 if( !a || (pu_a.u_prev_offset > p_sys->i_offset) )
746 goto sync_fail; /* b lies beyond start of bytestream: can't sync */
748 if( !pu_a.u_prev_offset )
750 if( p_sys->i_state == TRY_SYNC )
752 goto sync_fail; /* can't find different pu_b from pu_a */
754 /* state == SYNCED: already know where pu_b is.
755 * pu_a has probably been inserted by something that doesn't
756 * know what the last next_parse_offset was */
757 pu_a.u_prev_offset = pu.u_next_offset;
760 parse_info_t *pu_b = &pu;
761 bool b = dirac_UnpackParseInfo( pu_b, &p_sys->bytestream, p_sys->i_offset - pu_a.u_prev_offset );
762 if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) )
764 /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
765 * just rely on finding a valid pu_b from pu_a. */
766 goto sync_fail;
768 p_sys->u_last_npo = pu_b->u_next_offset;
769 if( !pu_b->u_next_offset ) pu_b->u_next_offset = pu_a.u_prev_offset;
770 /* offset was pointing at pu_a, rewind to point at pu_b */
771 p_sys->i_offset -= pu_a.u_prev_offset;
772 p_sys->i_state = SYNCED;
773 break;
775 sync_fail:
776 if( p_sys->i_state == SYNCED ) p_sys->i_offset = 0;
777 p_sys->i_offset++;
778 p_sys->i_state = NOT_SYNCED;
779 break; /* find somewhere else to try again */
780 default:;
782 } while( SYNCED != p_sys->i_state );
785 * synced, attempt to extract a data unit
788 /* recover any timestamps from the data that is about to be flushed */
789 dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
791 /* flush everything up to the start of the DU */
792 block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
793 block_BytestreamFlush( &p_sys->bytestream );
794 p_sys->i_offset = 0;
796 /* setup the data unit buffer */
797 block_t *p_block = block_Alloc( pu.u_next_offset );
798 if( !p_block )
799 return NULL;
801 p_block->i_pts = p_sys->i_sync_pts;
802 p_block->i_dts = p_sys->i_sync_dts;
803 p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
805 /* recover any new timestamps from the data that is about to be consumed */
806 dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
808 block_GetBytes( &p_sys->bytestream, p_block->p_buffer, p_block->i_buffer );
810 /* save parse offset in private area for later use */
811 dirac_block_encap_t *p_dbe = dirac_NewBlockEncap( &p_block );
812 if( p_dbe ) p_dbe->u_last_next_offset = pu.u_next_offset;
814 return p_block;
817 /***
818 * Packet (Data Unit) inspection, learns parameters from sequence
819 * headers, sets up flags, drops unwanted data units, sets
820 * encapsulation unit termination policy
822 static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu )
824 decoder_sys_t *p_sys = p_dec->p_sys;
825 block_t *p_block = *pp_block;
826 uint8_t u_parse_code = p_block->p_buffer[4];
828 if( dirac_isEOS( u_parse_code ) )
830 if( p_sys->b_seen_eos )
832 /* remove duplicate EOS packets */
833 block_Release( p_block );
834 *pp_block = NULL;
835 return DIRAC_DU_IN_EU;
837 /* p_block is an EOS packet */
838 p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
839 /* for the moment, let this end an encapsulation unit */
840 /* seeing an eos packet requires a flush of the packetizer
841 * this is detected by the caller of this function */
842 p_sys->b_seen_seq_hdr = false;
843 p_sys->b_seen_eos = true;
844 return DIRAC_DU_ENDS_EU;
845 #if 0
846 /* let anything down streem know too */
848 Actually, this is a bad idea:
849 - It sets the discontinuity for every dirac EOS packet
850 which doesnt imply a time discontinuity.
851 - When the synchronizer detects a real discontinuity, it
852 should copy the flags through.
853 p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
855 #endif
857 p_sys->b_seen_eos = false;
859 if( dirac_isPicture( u_parse_code ) )
861 /* timestamps apply to pictures only */
862 p_eu->i_dts = p_sys->i_eu_dts;
863 p_eu->i_pts = p_sys->i_eu_pts;
864 p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
866 if( !p_sys->b_seen_seq_hdr )
868 /* can't timestamp in this case, discard later
869 * so that the timestamps aren't lost */
870 p_eu->i_flags |= DIRAC_DISCARD;
872 /* p_block is a picture -- it ends the 'encapsulation unit' */
873 if( dirac_numRefs( u_parse_code ) )
875 /* if this picture is not an I frame, ensure that the
876 * random access point flags are not set */
877 p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
879 dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
880 if( p_dbe && p_block->i_buffer > 13+4 )
882 /* record the picture number to save the time gen functions
883 * from having to inspect the data for it */
884 p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
886 return DIRAC_DU_ENDS_EU;
889 if( dirac_isSeqHdr( u_parse_code ) )
891 if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) )
893 /* couldn't parse the sequence header, just ignore it */
894 return DIRAC_DU_IN_EU;
896 p_sys->b_seen_seq_hdr = true;
898 /* a sequence header followed by an I frame is a random
899 * access point; assume that this is the case */
900 p_eu->i_flags |= BLOCK_FLAG_TYPE_I;
902 es_format_t *p_es = &p_dec->fmt_out;
904 p_es->video.i_width = p_sys->seq_hdr.u_width;
905 p_es->video.i_height = p_sys->seq_hdr.u_height;
907 vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
908 , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );
910 /* when field coding, dts needs to be incremented in terms of field periods */
911 unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
912 if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING )
914 u_pics_per_sec *= 2;
916 if( u_pics_per_sec && p_sys->seq_hdr.u_fps_den )
917 date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den );
919 /* TODO: set p_sys->reorder_buf.u_size_max */
920 p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max
921 * 1000000
922 * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1;
924 /* stash a copy of the seqhdr
925 * - required for ogg muxing
926 * - useful for error checking
927 * - it isn't allowed to change until an eos */
928 free( p_es->p_extra );
929 p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
930 if( !p_es->p_extra )
932 p_es->i_extra = 0;
933 return DIRAC_DU_IN_EU;
935 p_es->i_extra = p_block->i_buffer;
936 memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer );
937 /* append EOS as per Ogg guidelines */
938 p_block = dirac_EmitEOS( p_dec, p_block->i_buffer );
939 if( p_block )
941 memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 );
942 p_es->i_extra += 13;
945 return DIRAC_DU_IN_EU;
948 /* doesn't end an encapsulation unit */
949 return DIRAC_DU_IN_EU;
952 /***
953 * Encapsulation (packetization) suitable for all muxing standards
954 * maps [DataUnit] -> EncapsulationUnit
956 static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block )
958 decoder_sys_t *p_sys = p_dec->p_sys;
960 assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer ));
962 if( p_sys->i_eu_pts <= VLC_TS_INVALID && p_sys->i_eu_dts <= VLC_TS_INVALID )
964 /* earliest block with pts/dts gets to set the pts/dts for the dated
965 * encapsulation unit as a whole */
966 /* NB, the 'earliest block' criteria is aribtary */
967 if( p_block->i_pts > VLC_TS_INVALID || p_block->i_dts > VLC_TS_INVALID )
969 p_sys->i_eu_pts = p_block->i_pts;
970 p_sys->i_eu_dts = p_block->i_dts;
974 /* inpectdataunit also updates flags for the EU.
975 * - if this is the first block in the EU, then it hasn't been added
976 * to the chain yet (so, p_block will become the front of the chain
977 * - otherwise, use the flags of the chain (first block) */
978 block_t *p_eu = p_sys->p_eu ? p_sys->p_eu : p_block;
979 int i_block = dirac_InspectDataUnit( p_dec, &p_block, p_eu);
981 if( !p_block )
983 /* block has been discarded during inspection */
984 /* becareful, don't discard anything that is dated,
985 * as this needs to go into the timegen loop. set
986 * the DIRAC_DISCARD block flag, and it'll be dropped
987 * at output time */
988 return NULL;
991 block_ChainLastAppend( &p_sys->pp_eu_last, p_block );
993 dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
994 #ifdef SANITIZE_PREV_PARSE_OFFSET
995 /* fixup prev_parse_offset to point to the last data unit
996 * to arrive */
997 if( p_dbe )
999 SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo );
1000 p_sys->u_eu_last_npo = p_dbe->u_last_next_offset;
1002 #endif
1004 if( i_block != DIRAC_DU_ENDS_EU )
1006 /* encapsulation unit not ended */
1007 return NULL;
1010 /* gather up encapsulation unit, reassociating the final
1011 * private state with the gathered block */
1012 block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next );
1013 p_dbe = dirac_RemoveBlockEncap( p_eu_last );
1015 uint8_t u_parse_code = p_block->p_buffer[4];
1017 /* gather up the encapsulation unit */
1018 p_block = block_ChainGather( p_sys->p_eu );
1019 assert( p_block ); /* block_ChainGather doesn't define when it frees chain */
1021 p_block->i_flags |= DIRAC_NON_DATED;
1022 if( p_dbe )
1024 dirac_AddBlockEncap( &p_block, p_dbe );
1025 if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED;
1027 p_sys->p_eu = NULL;
1028 p_sys->pp_eu_last = &p_sys->p_eu;
1029 return p_block;
1033 * dirac_TimeGenPush:
1034 * @p_dec: vlc object
1035 * @p_block_in: whole encapsulation unit to generate timestamps for
1037 * Returns:
1038 * 0: everything ok
1039 * 1: EOS occurred, please flush and reset
1040 * 2: picture number discontinuity, please flush and reset
1042 static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
1044 decoder_sys_t *p_sys = p_dec->p_sys;
1045 dirac_block_encap_t *p_dbe;
1047 if( p_block_in->i_flags & BLOCK_FLAG_END_OF_SEQUENCE )
1049 /* NB, this test occurs after the timegen push, so as to
1050 * push the block into the output queue */
1051 return 1;
1054 if( p_block_in->i_flags & DIRAC_NON_DATED )
1056 /* no picture found, which means p_block_in is a non-dated EU,
1057 * do not try and put a date on it */
1058 return 0;
1061 p_dbe = dirac_GetBlockEncap( p_block_in );
1062 uint32_t u_picnum = p_dbe ? p_dbe->u_picture_number : 0;
1064 * Simple DTS regeneration:
1065 * - DTS values linearly increase in stream order.
1066 * - Every time a DTS occurs at the input, sync to it
1067 * - If this is the first DTS seen, backdate all the previous ones that are undated
1068 * - If a DTS is missing, guess that it increases by one picture period
1069 * - If never seen DTS, don't do anything
1072 * Simple PTS regeneration
1073 * - PTS values do not linearly increase in stream order.
1074 * - Every time a PTS occurs at the input, sync to it and record picture number
1075 * - If a PTS is missing, guess that it differs by the product of picture
1076 * period and difference between picture number of sync point and current picture
1077 * - If this is the first PTS seen, backdate all previous ones that are undated
1078 * - If never seen PTS, don't do anything
1081 * Stage 1, sync to input timestamps, backdate timestamps for old
1082 * EUs that are in the outqueue with missing dates
1084 if( p_block_in->i_dts > VLC_TS_INVALID )
1085 do {
1086 /* if timestamps exist, sync to them */
1087 if( p_sys->b_dts )
1088 break;
1089 /* first dts seen, backdate any packets in outqueue */
1090 p_sys->b_dts = true;
1091 date_t dts = p_sys->dts;
1092 dirac_BackdateDTS( p_sys->p_outqueue, p_block_in, &dts );
1093 } while( 0 );
1095 if( p_block_in->i_pts > VLC_TS_INVALID )
1096 do {
1097 /* if timestamps exist, sync to them */
1098 p_sys->u_pts_picnum = u_picnum;
1099 p_sys->i_pts = p_block_in->i_pts;
1100 if( p_sys->b_pts )
1101 break;
1102 /* first pts seen, backdate any packets in outqueue */
1103 p_sys->b_pts = true;
1104 date_t pts = p_sys->dts;
1105 date_Set( &pts, p_sys->i_pts );
1106 dirac_BackdatePTS( p_sys->p_outqueue, p_block_in, &pts, p_sys->u_pts_picnum );
1107 } while( 0 );
1110 * Stage 2, don't attempt to forwards interpolate timestamps for
1111 * blocks if the picture rates aren't known
1113 if( !p_sys->b_seen_seq_hdr )
1115 return 0;
1119 * Stage 3, for block_in, interpolate any missing timestamps
1121 if( p_sys->b_dts && p_block_in->i_dts <= VLC_TS_INVALID )
1123 /* dts has previously been seen, but not this time, interpolate */
1124 p_block_in->i_dts = date_Increment( &p_sys->dts, 1 );
1127 if( p_sys->b_pts && p_block_in->i_pts <= VLC_TS_INVALID )
1129 /* pts has previously been seen, but not this time, interpolate */
1130 date_t pts = p_sys->dts;
1131 date_Set( &pts, p_sys->i_pts );
1132 int32_t i_dist = u_picnum - p_sys->u_pts_picnum;
1133 if( i_dist >= 0 )
1134 p_block_in->i_pts = date_Increment( &pts, i_dist );
1135 else
1136 p_block_in->i_pts = date_Decrement( &pts, -i_dist );
1139 /* If pts and dts have been seen, there is no need to simulate operation
1140 * of the decoder reorder buffer */
1141 /* If neither have been seen, there is little point in simulating */
1142 if( p_sys->b_dts == p_sys->b_pts )
1143 return 0;
1145 /* model the reorder buffer */
1146 block_t *p_block = dirac_Reorder( p_dec, p_block_in, u_picnum );
1147 if( !p_block )
1148 return 0;
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
1152 * the future */
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.
1165 * flush 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 */
1175 return 2;
1178 p_sys->b_tg_last_picnum = true;
1179 p_sys->u_tg_last_picnum = u_picnum;
1181 return 0;
1185 static void dirac_ReorderDequeueAndReleaseBlock( decoder_t *p_dec, block_t *p_block )
1187 decoder_sys_t *p_sys = p_dec->p_sys;
1188 /* Check if that block is present in reorder queue and release it
1189 if needed */
1190 struct dirac_reorder_entry **pp_at = &p_sys->reorder_buf.p_head;
1191 for( ; *pp_at; pp_at = &(*pp_at)->p_next )
1193 /* backup address in case we remove member */
1194 struct dirac_reorder_entry *p_entry = *pp_at;
1195 if ( p_entry->p_eu == p_block )
1197 /* unlink member */
1198 *pp_at = (*pp_at)->p_next;
1200 /* Add to empty reorder entry list*/
1201 p_entry->p_next = p_sys->reorder_buf.p_empty;
1202 p_sys->reorder_buf.p_empty = p_entry;
1204 p_sys->reorder_buf.u_size--;
1205 break;
1209 block_Release( p_block );
1212 /*****************************************************************************
1213 * Flush:
1214 *****************************************************************************/
1215 static void Flush( decoder_t *p_dec )
1217 decoder_sys_t *p_sys = p_dec->p_sys;
1219 /* pre-emptively insert an EOS at a discontinuity, protects
1220 * any decoders from any sudden changes */
1221 block_t *p_block = dirac_EmitEOS( p_dec, 0 );
1222 if( p_block )
1224 p_block->p_next = dirac_EmitEOS( p_dec, 13 );
1225 /* need two EOS to ensure it gets detected by synchro
1226 * duplicates get discarded in forming encapsulation unit */
1228 block_BytestreamPush( &p_sys->bytestream, p_block );
1232 /*****************************************************************************
1233 * Packetize: form dated encapsulation units from anything
1234 *****************************************************************************/
1235 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
1237 decoder_sys_t *p_sys = p_dec->p_sys;
1238 block_t *p_block = NULL;
1239 int i_flushing = 0;
1241 if( pp_block && *pp_block )
1243 p_block = *pp_block;
1244 *pp_block = NULL;
1246 if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
1248 block_Release( p_block );
1249 p_block = NULL;
1250 Flush( p_dec );
1252 else if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
1254 /* silently discard corruption sentinels,
1255 * synchronizer will then discard affected data units.
1256 * do not produce an EOS data unit as this is very
1257 * disruptive to the stream (and may make a larger error). */
1258 block_Release( p_block );
1259 p_block = NULL;
1261 if( p_block )
1262 block_BytestreamPush( &p_sys->bytestream, p_block );
1265 /* form as many encapsulation units as possible, give up
1266 * when the synchronizer runs out of input data */
1267 while( ( p_block = dirac_DoSync( p_dec ) ) )
1269 p_block = dirac_BuildEncapsulationUnit( p_dec, p_block );
1270 if( !p_block )
1271 continue;
1272 /* add to tail of output queue (ie, not reordered) */
1273 block_ChainLastAppend( &p_sys->pp_outqueue_last, p_block );
1274 /* insert encapsulation unit into timestamp generator
1275 * which then calculates some timestamps if required */
1276 i_flushing = dirac_TimeGenPush( p_dec, p_block );
1277 if( i_flushing )
1278 break;
1281 block_t *p_output = NULL;
1282 block_t **pp_output = &p_output;
1284 /* extract all the dated packets from the head of the output queue */
1285 /* explicitly nondated packets repeat the previous timestamps to
1286 * stop vlc discarding them */
1287 while( (p_block = p_sys->p_outqueue) )
1289 if( p_block->i_flags & DIRAC_DISCARD )
1291 p_sys->p_outqueue = p_block->p_next;
1292 p_block->p_next = NULL;
1293 block_Release( p_block );
1294 continue;
1297 if( i_flushing || p_block->i_flags & DIRAC_NON_DATED )
1299 p_block->i_dts = p_sys->i_dts_last_out;
1300 p_block->i_pts = p_sys->i_pts_last_out;
1302 else if( p_block->i_pts <= VLC_TS_INVALID ) break;
1303 else if( p_block->i_dts <= VLC_TS_INVALID ) break;
1305 p_sys->i_dts_last_out = p_block->i_dts;
1306 p_sys->i_pts_last_out = p_block->i_pts;
1308 p_sys->p_outqueue = p_block->p_next;
1309 p_block->p_next = NULL;
1310 /* clear any flags we set */
1311 p_block->i_flags &= ~BLOCK_FLAG_PRIVATE_MASK;
1312 block_ChainLastAppend( &pp_output, p_block );
1314 mtime_t i_delay = p_block->i_pts - p_block->i_dts;
1315 if( i_delay < 0 )
1316 msg_Err( p_dec, "pts - dts is negative(%"PRId64"): incorrect RoB size", i_delay );
1319 if( i_flushing )
1321 p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
1323 /* reset timegen state (except synchronizer) */
1324 p_sys->b_seen_seq_hdr = false;
1325 if( i_flushing < 2 )
1327 /* this state isn't safe to loose if there was
1328 * an unsignalled discontinuity */
1329 p_sys->b_pts = p_sys->b_dts = false;
1331 p_sys->b_tg_last_picnum = false;
1332 dirac_ReorderInit( &p_sys->reorder_buf );
1334 assert( p_sys->p_outqueue == NULL );
1337 /* perform sanity check:
1338 * if there were a block at the front of outqueue that never
1339 * satisfied the extraction criteria, but all blocks after did,
1340 * the output queue would grow bounded by the stream length.
1341 * If there are 10 data units in the output queue, assume this
1342 * has happened and purge all blocks that fail extraction criteria */
1343 int i_count;
1344 block_ChainProperties( p_sys->p_outqueue, &i_count, NULL, NULL );
1345 if( i_count > 9 )
1347 p_block = p_sys->p_outqueue;
1348 while( p_block )
1350 block_t *p_block_next = p_block->p_next;
1351 if( p_block->i_pts > VLC_TS_INVALID && p_block->i_dts > VLC_TS_INVALID )
1352 break;
1353 dirac_ReorderDequeueAndReleaseBlock( p_dec, p_block );
1354 p_sys->p_outqueue = p_block = p_block_next;
1358 if( !p_sys->p_outqueue )
1360 p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1362 return p_output;
1365 /*****************************************************************************
1366 * Open: probe the packetizer and return score
1367 *****************************************************************************/
1368 static int Open( vlc_object_t *p_this )
1370 decoder_t *p_dec = (decoder_t*)p_this;
1371 decoder_sys_t *p_sys;
1373 if( p_dec->fmt_in.i_codec != VLC_CODEC_DIRAC )
1374 return VLC_EGENERIC;
1376 p_dec->pf_packetize = Packetize;
1377 p_dec->pf_flush = Flush;
1379 /* Create the output format */
1380 es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
1381 p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
1383 if( !p_sys )
1384 return VLC_ENOMEM;
1386 p_sys->i_eu_pts = p_sys->i_eu_dts = VLC_TS_INVALID;
1387 p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
1388 p_sys->i_dts_last_out = p_sys->i_pts_last_out = VLC_TS_INVALID;
1390 p_sys->i_state = NOT_SYNCED;
1391 block_BytestreamInit( &p_sys->bytestream );
1393 p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1394 p_sys->pp_eu_last = &p_sys->p_eu;
1396 date_Init( &p_sys->dts, 1, 1 );
1397 dirac_ReorderInit( &p_sys->reorder_buf );
1399 if( p_dec->fmt_in.i_extra > 0 )
1401 /* handle hacky systems like ogg that dump some headers
1402 * in p_extra. and packetizers that expect it to be filled
1403 * in before real startup */
1404 block_t *p_init = block_Alloc( p_dec->fmt_in.i_extra );
1405 if( !p_init )
1407 /* memory might be avaliable soon. it isn't the end of
1408 * the world that fmt_in.i_extra isn't handled */
1409 return VLC_SUCCESS;
1411 memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
1412 /* in theory p_extra should contain just a seqhdr&EOS. if just a
1413 * seqhdr, ensure it is extracted by appending an EOS with
1414 * prev_offset = seqhdr length, ie i_extra. If all were actually
1415 * ok, this won't do anything bad */
1416 if( ( p_init->p_next = dirac_EmitEOS( p_dec, p_dec->fmt_in.i_extra ) ) )
1418 /* to ensure that one of these two EOS dataunits gets extracted,
1419 * send a second one */
1420 p_init->p_next->p_next = dirac_EmitEOS( p_dec, 13 );
1423 block_t *p_block;
1424 while( ( p_block = Packetize( p_dec, &p_init ) ) )
1425 block_Release( p_block );
1428 return VLC_SUCCESS;
1431 /*****************************************************************************
1432 * Close:
1433 *****************************************************************************/
1434 static void Close( vlc_object_t *p_this )
1436 decoder_t *p_dec = (decoder_t*)p_this;
1437 decoder_sys_t *p_sys = p_dec->p_sys;
1439 block_BytestreamRelease( &p_sys->bytestream );
1440 if( p_sys->p_outqueue )
1441 block_ChainRelease( p_sys->p_outqueue );
1442 if( p_sys->p_eu )
1443 block_ChainRelease( p_sys->p_eu );
1444 free( p_sys );