]> git.sesse.net Git - vlc/blob - modules/packetizer/dirac.c
Packetizer is capable of:
[vlc] / modules / packetizer / dirac.c
1 /*****************************************************************************
2  * dirac.c
3  *****************************************************************************
4  * Copyright (C) 2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: David Flynn <davidf@rd.bbc.co.uk>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /* Dirac packetizer, formed of three parts:
25  *  1) Bitstream synchroniser (dirac_DoSync)
26  *      - Given an arbitary 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.)
52  *
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).
57  */
58
59 /*****************************************************************************
60  * Preamble
61  *****************************************************************************/
62
63 #ifdef HAVE_CONFIG_H
64 # include "config.h"
65 #endif
66
67 #include <assert.h>
68 #include <vlc_common.h>
69 #include <vlc_plugin.h>
70 #include <vlc_codec.h>
71 #include <vlc_block.h>
72
73 #include "vlc_bits.h"
74 #include "vlc_block_helper.h"
75
76 #define SANITIZE_PREV_PARSE_OFFSET 1
77
78 /*****************************************************************************
79  * Module descriptor
80  *****************************************************************************/
81 static int  Open ( vlc_object_t * );
82 static void Close( vlc_object_t * );
83
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()
91
92 /*****************************************************************************
93  * Local prototypes
94  *****************************************************************************/
95 struct decoder_sys_t
96 {
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;
107
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;
114
115     /* timestamp generator state */
116     date_t dts; /*< timegen decode clock, increments at picture rate */
117     bool b_dts; /*< timegen decode clock valid */
118
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 */
122
123     mtime_t i_pts_offset; /*< maximum time between pts and dts */
124
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;
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 */
133     block_t *p_out_dts;
134
135     uint32_t u_tg_last_picnum; /*< most recent picturenumber output from RoB */
136     bool b_tg_last_picnum; /*< u_tg_last_picnum valid */
137
138     struct dirac_reorder_buffer {
139         int u_size_max;
140         int u_size;
141         struct dirac_reorder_entry {
142             struct dirac_reorder_entry *p_next;
143             block_t *p_eu;
144             uint32_t u_picnum;
145         } p_entries[32], *p_head, *p_empty;
146     } reorder_buf; /*< reorder buffer, used by timegenerator */
147
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 */
151
152     struct seq_hdr_t {
153         uint32_t u_width;
154         uint32_t u_height;
155         uint32_t u_fps_num;
156         uint32_t u_fps_den;
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 */
164 };
165
166 typedef struct {
167     uint32_t u_next_offset;
168     uint32_t u_prev_offset;
169     int i_parse_code;
170 } parse_info_t;
171
172 typedef struct {
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;
179
180 enum {
181     NOT_SYNCED=0,
182     TRY_SYNC,
183     SYNCED,
184     SYNCED_INCOMPLETEDU,
185 };
186
187 enum {
188     DIRAC_EOS = 0x02000000,
189     DIRAC_NON_DATED = 0x04000000,
190     DIRAC_DISCARD = 0x08000000,
191 };
192
193 enum {
194     DIRAC_DU_IN_EU,
195     DIRAC_DU_ENDS_EU,
196 };
197
198 /***
199  * Block encapsulation functions.
200  * Things are greately simplified by associating some metadata
201  * with a block as it passes through the packetizer (saves having
202  * to determine it again)
203  *
204  * unfortunately p_block doesn't have a p_priv, so some fakage
205  * needs to happen:
206  *   - Create a dummy block that has some extra storage, set up
207  *     members to be identical to the actual block
208  *   - Store private data there and pointer to orig block
209  *   - modify block pointer to point to fake block
210  *
211  * NB, the add/new functions must not be used to blocks
212  * that are referenced in lists, etc., [in this code, this is ok]
213  * NB, don't call add on the same block multiple times (will leak)
214  *
215  * davidf has a patch that reverts this to use a p_priv in block_t.
216  */
217 typedef struct {
218     block_t fake;
219     block_t *p_orig;
220     void *p_priv;
221 } fake_block_t;
222
223 static dirac_block_encap_t *dirac_RemoveBlockEncap( block_t *p_block )
224 {
225     fake_block_t *p_fake = (fake_block_t *)p_block;
226     dirac_block_encap_t *dbe = p_fake->p_priv;
227     if( !dbe ) return NULL;
228     p_fake->p_priv = NULL;
229     dbe->pf_blk_release = NULL;
230     return dbe;
231 }
232
233 static void dirac_ReleaseBlockAndEncap( block_t *p_block )
234 {
235     fake_block_t *p_fake = (fake_block_t *)p_block;
236     free( dirac_RemoveBlockEncap( p_block ) );
237     p_fake->p_orig->pf_release( p_fake->p_orig );
238     free( p_fake );
239 }
240
241 static void dirac_AddBlockEncap( block_t **pp_block, dirac_block_encap_t *p_dbe )
242 {
243     fake_block_t *p_fake = calloc( 1, sizeof( *p_fake ) );
244     assert( p_fake ); /* must not fail, fixby: adding a p_priv to block_t */
245     p_fake->p_orig = *pp_block;
246     memcpy( &p_fake->fake, *pp_block, sizeof( block_t ) );
247     *pp_block = &p_fake->fake;
248
249     p_fake->p_priv = p_dbe;
250     p_dbe->pf_blk_release = p_fake->p_orig->pf_release;
251     p_fake->fake.pf_release = dirac_ReleaseBlockAndEncap;
252 }
253
254 static dirac_block_encap_t *dirac_NewBlockEncap( block_t **pp_block )
255 {
256     dirac_block_encap_t *dbe = calloc( 1, sizeof( *dbe ) );
257     if( dbe ) dirac_AddBlockEncap( pp_block, dbe );
258     return dbe;
259 }
260
261 static dirac_block_encap_t *dirac_GetBlockEncap( block_t *p_block )
262 {
263     return (dirac_block_encap_t*) ((fake_block_t *)p_block)->p_priv;
264 }
265
266 /***
267  * General utility funcions
268  */
269
270 /* decrement a date. opposite to date_Increment */
271 static mtime_t date_Decrement( date_t *p_date, uint32_t i_nb_samples )
272 {
273     mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000 * p_date->i_divider_den;
274     p_date->date -= i_dividend / p_date->i_divider_num;
275     unsigned u_rem_adjust = i_dividend % p_date->i_divider_num;
276
277     if( p_date->i_remainder < u_rem_adjust )
278     {
279         /* This is Bresenham algorithm. */
280         assert( p_date->i_remainder > -p_date->i_divider_num);
281         p_date->date -= 1;
282         p_date->i_remainder += p_date->i_divider_num;
283     }
284
285     p_date->i_remainder -= u_rem_adjust;
286
287     return p_date->date;
288 }
289
290 /**
291  * given a chain of block_t, allocate and return an array containing
292  * pointers to all the blocks. (Acts as a replacement for the old p_prev
293  * member of block_t) */
294 static int block_ChainToArray( block_t *p_block, block_t ***ppp_array)
295 {
296     if( !ppp_array )
297         return 0;
298
299     int num_blocks;
300     block_ChainProperties( p_block, &num_blocks, NULL, NULL );
301
302     *ppp_array = malloc( sizeof( block_t* ) * num_blocks );
303     if( !ppp_array ) return 0;
304
305     for( int i = 0; i < num_blocks; i++ )
306     {
307         (*ppp_array)[i] = p_block;
308         p_block = p_block->p_next;
309     }
310
311     return num_blocks;
312 }
313
314 /**
315  * Destructively find and recover the earliest timestamp from start of
316  * bytestream, upto i_length.
317  */
318 static void dirac_RecoverTimestamps ( decoder_t *p_dec, size_t i_length )
319 {
320     decoder_sys_t *p_sys = p_dec->p_sys;
321     block_t *p_block = p_sys->bytestream.p_block;
322
323     /* Find the block with first non-flushed data */
324     size_t i_offset = p_sys->bytestream.i_offset;
325     for(; p_block != NULL; p_block = p_block->p_next )
326     {
327         if( i_offset < p_block->i_buffer )
328             break;
329         i_offset -= p_block->i_buffer;
330     }
331
332     i_offset += i_length;
333     for(; p_block != NULL; p_block = p_block->p_next )
334     {
335         if( p_sys->i_sync_pts == VLC_TS_INVALID && p_sys->i_sync_dts == VLC_TS_INVALID )
336         {
337             /* oldest timestamp wins */
338             p_sys->i_sync_pts = p_block->i_pts;
339             p_sys->i_sync_dts = p_block->i_dts;
340         }
341         /* clear timestamps -- more than one data unit can come from a block */
342         p_block->i_flags = 0;
343         p_block->i_pts = p_block->i_dts = VLC_TS_INVALID;
344         if( i_offset < p_block->i_buffer )
345             break;
346         i_offset -= p_block->i_buffer;
347     }
348 }
349
350 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
351 static void dirac_BackdateDTS( block_t *p_block, block_t *p_last, date_t *p_dts )
352 {
353     /* Transverse p_last backwards.  (no p_prev anymore) */
354     block_t **pp_array = NULL;
355     int n = block_ChainToArray( p_block, &pp_array );
356     while( n ) if( pp_array[--n] == p_last ) break;
357     /* want to start at p_last->p_prev */
358     while( n-- )
359     {
360         if( pp_array[n]->i_flags & DIRAC_NON_DATED )
361             continue;
362         if( pp_array[n]->i_dts == VLC_TS_INVALID )
363             pp_array[n]->i_dts = date_Decrement( p_dts, 1 );
364     }
365     free( pp_array );
366 }
367
368 /* backdate the list [p_block .. p_block->p_next where p_next == p_last] */
369 static void dirac_BackdatePTS( block_t *p_block, block_t *p_last, date_t *p_pts, uint32_t u_pts_picnum )
370 {
371     /* Transverse p_last backwards.  (no p_prev anymore) */
372     block_t **pp_array = NULL;
373     int n = block_ChainToArray( p_block, &pp_array );
374     while( n ) if( pp_array[--n] == p_last ) break;
375     /* want to start at p_last->p_prev */
376     while( n-- )
377     {
378         if( pp_array[n]->i_flags & DIRAC_NON_DATED )
379             continue;
380         if( pp_array[n]->i_dts != VLC_TS_INVALID )
381             continue;
382         dirac_block_encap_t *dbe = dirac_GetBlockEncap( pp_array[n] );
383         int32_t u_pic_num = dbe ? dbe->u_picture_number : 0;
384         int32_t i_dist = u_pic_num - u_pts_picnum;
385         date_t pts = *p_pts;
386         if( i_dist >= 0 )
387             pp_array[n]->i_pts = date_Increment( &pts, i_dist );
388         else
389             pp_array[n]->i_pts = date_Decrement( &pts, -i_dist );
390     }
391     free( pp_array );
392 }
393
394 /***
395  * Dirac spec defined relations
396  */
397
398 static bool dirac_isEOS( uint8_t u_parse_code ) { return 0x10 == u_parse_code; }
399 static bool dirac_isSeqHdr( uint8_t u_parse_code ) { return 0 == u_parse_code; }
400 static bool dirac_isPicture( uint8_t u_parse_code ) { return 0x08 & u_parse_code; }
401 static int dirac_numRefs( uint8_t u_parse_code ) { return 0x3 & u_parse_code; }
402
403 static inline bool dirac_PictureNbeforeM( uint32_t u_n, uint32_t u_m )
404 {
405     /* specified as: u_n occurs before u_m if:
406      *   (u_m - u_n) mod (1<<32) < D */
407     return (uint32_t)(u_m - u_n) < (1u<<31);
408 }
409
410 /***
411  * Reorder buffer model
412  */
413
414 static void dirac_ReorderInit( struct dirac_reorder_buffer *p_rb )
415 {
416     memset( p_rb, 0, sizeof(*p_rb) );
417     p_rb->u_size_max = 2;
418     p_rb->p_empty = p_rb->p_entries;
419     p_rb->p_entries[31].p_next = NULL;
420
421     for( int i = 0; i < 31; i++ ) {
422         p_rb->p_entries[i].p_next = &p_rb->p_entries[i+1];
423     }
424 }
425
426 /* simulate the dirac picture reorder buffer */
427 static block_t *dirac_Reorder( decoder_t *p_dec, block_t *p_block_in, uint32_t u_picnum )
428 {
429     decoder_sys_t *p_sys = p_dec->p_sys;
430
431     if( !p_sys->reorder_buf.u_size_max )
432         /* reorder buffer disabled */
433         return p_block_in;
434
435     /* Modeling the reorder buffer:
436      * 1. If the reorder buffer is not full, insert picture for reordering.
437      *    No picture is output by the system this picture period
438      * 2. If the reorder buffer is full:
439      *    a. The picture decoded this period (u_picnum) bypasses the reorder
440      *       buffer if it has a lower picture number than any entry in the
441      *       reorder buffer. This picture is output by the system.
442      *    b. Otherwise, the lowest picture number in the reorder buffer is
443      *       removed from the buffer and output by the system.  The current
444      *       decoded picture (u_picnum) is inserted into the reorder buffer
445      */
446
447     block_t *p_block = NULL;
448     /* Determine if the picture needs to be inserted */
449     if( p_sys->reorder_buf.u_size == p_sys->reorder_buf.u_size_max )
450     {
451         /* (2) reorder buffer is full */
452         if( !p_sys->reorder_buf.u_size_max ||
453             dirac_PictureNbeforeM( u_picnum, p_sys->reorder_buf.p_head->u_picnum ) )
454         {
455             /* (2a) current picture is first in order */
456             return p_block_in;
457         }
458
459         /* (2b) extract the youngest picture in the buffer */
460         p_block = p_sys->reorder_buf.p_head->p_eu;
461
462         struct dirac_reorder_entry *p_tmp = p_sys->reorder_buf.p_head;
463         p_sys->reorder_buf.p_head = p_tmp->p_next;
464         p_tmp->p_next = p_sys->reorder_buf.p_empty;
465         p_sys->reorder_buf.p_empty = p_tmp;
466
467         p_sys->reorder_buf.u_size--;
468     }
469
470     /* (1) and (2b) both require u_picnum to be inserted */
471     struct dirac_reorder_entry *p_current = p_sys->reorder_buf.p_empty;
472     p_sys->reorder_buf.p_empty = p_current->p_next;
473     p_sys->reorder_buf.u_size++;
474
475     /* insertion sort to keep p_head always sorted, earliest first */
476     struct dirac_reorder_entry **pp_at = &p_sys->reorder_buf.p_head;
477     for( ; *pp_at; pp_at = &(*pp_at)->p_next )
478         if( dirac_PictureNbeforeM( u_picnum, (*pp_at)->u_picnum ) )
479             break;
480
481     p_current->u_picnum = u_picnum;
482     p_current->p_eu = p_block_in;
483     p_current->p_next = *pp_at;
484     *pp_at = p_current;
485
486     return p_block;
487 }
488
489 /***
490  * bytestream parsing and unmarshalling functions
491  */
492
493 static bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs,
494                                    size_t u_offset )
495 {
496     uint8_t p_d[13];
497     if( VLC_SUCCESS != block_PeekOffsetBytes( p_bs, u_offset, p_d, 13 ) )
498         return false;
499
500     if( p_d[0] != 'B' || p_d[1] != 'B' || p_d[2] != 'C' || p_d[3] != 'D' )
501         return false;
502
503     p_pi->i_parse_code = p_d[4];
504     p_pi->u_next_offset = p_d[5] << 24 | p_d[6] << 16 | p_d[7] << 8 | p_d[8];
505     p_pi->u_prev_offset = p_d[9] << 24 | p_d[10] << 16 | p_d[11] << 8 | p_d[12];
506     return true;
507 }
508
509 static uint32_t dirac_uint( bs_t *p_bs )
510 {
511   uint32_t count = 0, value = 0;
512   while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
513   {
514     count++;
515     value <<= 1;
516     value |= bs_read( p_bs, 1 );
517   }
518
519   return (1 << count) - 1 + value;
520 }
521
522 static int dirac_bool( bs_t *p_bs )
523 {
524     return bs_read( p_bs, 1 );
525 }
526
527 /* read in useful bits from sequence header */
528 static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
529 {
530     bs_t bs;
531     bs_init( &bs, p_block->p_buffer, p_block->i_buffer );
532     bs_skip( &bs, 13*8 ); /* parse_info_header */
533     dirac_uint( &bs ); /* major_version */
534     dirac_uint( &bs ); /* minor_version */
535     dirac_uint( &bs ); /* profile */
536     dirac_uint( &bs ); /* level */
537
538     uint32_t u_video_format = dirac_uint( &bs ); /* index */
539     if( u_video_format > 20 )
540     {
541         /* dont know how to parse this header */
542         return false;
543     }
544
545     static const struct {
546         uint32_t u_w, u_h;
547     } dirac_size_tbl[] = {
548         {640,480}, {176,120}, {176,144}, {352,240}, {352,288}, {704,480},
549         {704,576}, {720,480}, {720,576}, {1280,720}, {1280,720}, {1920,1080},
550         {1920,1080}, {1920,1080}, {1920,1080}, {2048,1080}, {4096,2160},
551         {3840,2160}, {3840,2160}, {7680,4320}, {7680,4320},
552     };
553
554     p_sh->u_width = dirac_size_tbl[u_video_format].u_w;
555     p_sh->u_height = dirac_size_tbl[u_video_format].u_h;
556     if( dirac_bool( &bs ) )
557     {
558         p_sh->u_width = dirac_uint( &bs ); /* frame_width */
559         p_sh->u_height = dirac_uint( &bs ); /* frame_height */
560     }
561
562     if( dirac_bool( &bs ) )
563     {
564         dirac_uint( &bs ); /* chroma_format */
565     }
566
567     if( dirac_bool( &bs ) )
568     {
569         dirac_uint( &bs ); /* scan_format */
570     }
571
572     static const struct {
573         uint32_t u_n /* numerator */, u_d /* denominator */;
574     } dirac_frate_tbl[] = { /* table 10.3 */
575         {1, 1}, /* this value is not used */
576         {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
577         {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
578     };
579
580     const unsigned dirac_frate_tbl_size =
581         sizeof( dirac_frate_tbl ) / sizeof( *dirac_frate_tbl );
582
583     static const uint32_t dirac_vidfmt_frate[] = { /* table C.1 */
584         1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
585     };
586
587     p_sh->u_fps_num = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_n;
588     p_sh->u_fps_den = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_d;
589     if( dirac_bool( &bs ) )
590     {
591         uint32_t frame_rate_index = dirac_uint( &bs );
592         p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n;
593         p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d;
594         if( frame_rate_index >= dirac_frate_tbl_size )
595         {
596             /* invalid header */
597             return false;
598         }
599         if( frame_rate_index == 0 )
600         {
601             p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */
602             p_sh->u_fps_den = dirac_uint( &bs ); /* frame_rate_denominator */
603         }
604     }
605
606     /* must have a valid framerate */
607     if( !p_sh->u_fps_num || !p_sh->u_fps_den )
608         return false;
609
610     if( dirac_bool( &bs ) )
611     {
612         uint32_t par_index = dirac_uint( &bs );
613         if( !par_index )
614         {
615             dirac_uint( &bs ); /* par_num */
616             dirac_uint( &bs ); /* par_den */
617         }
618     }
619
620     if( dirac_bool( &bs ) )
621     {
622         dirac_uint( &bs ); /* clean_width */
623         dirac_uint( &bs ); /* clean_height */
624         dirac_uint( &bs ); /* clean_left_offset */
625         dirac_uint( &bs ); /* clean_top_offset */
626     }
627
628     if( dirac_bool( &bs ) )
629     {
630         uint32_t signal_range_index = dirac_uint( &bs );
631         if( !signal_range_index )
632         {
633             dirac_uint( &bs ); /* luma_offset */
634             dirac_uint( &bs ); /* luma_excursion */
635             dirac_uint( &bs ); /* chroma_offset */
636             dirac_uint( &bs ); /* chroma_excursion */
637         }
638     }
639
640     if( dirac_bool( &bs ) )
641     {
642         uint32_t colour_spec_index = dirac_uint( &bs );
643         if( !colour_spec_index )
644         {
645             if( dirac_bool( &bs ) )
646             {
647                 dirac_uint( &bs ); /* colour_primaries_index */
648             }
649             if( dirac_bool( &bs ) )
650             {
651                 dirac_uint( &bs ); /* colour_matrix_index */
652             }
653             if( dirac_bool( &bs ) )
654             {
655                 dirac_uint( &bs ); /* transfer_function_index */
656             }
657         }
658     }
659
660     p_sh->u_picture_coding_mode = dirac_uint( &bs );
661
662     return true;
663 }
664
665 /***
666  * Data Unit marshalling functions
667  */
668
669 static block_t *dirac_EmitEOS( decoder_t *p_dec, uint32_t i_prev_parse_offset )
670 {
671     const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
672     block_t *p_block = block_New( p_dec, 13 );
673     if( !p_block )
674         return NULL;
675     memcpy( p_block->p_buffer, eos, 13 );
676
677     SetDWBE( p_block->p_buffer + 9, i_prev_parse_offset );
678
679     p_block->i_flags = DIRAC_NON_DATED;
680
681     return p_block;
682
683     (void) p_dec;
684 }
685
686 /***
687  * Bytestream synchronizer
688  * maps [Bytes] -> DataUnit
689  */
690 static block_t *dirac_DoSync( decoder_t *p_dec )
691 {
692     decoder_sys_t *p_sys = p_dec->p_sys;
693     parse_info_t pu;
694
695     static const uint8_t p_parsecode[4] = {'B','B','C','D'};
696     do {
697         switch( p_sys->i_state )
698         {
699         case NOT_SYNCED: {
700             if( VLC_SUCCESS !=
701                 block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_parsecode, 4 ) )
702             {
703                 /* p_sys->i_offset will have been set to:
704                  *   end of bytestream - amount of prefix found
705                  * can resume search from this point when more data arrives */
706                 return NULL;
707             }
708             /* candidate parse_code_prefix has been found at p_sys->i_offset */
709             if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_offset + 12, NULL, 0 ) )
710             {
711                 /* insufficient data has been accumulated to fully extract
712                  * a parse_info header. exit for now in the hope of more
713                  * data later to retry at exactly the same point */
714                 return NULL;
715             }
716             p_sys->i_state = TRY_SYNC;
717             break; /* candidate found, try to sync */
718         }
719         case SYNCED: /* -> TRY_SYNC | NOT_SYNCED */
720             /* sanity: can only reach this after having extracted a DU,
721              * which causes data to be consumed and local i_offset to be reset */
722             assert( p_sys->i_offset == 0 );
723             if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, 12, NULL, 0 ) )
724             {
725                 /* insufficient data has been accumulated to fully extract
726                  * a parse_info header, retry later */
727                 return NULL;
728             }
729             if( !dirac_UnpackParseInfo( &pu, &p_sys->bytestream, 0 )
730              || !pu.u_next_offset || (p_sys->u_last_npo != pu.u_prev_offset) )
731             {
732                 /* !a: not a valid parse info.
733                  * !pu.u_next_offset: don't know the length of the data unit
734                  *                    search for the next one that points back
735                  *                    to this one to determine length.
736                  * (p_sys->u_last_npo != pu.u_prev_offset): some desync
737                  */
738                 p_sys->i_state = NOT_SYNCED;
739                 break;
740             }
741             if( pu.u_next_offset > 1024*1024 )
742             {
743                 /* sanity check for erronious hugs next_parse_offsets
744                  * (eg, 2^32-1) that would cause a very long wait
745                  * and large space consumption: fall back to try sync */
746                 p_sys->i_state = TRY_SYNC;
747                 break;
748             }
749             /* check that the start of the next data unit is avaliable */
750             if( VLC_SUCCESS !=
751                 block_PeekOffsetBytes( &p_sys->bytestream, pu.u_next_offset + 12, NULL, 0 ) )
752             {
753                 return NULL; /* retry later */
754             }
755             /* attempt to syncronise backwards from pu.u_next_offset */
756             p_sys->i_offset = pu.u_next_offset;
757             /* fall through */
758         case TRY_SYNC: { /* -> SYNCED | NOT_SYNCED */
759             if( !p_sys->i_offset ) {
760                 goto sync_fail; /* if a is at start of bytestream, b can't be in buffer */
761             }
762
763             parse_info_t pu_a;
764             bool a = dirac_UnpackParseInfo( &pu_a, &p_sys->bytestream, p_sys->i_offset );
765             if( !a || (pu_a.u_prev_offset > p_sys->i_offset) ) {
766                 goto sync_fail; /* b lies beyond start of bytestream: can't sync */
767             }
768
769             if( !pu_a.u_prev_offset ) {
770                 if( p_sys->i_state == TRY_SYNC )
771                 {
772                     goto sync_fail; /* can't find different pu_b from pu_a */
773                 }
774                 /* state == SYNCED: already know where pu_b is.
775                  * pu_a has probably been inserted by something that doesn't
776                  * know what the last next_parse_offset was */
777                 pu_a.u_prev_offset = pu.u_next_offset;
778             }
779
780             parse_info_t *pu_b = &pu;
781             bool b = dirac_UnpackParseInfo( pu_b, &p_sys->bytestream, p_sys->i_offset - pu_a.u_prev_offset );
782             if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) ) {
783                 /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
784                  * just rely on finding a valid pu_b from pu_a. */
785                 goto sync_fail;
786             }
787             p_sys->u_last_npo = pu_b->u_next_offset;
788             if( !pu_b->u_next_offset ) pu_b->u_next_offset = pu_a.u_prev_offset;
789             /* offset was pointing at pu_a, rewind to point at pu_b */
790             p_sys->i_offset -= pu_a.u_prev_offset;
791             p_sys->i_state = SYNCED;
792             break;
793         }
794 sync_fail:
795             if( p_sys->i_state == SYNCED ) p_sys->i_offset = 0;
796             p_sys->i_offset++;
797             p_sys->i_state = NOT_SYNCED;
798             break; /* find somewhere else to try again */
799         default:;
800         }
801     } while( SYNCED != p_sys->i_state );
802
803     /*
804      * synced, attempt to extract a data unit
805      */
806
807     /* recover any timestamps from the data that is about to be flushed */
808     dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
809
810     /* flush everything upto the start of the DU */
811     block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
812     block_BytestreamFlush( &p_sys->bytestream );
813     p_sys->i_offset = 0;
814
815     /* setup the data unit buffer */
816     block_t *p_block = block_New( p_dec, pu.u_next_offset );
817     if( !p_block )
818         return NULL;
819
820     p_block->i_pts = p_sys->i_sync_pts;
821     p_block->i_dts = p_sys->i_sync_dts;
822     p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
823
824     /* recover any new timestamps from the data that is about to be consumed */
825     dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
826
827     block_GetBytes( &p_sys->bytestream, p_block->p_buffer, p_block->i_buffer );
828
829     /* save parse offset in private area for later use */
830     dirac_block_encap_t *dbe = dirac_NewBlockEncap( &p_block );
831     if( dbe ) dbe->u_last_next_offset = pu.u_next_offset;
832
833     return p_block;
834 }
835
836 /***
837  * Packet (Data Unit) inspection, learns parameters from sequence
838  * headers, sets up flags, drops unwanted data units, sets
839  * encapsulation unit termination policy
840  */
841 static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu )
842 {
843     decoder_sys_t *p_sys = p_dec->p_sys;
844     block_t *p_block = *pp_block;
845     uint8_t u_parse_code = p_block->p_buffer[4];
846
847     if( dirac_isEOS( u_parse_code ) )
848     {
849         if( p_sys->b_seen_eos )
850         {
851             /* remove duplicate EOS packets */
852             block_Release( p_block );
853             *pp_block = NULL;
854             return DIRAC_DU_IN_EU;
855         }
856         /* p_block is an EOS packet */
857         p_eu->i_flags |= DIRAC_EOS;
858         /* for the moment, let this end an encapsulation unit */
859         /* seeing an eos packet requires a flush of the packetizer
860          * this is detected by the caller of this function */
861         p_sys->b_seen_seq_hdr = false;
862         p_sys->b_seen_eos = true;
863         return DIRAC_DU_ENDS_EU;
864 #if 0
865         /* let anything down streem know too */
866         /*
867         Actually, this is a bad idea:
868          - It sets the discontinuity for every dirac EOS packet
869            which doesnt imply a time discontinuity.
870          - When the syncronizer detects a real discontinuity, it
871            should copy the flags through.
872         p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
873         */
874 #endif
875     }
876     p_sys->b_seen_eos = false;
877
878     if( dirac_isPicture( u_parse_code ) )
879     {
880         /* timestamps apply to pictures only */
881         p_eu->i_dts = p_sys->i_eu_dts;
882         p_eu->i_pts = p_sys->i_eu_pts;
883         p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
884
885         if( !p_sys->b_seen_seq_hdr )
886         {
887             /* can't timestamp in this case, discard later
888              * so that the timestamps aren't lost */
889             p_eu->i_flags |= DIRAC_DISCARD;
890         }
891         /* p_block is a picture -- it ends the 'encapsulation unit' */
892         if( dirac_numRefs( u_parse_code ) )
893         {
894             /* if this picture is not an I frame, ensure that the
895              * random access point flags are not set */
896             p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
897         }
898         dirac_block_encap_t *dbe = dirac_GetBlockEncap( p_block );
899         if( dbe && p_block->i_buffer > 13+4 )
900         {
901             /* record the picture number to save the time gen functions
902              * from having to inspect the data for it */
903             dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
904         }
905         return DIRAC_DU_ENDS_EU;
906     }
907
908     if( dirac_isSeqHdr( u_parse_code ) )
909     {
910         if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) )
911         {
912             /* couldn't parse the sequence header, just ignore it */
913             return DIRAC_DU_IN_EU;
914         }
915         p_sys->b_seen_seq_hdr = true;
916
917        /* a sequence header followed by an I frame is a random
918         * access point; assume that this is the case */
919         p_eu->i_flags |= BLOCK_FLAG_TYPE_I;
920
921         es_format_t *p_es = &p_dec->fmt_out;
922
923         p_es->video.i_width  = p_sys->seq_hdr.u_width;
924         p_es->video.i_height = p_sys->seq_hdr.u_height;
925
926         vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
927                    , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );
928
929         /* when field coding, dts needs to be incremented in terms of field periods */
930         int u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
931         if (p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING)
932         {
933             u_pics_per_sec *= 2;
934         }
935         date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den );
936
937         /* TODO: set p_sys->reorder_buf.u_size_max */
938         p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max
939                             * 1000000
940                             * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1;
941
942         /* stash a copy of the seqhdr
943          *  - required for ogg muxing
944          *  - useful for error checking
945          *  - it isn't allowed to change until an eos */
946         if( p_es->p_extra )
947             free( p_es->p_extra );
948         p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
949         if( !p_es->p_extra )
950         {
951             p_es->i_extra = 0;
952             return DIRAC_DU_IN_EU;
953         }
954         p_es->i_extra = p_block->i_buffer;
955         memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer );
956         /* append EOS as per Ogg guidelines */
957         p_block = dirac_EmitEOS( p_dec, p_block->i_buffer );
958         if( p_block )
959         {
960             memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 );
961             p_es->i_extra += 13;
962         }
963
964         return DIRAC_DU_IN_EU;
965     }
966
967     /* doesn't end an encapsulation unit */
968     return DIRAC_DU_IN_EU;
969 }
970
971 /***
972  * Encapsulation (packetization) suitable for all muxing standards
973  * maps [DataUnit] -> EncapsulationUnit
974  */
975 static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block )
976 {
977     decoder_sys_t *p_sys = p_dec->p_sys;
978
979     assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer ));
980
981     if( p_sys->i_eu_pts == VLC_TS_INVALID && p_sys->i_eu_dts == VLC_TS_INVALID )
982     {
983         /* earliest block with pts/dts gets to set the pts/dts for the dated
984          * encapsulation unit as a whole */
985         /* NB, the 'earliest block' criteria is aribtary */
986         if( p_block->i_pts != VLC_TS_INVALID || p_block->i_dts != VLC_TS_INVALID )
987         {
988             p_sys->i_eu_pts = p_block->i_pts;
989             p_sys->i_eu_dts = p_block->i_dts;
990         }
991     }
992
993     /* inpectdataunit also updates flags for the EU.
994      *  - if this is the first block in the EU, then it hasn't been added
995      *    to the chain yet (so, p_block will become the front of the chain
996      *  - otherwise, use the flags of the chain (first block) */
997     block_t *p_eu = p_sys->p_eu ? p_sys->p_eu : p_block;
998     int i_block = dirac_InspectDataUnit( p_dec, &p_block, p_eu);
999
1000     if( !p_block )
1001     {
1002         /* block has been discarded during inspection */
1003         /* becareful, don't discard anything that is dated,
1004          * as this needs to go into the timegen loop.  set
1005          * the DIRAC_DISCARD block flag, and it'll be dropped
1006          * at output time */
1007         return NULL;
1008     }
1009
1010     block_ChainLastAppend( &p_sys->pp_eu_last, p_block );
1011
1012     dirac_block_encap_t *dbe = dirac_GetBlockEncap( p_block );
1013 #ifdef SANITIZE_PREV_PARSE_OFFSET
1014     /* fixup prev_parse_offset to point to the last data unit
1015      * to arrive */
1016     if( dbe )
1017     {
1018         SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo );
1019         p_sys->u_eu_last_npo = dbe->u_last_next_offset;
1020     }
1021 #endif
1022
1023     if( i_block != DIRAC_DU_ENDS_EU )
1024     {
1025         /* encapsulation unit not ended */
1026         return NULL;
1027     }
1028
1029     /* gather up encapsulation unit, reassociating the final
1030      * private state with the gathered block */
1031     block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next );
1032     dbe = dirac_RemoveBlockEncap( p_eu_last );
1033
1034     uint8_t u_parse_code = p_block->p_buffer[4];
1035
1036     /* gather up the encapsulation unit */
1037     p_block = block_ChainGather( p_sys->p_eu );
1038     assert( p_block ); /* block_ChainGather doesn't define when it frees chain */
1039
1040     p_block->i_flags |= DIRAC_NON_DATED;
1041     if( dbe )
1042     {
1043         dirac_AddBlockEncap( &p_block, dbe );
1044         if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED;
1045     }
1046     p_sys->p_eu = NULL;
1047     p_sys->pp_eu_last = &p_sys->p_eu;
1048     return p_block;
1049 }
1050
1051 /**
1052  * dirac_TimeGenPush:
1053  * @p_dec: vlc object
1054  * @p_block_in: whole encapsulation unit to generate timestamps for
1055  *
1056  * Returns:
1057  *  0: everything ok
1058  *  1: EOS occured, please flush and reset
1059  *  2: picture number discontinuity, please flush and reset
1060  */
1061 static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
1062 {
1063     decoder_sys_t *p_sys = p_dec->p_sys;
1064     dirac_block_encap_t *dbe;
1065
1066     if( p_block_in->i_flags & DIRAC_EOS )
1067     {
1068         /* NB, this test occurs after the timegen push, so as to
1069          * push the block into the output queue */
1070         return 1;
1071     }
1072
1073     if( p_block_in->i_flags & DIRAC_NON_DATED )
1074     {
1075         /* no picture found, which means p_block_in is a non-dated EU,
1076          * do not try and put a date on it */
1077         return 0;
1078     }
1079
1080     dbe = dirac_GetBlockEncap( p_block_in );
1081     uint32_t u_picnum = dbe ? dbe->u_picture_number : 0;
1082     /*
1083      * Simple DTS regeneration:
1084      *  - DTS values linearly increase in stream order.
1085      *  - Every time a DTS occurs at the input, sync to it
1086      *    - If this is the first DTS seen, backdate all the previous ones that are undated
1087      *  - If a DTS is missing, guess that it increases by one picture period
1088      *  - If never seen DTS, don't do anything
1089      */
1090     /*
1091      * Simple PTS regeneration
1092      *  - PTS values do not linearly increase in stream order.
1093      *  - Every time a PTS occurs at the input, sync to it and record picture number
1094      *  - If a PTS is missing, guess that it differs by the product of picture
1095      *    period and difference between picture number of sync point and current picture
1096      *  - If this is the first PTS seen, backdate all previous ones that are undated
1097      *  - If never seen PTS, don't do anything
1098      */
1099     /*
1100      * Stage 1, sync to input timestamps, backdate timestamps for old
1101      * EUs that are in the outqueue with missing dates
1102      */
1103     if( p_block_in->i_dts != VLC_TS_INVALID )
1104     do {
1105         /* if timestamps exist, sync to them */
1106         if( p_sys->b_dts )
1107             break;
1108         /* first dts seen, backdate any packets in outqueue */
1109         p_sys->b_dts = true;
1110         date_t dts = p_sys->dts;
1111         dirac_BackdateDTS( p_sys->p_outqueue, p_block_in, &dts );
1112     } while( 0 );
1113
1114     if( p_block_in->i_pts != VLC_TS_INVALID )
1115     do {
1116         /* if timestamps exist, sync to them */
1117         p_sys->u_pts_picnum = u_picnum;
1118         p_sys->i_pts = p_block_in->i_pts;
1119         if( p_sys->b_pts )
1120             break;
1121         /* first pts seen, backdate any packets in outqueue */
1122         p_sys->b_pts = true;
1123         date_t pts = p_sys->dts;
1124         date_Set( &pts, p_sys->i_pts );
1125         dirac_BackdatePTS( p_sys->p_outqueue, p_block_in, &pts, p_sys->u_pts_picnum );
1126     } while( 0 );
1127
1128     /*
1129      * Stage 2, don't attempt to forwards interpolate timestamps for
1130      * blocks if the picture rates aren't known
1131      */
1132     if( !p_sys->b_seen_seq_hdr )
1133     {
1134         return 0;
1135     }
1136
1137     /*
1138      * Stage 3, for block_in, interpolate any missing timestamps
1139      */
1140     if( p_sys->b_dts && p_block_in->i_dts == VLC_TS_INVALID )
1141     {
1142         /* dts has previously been seen, but not this time, interpolate */
1143         p_block_in->i_dts = date_Increment( &p_sys->dts, 1 );
1144     }
1145
1146     if( p_sys->b_pts && p_block_in->i_pts == VLC_TS_INVALID )
1147     {
1148         /* pts has previously been seen, but not this time, interpolate */
1149         date_t pts = p_sys->dts;
1150         date_Set( &pts, p_sys->i_pts );
1151         int32_t i_dist = u_picnum - p_sys->u_pts_picnum;
1152         if( i_dist >= 0 )
1153             p_block_in->i_pts = date_Increment( &pts, i_dist );
1154         else
1155             p_block_in->i_pts = date_Decrement( &pts, -i_dist );
1156     }
1157
1158     /* If pts and dts have been seen, there is no need to simulate operation
1159      * of the decoder reorder buffer */
1160     /* If neither have been seen, there is little point in simulating */
1161     if( p_sys->b_dts == p_sys->b_pts )
1162         return 0;
1163
1164     if( !p_sys->p_out_dts )
1165         p_sys->p_out_dts = p_sys->p_outqueue;
1166
1167     /* model the reorder buffer */
1168     block_t *p_block = dirac_Reorder( p_dec, p_block_in, u_picnum );
1169     if( !p_block )
1170         return 0;
1171
1172     /* A future ehancement is to stop modeling the reorder buffer as soon as
1173      * the first packet is output -- interpolate the past and freewheel for
1174      * the future */
1175
1176     dbe = dirac_GetBlockEncap( p_block );
1177     u_picnum = dbe ? dbe->u_picture_number : 0;
1178     if( p_sys->b_tg_last_picnum )
1179     {
1180         if( dirac_PictureNbeforeM( u_picnum, p_sys->u_tg_last_picnum ) )
1181         {
1182             msg_Warn( p_dec, "stream jumped? %d < %d: resetting"
1183                     , u_picnum, p_sys->u_tg_last_picnum );
1184             /* pictures only emerge from the reorder buffer in sequence
1185              * if a stream suddenly jumped backwards without a signaling
1186              * a discontinuity, some pictures will get stuck in the RoB.
1187              * flush the RoB. */
1188             /* this could be a bit less indiscriminate */
1189             dbe = dirac_GetBlockEncap( p_sys->p_outqueue );
1190             uint32_t u_prev_parse_offset = dbe ? dbe->u_last_next_offset : 0;
1191             block_ChainRelease( p_sys->p_outqueue );
1192             p_sys->p_outqueue = dirac_EmitEOS( p_dec, u_prev_parse_offset );
1193             if( p_sys->p_outqueue )
1194                 p_sys->p_outqueue->i_flags = BLOCK_FLAG_DISCONTINUITY | DIRAC_NON_DATED;
1195             /* return 2, so as not to reset the b_dts flags -- needed if
1196              * using the rawdirac demuxer with broken stream */
1197             return 2;
1198         }
1199     }
1200     p_sys->b_tg_last_picnum = true;
1201     p_sys->u_tg_last_picnum = u_picnum;
1202
1203     if( !p_sys->b_pts )
1204     {
1205         /* some demuxers (eg, AVI) will provide a series of fake dts values,
1206          * which are actually inorder pts values (ie, what should be seen at
1207          * the output of a decoder.  A main reason for simulating the reorder
1208          * buffer is to turn the inorder fakedts into an out-of-order pts */
1209         p_block->i_pts = p_sys->p_out_dts->i_dts;
1210         p_sys->p_out_dts->i_dts = VLC_TS_INVALID;
1211     }
1212
1213     /* If pts was copied from dts, the dts needs to be corrected to account for reordering*/
1214     /* If dts has never been seen, the same needs to happen */
1215     p_sys->p_out_dts->i_dts = p_block->i_pts - p_sys->i_pts_offset;
1216
1217     /* move dts pointer */
1218     if( p_sys->p_out_dts )
1219         p_sys->p_out_dts = p_sys->p_out_dts->p_next;
1220
1221     return 0;
1222 }
1223
1224 /*****************************************************************************
1225  * Packetize: form dated encapsulation units from anything
1226  *****************************************************************************/
1227 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
1228 {
1229     decoder_sys_t *p_sys = p_dec->p_sys;
1230     block_t *p_block = NULL;
1231     int i_flushing = 0;
1232
1233     while( pp_block && *pp_block )
1234     {
1235         p_block = *pp_block;
1236         *pp_block = p_block->p_next;
1237         p_block->p_next = NULL;
1238
1239         if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
1240         {
1241             /* silently discard corruption sentinels,
1242              * synchronizer will then discard affected data units.
1243              * do not produce an EOS data unit as this is very
1244              * disruptive to the stream (and may make a larger error). */
1245             block_Release( p_block );
1246             continue;
1247         }
1248         if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
1249         {
1250             /* pre-emptively insert an EOS at a discontinuity, protects
1251              * any decoders from any sudden changes */
1252             block_Release( p_block );
1253             p_block = dirac_EmitEOS( p_dec, 0 );
1254             if( p_block )
1255             {
1256                 p_block->p_next = dirac_EmitEOS( p_dec, 13 );
1257                 /* need two EOS to ensure it gets detected by syncro
1258                  * duplicates get discarded in forming encapsulation unit */
1259             }
1260         }
1261         block_BytestreamPush( &p_sys->bytestream, p_block );
1262     }
1263
1264     /* form as many encapsulation units as possible, give up
1265      * when the syncronizer runs out of input data */
1266     while( ( p_block = dirac_DoSync( p_dec ) ) )
1267     {
1268         p_block = dirac_BuildEncapsulationUnit( p_dec, p_block );
1269         if( !p_block )
1270             continue;
1271         /* add to tail of output queue (ie, not reordered) */
1272         block_ChainLastAppend( &p_sys->pp_outqueue_last, p_block );
1273         /* insert encapsulation unit into timestamp generator
1274          * which then calculates some timestamps if required */
1275         i_flushing = dirac_TimeGenPush( p_dec, p_block );
1276         if( i_flushing )
1277             break;
1278     }
1279
1280     block_t *p_output = NULL;
1281     block_t **pp_output = &p_output;
1282
1283     /* extract all the dated packets from the head of the ouput queue */
1284     /* explicitly nondated packets repeat the previous timestamps to
1285      * stop vlc discarding them */
1286     while( (p_block = p_sys->p_outqueue) )
1287     {
1288         if( p_block->i_flags & DIRAC_DISCARD )
1289         {
1290             p_sys->p_outqueue = p_block->p_next;
1291             p_block->p_next = NULL;
1292             block_Release( p_block );
1293             continue;
1294         }
1295
1296         if( i_flushing || p_block->i_flags & DIRAC_NON_DATED )
1297         {
1298             p_block->i_dts = p_sys->i_dts_last_out;
1299             p_block->i_pts = p_sys->i_pts_last_out;
1300         }
1301         else if( p_block->i_pts == VLC_TS_INVALID ) break;
1302         else if( p_block->i_dts == VLC_TS_INVALID ) break;
1303
1304         p_sys->i_dts_last_out = p_block->i_dts;
1305         p_sys->i_pts_last_out = p_block->i_pts;
1306
1307         p_sys->p_outqueue = p_block->p_next;
1308         p_block->p_next = NULL;
1309         /* clear any flags we set */
1310         p_block->i_flags &= ~BLOCK_FLAG_PRIVATE_MASK;
1311         block_ChainLastAppend( &pp_output, p_block );
1312
1313         mtime_t i_delay = p_block->i_pts - p_block->i_dts;
1314         if( i_delay < 0 )
1315             msg_Err( p_dec, "pts - dts is negative(%"PRId64"): incorrect RoB size", i_delay );
1316     }
1317
1318     if( i_flushing )
1319     {
1320         p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
1321
1322         /* reset timegen state (except synchronizer) */
1323         p_sys->b_seen_seq_hdr = false;
1324         if( i_flushing < 2 )
1325         {
1326             /* this state isn't safe to loose if there was
1327              * an unsignalled discontinuity */
1328             p_sys->b_pts = p_sys->b_dts = false;
1329         }
1330         p_sys->b_tg_last_picnum = false;
1331         dirac_ReorderInit( &p_sys->reorder_buf );
1332
1333         assert( p_sys->p_outqueue == NULL );
1334         p_sys->p_out_dts = NULL;
1335     }
1336
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     unsigned count = 0;
1344     for( p_block = p_sys->p_outqueue; p_block; p_block = p_block->p_next )
1345     {
1346         count++;
1347     }
1348     if( count > 9 )
1349     {
1350         p_block = p_sys->p_outqueue;
1351         while( p_block )
1352         {
1353             block_t *p_block_next = p_block->p_next;
1354             if( p_block->i_pts != VLC_TS_INVALID && p_block->i_dts != VLC_TS_INVALID )
1355                 break;
1356             block_Release( p_block );
1357             p_sys->p_outqueue = p_block = p_block_next;
1358         }
1359     }
1360
1361     if( !p_sys->p_outqueue )
1362     {
1363         p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1364     }
1365     return p_output;
1366 }
1367
1368 /*****************************************************************************
1369  * Open: probe the packetizer and return score
1370  *****************************************************************************/
1371 static int Open( vlc_object_t *p_this )
1372 {
1373     decoder_t     *p_dec = (decoder_t*)p_this;
1374     decoder_sys_t *p_sys;
1375
1376     if( p_dec->fmt_in.i_codec !=  VLC_FOURCC( 'd','r','a','c' ) )
1377         return VLC_EGENERIC;
1378
1379     p_dec->pf_packetize = Packetize;
1380
1381     /* Create the output format */
1382     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
1383     p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
1384
1385     if( !p_sys )
1386         return VLC_ENOMEM;
1387
1388     p_sys->i_eu_pts = p_sys->i_eu_dts = VLC_TS_INVALID;
1389     p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
1390     p_sys->i_dts_last_out = p_sys->i_pts_last_out = VLC_TS_INVALID;
1391
1392     p_sys->i_state = NOT_SYNCED;
1393     p_sys->bytestream = block_BytestreamInit();
1394
1395     p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1396     p_sys->pp_eu_last = &p_sys->p_eu;
1397
1398     date_Init( &p_sys->dts, 1, 1 );
1399     dirac_ReorderInit( &p_sys->reorder_buf );
1400
1401     if( p_dec->fmt_in.i_extra > 0 )
1402     {
1403         /* handle hacky systems like ogg that dump some headers
1404          * in p_extra. and packetizers that expect it to be filled
1405          * in before real startup */
1406         block_t *p_init = block_New( p_dec, p_dec->fmt_in.i_extra );
1407         if( !p_init )
1408         {
1409             /* memory might be avaliable soon.  it isn't the end of
1410              * the world that fmt_in.i_extra isn't handled */
1411             return VLC_SUCCESS;
1412         }
1413         memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
1414         /* in theory p_extra should contain just a seqhdr&EOS.  if just a
1415          * seqhdr, ensure it is extracted by appending an EOS with
1416          * prev_offset = seqhdr length, ie i_extra.  If all were actually
1417          * ok, this won't do anything bad */
1418         if( ( p_init->p_next = dirac_EmitEOS( p_dec, p_dec->fmt_in.i_extra ) ) )
1419         {
1420             /* to ensure that one of these two EOS dataunits gets extracted,
1421              * send a second one */
1422             p_init->p_next->p_next = dirac_EmitEOS( p_dec, 13 );
1423         }
1424
1425         block_t *p_block;
1426         while( ( p_block = Packetize( p_dec, &p_init ) ) )
1427             block_Release( p_block );
1428     }
1429
1430     return VLC_SUCCESS;
1431 }
1432
1433 /*****************************************************************************
1434  * Close:
1435  *****************************************************************************/
1436 static void Close( vlc_object_t *p_this )
1437 {
1438     decoder_t     *p_dec = (decoder_t*)p_this;
1439     decoder_sys_t *p_sys = p_dec->p_sys;
1440
1441     if( !p_sys )
1442         return;
1443
1444     block_BytestreamRelease( &p_sys->bytestream );
1445     if( p_sys->p_outqueue )
1446         block_ChainRelease( p_sys->p_outqueue );
1447     if( p_sys->p_eu )
1448         block_ChainRelease( p_sys->p_eu );
1449     free( p_sys );
1450 }
1451