]> git.sesse.net Git - vlc/blob - modules/packetizer/dirac.c
Qt: MIM: code cosmetics
[vlc] / modules / packetizer / dirac.c
1 /*****************************************************************************
2  * dirac.c
3  *****************************************************************************
4  * Copyright (C) 2008 VLC authors and VideoLAN
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 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.
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 Lesser General Public License for more details.
18  *
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  *****************************************************************************/
23
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.)
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 output, 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
132     uint32_t u_tg_last_picnum; /*< most recent picturenumber output from RoB */
133     bool b_tg_last_picnum; /*< u_tg_last_picnum valid */
134
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 */
144
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 */
148
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 */
161 };
162
163 typedef struct {
164     uint32_t u_next_offset;
165     uint32_t u_prev_offset;
166     int i_parse_code;
167 } parse_info_t;
168
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;
175
176 enum {
177     NOT_SYNCED=0,
178     TRY_SYNC,
179     SYNCED,
180     SYNCED_INCOMPLETEDU,
181 };
182
183 enum {
184     DIRAC_NON_DATED = (1 << BLOCK_FLAG_PRIVATE_SHIFT),
185     DIRAC_DISCARD   = (2 << BLOCK_FLAG_PRIVATE_SHIFT),
186 };
187
188 enum {
189     DIRAC_DU_IN_EU,
190     DIRAC_DU_ENDS_EU,
191 };
192
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)
198  *
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
205  *
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)
209  *
210  * davidf has a patch that reverts this to use a p_priv in block_t.
211  */
212 typedef struct {
213     block_t fake;
214     block_t *p_orig;
215     dirac_block_encap_t *p_dbe;
216 } fake_block_t;
217
218 static dirac_block_encap_t *dirac_RemoveBlockEncap( block_t *p_block )
219 {
220     fake_block_t *p_fake = (fake_block_t *)p_block;
221     dirac_block_encap_t *p_dbe = p_fake->p_dbe;
222
223     p_fake->p_dbe = NULL;
224     return p_dbe;
225 }
226
227 static void dirac_ReleaseBlockAndEncap( block_t *p_block )
228 {
229     fake_block_t *p_fake = (fake_block_t *)p_block;
230
231     free( dirac_RemoveBlockEncap( p_block ) );
232     block_Release( p_fake->p_orig );
233     free( p_fake );
234 }
235
236 static void dirac_AddBlockEncap( block_t **pp_block, dirac_block_encap_t *p_dbe )
237 {
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;
241
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;
251
252     *pp_block = out;
253 }
254
255 static dirac_block_encap_t *dirac_NewBlockEncap( block_t **pp_block )
256 {
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;
260 }
261
262 static dirac_block_encap_t *dirac_GetBlockEncap( block_t *p_block )
263 {
264     return ((fake_block_t *)p_block)->p_dbe;
265 }
266
267 /***
268  * General utility funcions
269  */
270
271 /**
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)
276 {
277     if( !ppp_array )
278         return 0;
279
280     int i_num_blocks;
281     block_ChainProperties( p_block, &i_num_blocks, NULL, NULL );
282
283     *ppp_array = calloc( i_num_blocks, sizeof( block_t* ) );
284     if( !*ppp_array ) return 0;
285
286     for( int i = 0; i < i_num_blocks; i++ )
287     {
288         (*ppp_array)[i] = p_block;
289         p_block = p_block->p_next;
290     }
291
292     return i_num_blocks;
293 }
294
295 /**
296  * Destructively find and recover the earliest timestamp from start of
297  * bytestream, up to i_length.
298  */
299 static void dirac_RecoverTimestamps ( decoder_t *p_dec, size_t i_length )
300 {
301     decoder_sys_t *p_sys = p_dec->p_sys;
302     block_t *p_block = p_sys->bytestream.p_block;
303
304     /* Find the block with first non-flushed data */
305     size_t i_offset = p_sys->bytestream.i_offset;
306     for(; p_block != NULL; p_block = p_block->p_next )
307     {
308         if( i_offset < p_block->i_buffer )
309             break;
310         i_offset -= p_block->i_buffer;
311     }
312
313     i_offset += i_length;
314     for(; p_block != NULL; p_block = p_block->p_next )
315     {
316         if( p_sys->i_sync_pts <= VLC_TS_INVALID && p_sys->i_sync_dts <= VLC_TS_INVALID )
317         {
318             /* oldest timestamp wins */
319             p_sys->i_sync_pts = p_block->i_pts;
320             p_sys->i_sync_dts = p_block->i_dts;
321         }
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;
328     }
329 }
330
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 )
333 {
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-- )
340     {
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 );
345     }
346     free( pp_array );
347 }
348
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 )
351 {
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-- )
358     {
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 );
371     }
372     free( pp_array );
373 }
374
375 /***
376  * Dirac spec defined relations
377  */
378
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; }
383
384 static inline bool dirac_PictureNbeforeM( uint32_t u_n, uint32_t u_m )
385 {
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);
389 }
390
391 /***
392  * Reorder buffer model
393  */
394
395 static void dirac_ReorderInit( struct dirac_reorder_buffer *p_rb )
396 {
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;
401
402     for( int i = 0; i < 31; i++ )
403         p_rb->p_entries[i].p_next = &p_rb->p_entries[i+1];
404 }
405
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 )
408 {
409     decoder_sys_t *p_sys = p_dec->p_sys;
410
411     if( !p_sys->reorder_buf.u_size_max )
412         /* reorder buffer disabled */
413         return p_block_in;
414
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
425      */
426
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 )
430     {
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 ) )
434         {
435             /* (2a) current picture is first in order */
436             return p_block_in;
437         }
438
439         /* (2b) extract the youngest picture in the buffer */
440         p_block = p_sys->reorder_buf.p_head->p_eu;
441
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;
446
447         p_sys->reorder_buf.u_size--;
448     }
449
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++;
454
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;
460
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;
465
466     return p_block;
467 }
468
469 /***
470  * bytestream parsing and unmarshalling functions
471  */
472
473 static bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs,
474                                    size_t u_offset )
475 {
476     uint8_t p_d[13];
477     if( VLC_SUCCESS != block_PeekOffsetBytes( p_bs, u_offset, p_d, 13 ) )
478         return false;
479
480     if( p_d[0] != 'B' || p_d[1] != 'B' || p_d[2] != 'C' || p_d[3] != 'D' )
481         return false;
482
483     p_pi->i_parse_code = p_d[4];
484     p_pi->u_next_offset = p_d[5] << 24 | p_d[6] << 16 | p_d[7] << 8 | p_d[8];
485     p_pi->u_prev_offset = p_d[9] << 24 | p_d[10] << 16 | p_d[11] << 8 | p_d[12];
486     return true;
487 }
488
489 static uint32_t dirac_uint( bs_t *p_bs )
490 {
491     uint32_t u_count = 0, u_value = 0;
492     while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
493     {
494         u_count++;
495         u_value <<= 1;
496         u_value |= bs_read( p_bs, 1 );
497     }
498     return (1 << u_count) - 1 + u_value;
499 }
500
501 static int dirac_bool( bs_t *p_bs )
502 {
503     return bs_read( p_bs, 1 );
504 }
505
506 /* read in useful bits from sequence header */
507 static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
508 {
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 */
516
517     uint32_t u_video_format = dirac_uint( &bs ); /* index */
518     if( u_video_format > 20 )
519     {
520         /* don't know how to parse this header */
521         return false;
522     }
523
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},
531     };
532
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 ) )
536     {
537         p_sh->u_width = dirac_uint( &bs ); /* frame_width */
538         p_sh->u_height = dirac_uint( &bs ); /* frame_height */
539     }
540
541     if( dirac_bool( &bs ) )
542     {
543         dirac_uint( &bs ); /* chroma_format */
544     }
545
546     if( dirac_bool( &bs ) )
547     {
548         dirac_uint( &bs ); /* scan_format */
549     }
550
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},
557     };
558
559     const unsigned dirac_frate_tbl_size =
560         sizeof( dirac_frate_tbl ) / sizeof( *dirac_frate_tbl );
561
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,
564     };
565
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 ) )
569     {
570         uint32_t frame_rate_index = dirac_uint( &bs );
571         if( frame_rate_index >= dirac_frate_tbl_size )
572         {
573             /* invalid header */
574             return false;
575         }
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 )
579         {
580             p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */
581             p_sh->u_fps_den = dirac_uint( &bs ); /* frame_rate_denominator */
582         }
583     }
584
585     /* must have a valid framerate */
586     if( !p_sh->u_fps_num || !p_sh->u_fps_den )
587         return false;
588
589     if( dirac_bool( &bs ) )
590     {
591         uint32_t par_index = dirac_uint( &bs );
592         if( !par_index )
593         {
594             dirac_uint( &bs ); /* par_num */
595             dirac_uint( &bs ); /* par_den */
596         }
597     }
598
599     if( dirac_bool( &bs ) )
600     {
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 */
605     }
606
607     if( dirac_bool( &bs ) )
608     {
609         uint32_t signal_range_index = dirac_uint( &bs );
610         if( !signal_range_index )
611         {
612             dirac_uint( &bs ); /* luma_offset */
613             dirac_uint( &bs ); /* luma_excursion */
614             dirac_uint( &bs ); /* chroma_offset */
615             dirac_uint( &bs ); /* chroma_excursion */
616         }
617     }
618
619     if( dirac_bool( &bs ) )
620     {
621         uint32_t colour_spec_index = dirac_uint( &bs );
622         if( !colour_spec_index )
623         {
624             if( dirac_bool( &bs ) )
625             {
626                 dirac_uint( &bs ); /* colour_primaries_index */
627             }
628             if( dirac_bool( &bs ) )
629             {
630                 dirac_uint( &bs ); /* colour_matrix_index */
631             }
632             if( dirac_bool( &bs ) )
633             {
634                 dirac_uint( &bs ); /* transfer_function_index */
635             }
636         }
637     }
638
639     p_sh->u_picture_coding_mode = dirac_uint( &bs );
640
641     return true;
642 }
643
644 /***
645  * Data Unit marshalling functions
646  */
647
648 static block_t *dirac_EmitEOS( decoder_t *p_dec, uint32_t i_prev_parse_offset )
649 {
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 );
655
656     SetDWBE( p_block->p_buffer + 9, i_prev_parse_offset );
657
658     p_block->i_flags = DIRAC_NON_DATED;
659
660     (void) p_dec;
661     return p_block;
662 }
663
664 /***
665  * Bytestream synchronizer
666  * maps [Bytes] -> DataUnit
667  */
668 static block_t *dirac_DoSync( decoder_t *p_dec )
669 {
670     decoder_sys_t *p_sys = p_dec->p_sys;
671     parse_info_t pu;
672
673     static const uint8_t p_parsecode[4] = {'B','B','C','D'};
674     do {
675         switch( p_sys->i_state )
676         {
677         case NOT_SYNCED:
678         {
679             if( VLC_SUCCESS !=
680                 block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_parsecode, 4 ) )
681             {
682                 /* p_sys->i_offset will have been set to:
683                  *   end of bytestream - amount of prefix found
684                  * can resume search from this point when more data arrives */
685                 return NULL;
686             }
687             /* candidate parse_code_prefix has been found at p_sys->i_offset */
688             if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_offset + 12, NULL, 0 ) )
689             {
690                 /* insufficient data has been accumulated to fully extract
691                  * a parse_info header. exit for now in the hope of more
692                  * data later to retry at exactly the same point */
693                 return NULL;
694             }
695             p_sys->i_state = TRY_SYNC;
696             break; /* candidate found, try to sync */
697         }
698         case SYNCED: /* -> TRY_SYNC | NOT_SYNCED */
699             /* sanity: can only reach this after having extracted a DU,
700              * which causes data to be consumed and local i_offset to be reset */
701             assert( p_sys->i_offset == 0 );
702             if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, 12, NULL, 0 ) )
703             {
704                 /* insufficient data has been accumulated to fully extract
705                  * a parse_info header, retry later */
706                 return NULL;
707             }
708             if( !dirac_UnpackParseInfo( &pu, &p_sys->bytestream, 0 )
709              || !pu.u_next_offset || (p_sys->u_last_npo != pu.u_prev_offset) )
710             {
711                 /* !a: not a valid parse info.
712                  * !pu.u_next_offset: don't know the length of the data unit
713                  *                    search for the next one that points back
714                  *                    to this one to determine length.
715                  * (p_sys->u_last_npo != pu.u_prev_offset): some desync
716                  */
717                 p_sys->i_state = NOT_SYNCED;
718                 break;
719             }
720             if( pu.u_next_offset > 1024*1024 )
721             {
722                 /* sanity check for erronious hugs next_parse_offsets
723                  * (eg, 2^32-1) that would cause a very long wait
724                  * and large space consumption: fall back to try sync */
725                 p_sys->i_state = TRY_SYNC;
726                 break;
727             }
728             /* check that the start of the next data unit is avaliable */
729             if( VLC_SUCCESS !=
730                 block_PeekOffsetBytes( &p_sys->bytestream, pu.u_next_offset + 12, NULL, 0 ) )
731             {
732                 return NULL; /* retry later */
733             }
734             /* attempt to synchronise backwards from pu.u_next_offset */
735             p_sys->i_offset = pu.u_next_offset;
736             /* fall through */
737         case TRY_SYNC: /* -> SYNCED | NOT_SYNCED */
738         {
739             if( !p_sys->i_offset )
740                 goto sync_fail; /* if a is at start of bytestream, b can't be in buffer */
741
742             parse_info_t pu_a;
743             bool a = dirac_UnpackParseInfo( &pu_a, &p_sys->bytestream, p_sys->i_offset );
744             if( !a || (pu_a.u_prev_offset > p_sys->i_offset) )
745                 goto sync_fail; /* b lies beyond start of bytestream: can't sync */
746
747             if( !pu_a.u_prev_offset )
748             {
749                 if( p_sys->i_state == TRY_SYNC )
750                 {
751                     goto sync_fail; /* can't find different pu_b from pu_a */
752                 }
753                 /* state == SYNCED: already know where pu_b is.
754                  * pu_a has probably been inserted by something that doesn't
755                  * know what the last next_parse_offset was */
756                 pu_a.u_prev_offset = pu.u_next_offset;
757             }
758
759             parse_info_t *pu_b = &pu;
760             bool b = dirac_UnpackParseInfo( pu_b, &p_sys->bytestream, p_sys->i_offset - pu_a.u_prev_offset );
761             if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) )
762             {
763                 /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
764                  * just rely on finding a valid pu_b from pu_a. */
765                 goto sync_fail;
766             }
767             p_sys->u_last_npo = pu_b->u_next_offset;
768             if( !pu_b->u_next_offset ) pu_b->u_next_offset = pu_a.u_prev_offset;
769             /* offset was pointing at pu_a, rewind to point at pu_b */
770             p_sys->i_offset -= pu_a.u_prev_offset;
771             p_sys->i_state = SYNCED;
772             break;
773         }
774 sync_fail:
775             if( p_sys->i_state == SYNCED ) p_sys->i_offset = 0;
776             p_sys->i_offset++;
777             p_sys->i_state = NOT_SYNCED;
778             break; /* find somewhere else to try again */
779         default:;
780         }
781     } while( SYNCED != p_sys->i_state );
782
783     /*
784      * synced, attempt to extract a data unit
785      */
786
787     /* recover any timestamps from the data that is about to be flushed */
788     dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
789
790     /* flush everything up to the start of the DU */
791     block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
792     block_BytestreamFlush( &p_sys->bytestream );
793     p_sys->i_offset = 0;
794
795     /* setup the data unit buffer */
796     block_t *p_block = block_Alloc( pu.u_next_offset );
797     if( !p_block )
798         return NULL;
799
800     p_block->i_pts = p_sys->i_sync_pts;
801     p_block->i_dts = p_sys->i_sync_dts;
802     p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
803
804     /* recover any new timestamps from the data that is about to be consumed */
805     dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
806
807     block_GetBytes( &p_sys->bytestream, p_block->p_buffer, p_block->i_buffer );
808
809     /* save parse offset in private area for later use */
810     dirac_block_encap_t *p_dbe = dirac_NewBlockEncap( &p_block );
811     if( p_dbe ) p_dbe->u_last_next_offset = pu.u_next_offset;
812
813     return p_block;
814 }
815
816 /***
817  * Packet (Data Unit) inspection, learns parameters from sequence
818  * headers, sets up flags, drops unwanted data units, sets
819  * encapsulation unit termination policy
820  */
821 static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu )
822 {
823     decoder_sys_t *p_sys = p_dec->p_sys;
824     block_t *p_block = *pp_block;
825     uint8_t u_parse_code = p_block->p_buffer[4];
826
827     if( dirac_isEOS( u_parse_code ) )
828     {
829         if( p_sys->b_seen_eos )
830         {
831             /* remove duplicate EOS packets */
832             block_Release( p_block );
833             *pp_block = NULL;
834             return DIRAC_DU_IN_EU;
835         }
836         /* p_block is an EOS packet */
837         p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
838         /* for the moment, let this end an encapsulation unit */
839         /* seeing an eos packet requires a flush of the packetizer
840          * this is detected by the caller of this function */
841         p_sys->b_seen_seq_hdr = false;
842         p_sys->b_seen_eos = true;
843         return DIRAC_DU_ENDS_EU;
844 #if 0
845         /* let anything down streem know too */
846         /*
847         Actually, this is a bad idea:
848          - It sets the discontinuity for every dirac EOS packet
849            which doesnt imply a time discontinuity.
850          - When the synchronizer detects a real discontinuity, it
851            should copy the flags through.
852         p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
853         */
854 #endif
855     }
856     p_sys->b_seen_eos = false;
857
858     if( dirac_isPicture( u_parse_code ) )
859     {
860         /* timestamps apply to pictures only */
861         p_eu->i_dts = p_sys->i_eu_dts;
862         p_eu->i_pts = p_sys->i_eu_pts;
863         p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
864
865         if( !p_sys->b_seen_seq_hdr )
866         {
867             /* can't timestamp in this case, discard later
868              * so that the timestamps aren't lost */
869             p_eu->i_flags |= DIRAC_DISCARD;
870         }
871         /* p_block is a picture -- it ends the 'encapsulation unit' */
872         if( dirac_numRefs( u_parse_code ) )
873         {
874             /* if this picture is not an I frame, ensure that the
875              * random access point flags are not set */
876             p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
877         }
878         dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
879         if( p_dbe && p_block->i_buffer > 13+4 )
880         {
881             /* record the picture number to save the time gen functions
882              * from having to inspect the data for it */
883             p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
884         }
885         return DIRAC_DU_ENDS_EU;
886     }
887
888     if( dirac_isSeqHdr( u_parse_code ) )
889     {
890         if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) )
891         {
892             /* couldn't parse the sequence header, just ignore it */
893             return DIRAC_DU_IN_EU;
894         }
895         p_sys->b_seen_seq_hdr = true;
896
897        /* a sequence header followed by an I frame is a random
898         * access point; assume that this is the case */
899         p_eu->i_flags |= BLOCK_FLAG_TYPE_I;
900
901         es_format_t *p_es = &p_dec->fmt_out;
902
903         p_es->video.i_width  = p_sys->seq_hdr.u_width;
904         p_es->video.i_height = p_sys->seq_hdr.u_height;
905
906         vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
907                    , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );
908
909         /* when field coding, dts needs to be incremented in terms of field periods */
910         unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
911         if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING )
912         {
913             u_pics_per_sec *= 2;
914         }
915         date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den );
916
917         /* TODO: set p_sys->reorder_buf.u_size_max */
918         p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max
919                             * 1000000
920                             * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1;
921
922         /* stash a copy of the seqhdr
923          *  - required for ogg muxing
924          *  - useful for error checking
925          *  - it isn't allowed to change until an eos */
926         free( p_es->p_extra );
927         p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
928         if( !p_es->p_extra )
929         {
930             p_es->i_extra = 0;
931             return DIRAC_DU_IN_EU;
932         }
933         p_es->i_extra = p_block->i_buffer;
934         memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer );
935         /* append EOS as per Ogg guidelines */
936         p_block = dirac_EmitEOS( p_dec, p_block->i_buffer );
937         if( p_block )
938         {
939             memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 );
940             p_es->i_extra += 13;
941         }
942
943         return DIRAC_DU_IN_EU;
944     }
945
946     /* doesn't end an encapsulation unit */
947     return DIRAC_DU_IN_EU;
948 }
949
950 /***
951  * Encapsulation (packetization) suitable for all muxing standards
952  * maps [DataUnit] -> EncapsulationUnit
953  */
954 static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block )
955 {
956     decoder_sys_t *p_sys = p_dec->p_sys;
957
958     assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer ));
959
960     if( p_sys->i_eu_pts <= VLC_TS_INVALID && p_sys->i_eu_dts <= VLC_TS_INVALID )
961     {
962         /* earliest block with pts/dts gets to set the pts/dts for the dated
963          * encapsulation unit as a whole */
964         /* NB, the 'earliest block' criteria is aribtary */
965         if( p_block->i_pts > VLC_TS_INVALID || p_block->i_dts > VLC_TS_INVALID )
966         {
967             p_sys->i_eu_pts = p_block->i_pts;
968             p_sys->i_eu_dts = p_block->i_dts;
969         }
970     }
971
972     /* inpectdataunit also updates flags for the EU.
973      *  - if this is the first block in the EU, then it hasn't been added
974      *    to the chain yet (so, p_block will become the front of the chain
975      *  - otherwise, use the flags of the chain (first block) */
976     block_t *p_eu = p_sys->p_eu ? p_sys->p_eu : p_block;
977     int i_block = dirac_InspectDataUnit( p_dec, &p_block, p_eu);
978
979     if( !p_block )
980     {
981         /* block has been discarded during inspection */
982         /* becareful, don't discard anything that is dated,
983          * as this needs to go into the timegen loop.  set
984          * the DIRAC_DISCARD block flag, and it'll be dropped
985          * at output time */
986         return NULL;
987     }
988
989     block_ChainLastAppend( &p_sys->pp_eu_last, p_block );
990
991     dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
992 #ifdef SANITIZE_PREV_PARSE_OFFSET
993     /* fixup prev_parse_offset to point to the last data unit
994      * to arrive */
995     if( p_dbe )
996     {
997         SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo );
998         p_sys->u_eu_last_npo = p_dbe->u_last_next_offset;
999     }
1000 #endif
1001
1002     if( i_block != DIRAC_DU_ENDS_EU )
1003     {
1004         /* encapsulation unit not ended */
1005         return NULL;
1006     }
1007
1008     /* gather up encapsulation unit, reassociating the final
1009      * private state with the gathered block */
1010     block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next );
1011     p_dbe = dirac_RemoveBlockEncap( p_eu_last );
1012
1013     uint8_t u_parse_code = p_block->p_buffer[4];
1014
1015     /* gather up the encapsulation unit */
1016     p_block = block_ChainGather( p_sys->p_eu );
1017     assert( p_block ); /* block_ChainGather doesn't define when it frees chain */
1018
1019     p_block->i_flags |= DIRAC_NON_DATED;
1020     if( p_dbe )
1021     {
1022         dirac_AddBlockEncap( &p_block, p_dbe );
1023         if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED;
1024     }
1025     p_sys->p_eu = NULL;
1026     p_sys->pp_eu_last = &p_sys->p_eu;
1027     return p_block;
1028 }
1029
1030 /**
1031  * dirac_TimeGenPush:
1032  * @p_dec: vlc object
1033  * @p_block_in: whole encapsulation unit to generate timestamps for
1034  *
1035  * Returns:
1036  *  0: everything ok
1037  *  1: EOS occurred, please flush and reset
1038  *  2: picture number discontinuity, please flush and reset
1039  */
1040 static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
1041 {
1042     decoder_sys_t *p_sys = p_dec->p_sys;
1043     dirac_block_encap_t *p_dbe;
1044
1045     if( p_block_in->i_flags & BLOCK_FLAG_END_OF_SEQUENCE )
1046     {
1047         /* NB, this test occurs after the timegen push, so as to
1048          * push the block into the output queue */
1049         return 1;
1050     }
1051
1052     if( p_block_in->i_flags & DIRAC_NON_DATED )
1053     {
1054         /* no picture found, which means p_block_in is a non-dated EU,
1055          * do not try and put a date on it */
1056         return 0;
1057     }
1058
1059     p_dbe = dirac_GetBlockEncap( p_block_in );
1060     uint32_t u_picnum = p_dbe ? p_dbe->u_picture_number : 0;
1061     /*
1062      * Simple DTS regeneration:
1063      *  - DTS values linearly increase in stream order.
1064      *  - Every time a DTS occurs at the input, sync to it
1065      *    - If this is the first DTS seen, backdate all the previous ones that are undated
1066      *  - If a DTS is missing, guess that it increases by one picture period
1067      *  - If never seen DTS, don't do anything
1068      */
1069     /*
1070      * Simple PTS regeneration
1071      *  - PTS values do not linearly increase in stream order.
1072      *  - Every time a PTS occurs at the input, sync to it and record picture number
1073      *  - If a PTS is missing, guess that it differs by the product of picture
1074      *    period and difference between picture number of sync point and current picture
1075      *  - If this is the first PTS seen, backdate all previous ones that are undated
1076      *  - If never seen PTS, don't do anything
1077      */
1078     /*
1079      * Stage 1, sync to input timestamps, backdate timestamps for old
1080      * EUs that are in the outqueue with missing dates
1081      */
1082     if( p_block_in->i_dts > VLC_TS_INVALID )
1083     do {
1084         /* if timestamps exist, sync to them */
1085         if( p_sys->b_dts )
1086             break;
1087         /* first dts seen, backdate any packets in outqueue */
1088         p_sys->b_dts = true;
1089         date_t dts = p_sys->dts;
1090         dirac_BackdateDTS( p_sys->p_outqueue, p_block_in, &dts );
1091     } while( 0 );
1092
1093     if( p_block_in->i_pts > VLC_TS_INVALID )
1094     do {
1095         /* if timestamps exist, sync to them */
1096         p_sys->u_pts_picnum = u_picnum;
1097         p_sys->i_pts = p_block_in->i_pts;
1098         if( p_sys->b_pts )
1099             break;
1100         /* first pts seen, backdate any packets in outqueue */
1101         p_sys->b_pts = true;
1102         date_t pts = p_sys->dts;
1103         date_Set( &pts, p_sys->i_pts );
1104         dirac_BackdatePTS( p_sys->p_outqueue, p_block_in, &pts, p_sys->u_pts_picnum );
1105     } while( 0 );
1106
1107     /*
1108      * Stage 2, don't attempt to forwards interpolate timestamps for
1109      * blocks if the picture rates aren't known
1110      */
1111     if( !p_sys->b_seen_seq_hdr )
1112     {
1113         return 0;
1114     }
1115
1116     /*
1117      * Stage 3, for block_in, interpolate any missing timestamps
1118      */
1119     if( p_sys->b_dts && p_block_in->i_dts <= VLC_TS_INVALID )
1120     {
1121         /* dts has previously been seen, but not this time, interpolate */
1122         p_block_in->i_dts = date_Increment( &p_sys->dts, 1 );
1123     }
1124
1125     if( p_sys->b_pts && p_block_in->i_pts <= VLC_TS_INVALID )
1126     {
1127         /* pts has previously been seen, but not this time, interpolate */
1128         date_t pts = p_sys->dts;
1129         date_Set( &pts, p_sys->i_pts );
1130         int32_t i_dist = u_picnum - p_sys->u_pts_picnum;
1131         if( i_dist >= 0 )
1132             p_block_in->i_pts = date_Increment( &pts, i_dist );
1133         else
1134             p_block_in->i_pts = date_Decrement( &pts, -i_dist );
1135     }
1136
1137     /* If pts and dts have been seen, there is no need to simulate operation
1138      * of the decoder reorder buffer */
1139     /* If neither have been seen, there is little point in simulating */
1140     if( p_sys->b_dts == p_sys->b_pts )
1141         return 0;
1142
1143     /* model the reorder buffer */
1144     block_t *p_block = dirac_Reorder( p_dec, p_block_in, u_picnum );
1145     if( !p_block )
1146         return 0;
1147
1148     /* A future ehancement is to stop modeling the reorder buffer as soon as
1149      * the first packet is output -- interpolate the past and freewheel for
1150      * the future */
1151
1152     p_dbe = dirac_GetBlockEncap( p_block );
1153     u_picnum = p_dbe ? p_dbe->u_picture_number : 0;
1154     if( p_sys->b_tg_last_picnum )
1155     {
1156         if( dirac_PictureNbeforeM( u_picnum, p_sys->u_tg_last_picnum ) )
1157         {
1158             msg_Warn( p_dec, "stream jumped? %d < %d: resetting"
1159                     , u_picnum, p_sys->u_tg_last_picnum );
1160             /* pictures only emerge from the reorder buffer in sequence
1161              * if a stream suddenly jumped backwards without a signaling
1162              * a discontinuity, some pictures will get stuck in the RoB.
1163              * flush the RoB. */
1164             /* this could be a bit less indiscriminate */
1165             p_dbe = dirac_GetBlockEncap( p_sys->p_outqueue );
1166             uint32_t u_prev_parse_offset = p_dbe ? p_dbe->u_last_next_offset : 0;
1167             block_ChainRelease( p_sys->p_outqueue );
1168             p_sys->p_outqueue = dirac_EmitEOS( p_dec, u_prev_parse_offset );
1169             if( p_sys->p_outqueue )
1170                 p_sys->p_outqueue->i_flags = BLOCK_FLAG_DISCONTINUITY | DIRAC_NON_DATED;
1171             /* return 2, so as not to reset the b_dts flags -- needed if
1172              * using the rawdirac demuxer with broken stream */
1173             return 2;
1174         }
1175     }
1176     p_sys->b_tg_last_picnum = true;
1177     p_sys->u_tg_last_picnum = u_picnum;
1178
1179     return 0;
1180 }
1181
1182
1183 static void dirac_ReorderDequeueAndReleaseBlock( decoder_t *p_dec, block_t *p_block )
1184 {
1185     decoder_sys_t *p_sys = p_dec->p_sys;
1186     /* Check if that block is present in reorder queue and release it
1187        if needed */
1188     struct dirac_reorder_entry **pp_at = &p_sys->reorder_buf.p_head;
1189     for( ; *pp_at; pp_at = &(*pp_at)->p_next )
1190     {
1191         /* backup address in case we remove member */
1192         struct dirac_reorder_entry *p_entry = *pp_at;
1193         if ( p_entry->p_eu == p_block )
1194         {
1195             /* unlink member */
1196             *pp_at = (*pp_at)->p_next;
1197
1198             /* Add to empty reorder entry list*/
1199             p_entry->p_next = p_sys->reorder_buf.p_empty;
1200             p_sys->reorder_buf.p_empty = p_entry;
1201
1202             p_sys->reorder_buf.u_size--;
1203             break;
1204         }
1205     }
1206
1207     block_Release( p_block );
1208 }
1209
1210 /*****************************************************************************
1211  * Packetize: form dated encapsulation units from anything
1212  *****************************************************************************/
1213 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
1214 {
1215     decoder_sys_t *p_sys = p_dec->p_sys;
1216     block_t *p_block = NULL;
1217     int i_flushing = 0;
1218
1219     if( pp_block && *pp_block )
1220     {
1221         p_block = *pp_block;
1222         *pp_block = NULL;
1223
1224         if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
1225         {
1226             /* pre-emptively insert an EOS at a discontinuity, protects
1227              * any decoders from any sudden changes */
1228             block_Release( p_block );
1229             p_block = dirac_EmitEOS( p_dec, 0 );
1230             if( p_block )
1231             {
1232                 p_block->p_next = dirac_EmitEOS( p_dec, 13 );
1233                 /* need two EOS to ensure it gets detected by synchro
1234                  * duplicates get discarded in forming encapsulation unit */
1235             }
1236         }
1237         else if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
1238         {
1239             /* silently discard corruption sentinels,
1240              * synchronizer will then discard affected data units.
1241              * do not produce an EOS data unit as this is very
1242              * disruptive to the stream (and may make a larger error). */
1243             block_Release( p_block );
1244             p_block = NULL;
1245         }
1246         if( p_block )
1247             block_BytestreamPush( &p_sys->bytestream, p_block );
1248     }
1249
1250     /* form as many encapsulation units as possible, give up
1251      * when the synchronizer runs out of input data */
1252     while( ( p_block = dirac_DoSync( p_dec ) ) )
1253     {
1254         p_block = dirac_BuildEncapsulationUnit( p_dec, p_block );
1255         if( !p_block )
1256             continue;
1257         /* add to tail of output queue (ie, not reordered) */
1258         block_ChainLastAppend( &p_sys->pp_outqueue_last, p_block );
1259         /* insert encapsulation unit into timestamp generator
1260          * which then calculates some timestamps if required */
1261         i_flushing = dirac_TimeGenPush( p_dec, p_block );
1262         if( i_flushing )
1263             break;
1264     }
1265
1266     block_t *p_output = NULL;
1267     block_t **pp_output = &p_output;
1268
1269     /* extract all the dated packets from the head of the output queue */
1270     /* explicitly nondated packets repeat the previous timestamps to
1271      * stop vlc discarding them */
1272     while( (p_block = p_sys->p_outqueue) )
1273     {
1274         if( p_block->i_flags & DIRAC_DISCARD )
1275         {
1276             p_sys->p_outqueue = p_block->p_next;
1277             p_block->p_next = NULL;
1278             block_Release( p_block );
1279             continue;
1280         }
1281
1282         if( i_flushing || p_block->i_flags & DIRAC_NON_DATED )
1283         {
1284             p_block->i_dts = p_sys->i_dts_last_out;
1285             p_block->i_pts = p_sys->i_pts_last_out;
1286         }
1287         else if( p_block->i_pts <= VLC_TS_INVALID ) break;
1288         else if( p_block->i_dts <= VLC_TS_INVALID ) break;
1289
1290         p_sys->i_dts_last_out = p_block->i_dts;
1291         p_sys->i_pts_last_out = p_block->i_pts;
1292
1293         p_sys->p_outqueue = p_block->p_next;
1294         p_block->p_next = NULL;
1295         /* clear any flags we set */
1296         p_block->i_flags &= ~BLOCK_FLAG_PRIVATE_MASK;
1297         block_ChainLastAppend( &pp_output, p_block );
1298
1299         mtime_t i_delay = p_block->i_pts - p_block->i_dts;
1300         if( i_delay < 0 )
1301             msg_Err( p_dec, "pts - dts is negative(%"PRId64"): incorrect RoB size", i_delay );
1302     }
1303
1304     if( i_flushing )
1305     {
1306         p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;
1307
1308         /* reset timegen state (except synchronizer) */
1309         p_sys->b_seen_seq_hdr = false;
1310         if( i_flushing < 2 )
1311         {
1312             /* this state isn't safe to loose if there was
1313              * an unsignalled discontinuity */
1314             p_sys->b_pts = p_sys->b_dts = false;
1315         }
1316         p_sys->b_tg_last_picnum = false;
1317         dirac_ReorderInit( &p_sys->reorder_buf );
1318
1319         assert( p_sys->p_outqueue == NULL );
1320     }
1321
1322     /* perform sanity check:
1323      *  if there were a block at the front of outqueue that never
1324      *  satisfied the extraction criteria, but all blocks after did,
1325      *  the output queue would grow bounded by the stream length.
1326      * If there are 10 data units in the output queue, assume this
1327      * has happened and purge all blocks that fail extraction criteria */
1328     int i_count;
1329     block_ChainProperties( p_sys->p_outqueue, &i_count, NULL, NULL );
1330     if( i_count > 9 )
1331     {
1332         p_block = p_sys->p_outqueue;
1333         while( p_block )
1334         {
1335             block_t *p_block_next = p_block->p_next;
1336             if( p_block->i_pts > VLC_TS_INVALID && p_block->i_dts > VLC_TS_INVALID )
1337                 break;
1338             dirac_ReorderDequeueAndReleaseBlock( p_dec, p_block );
1339             p_sys->p_outqueue = p_block = p_block_next;
1340         }
1341     }
1342
1343     if( !p_sys->p_outqueue )
1344     {
1345         p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1346     }
1347     return p_output;
1348 }
1349
1350 /*****************************************************************************
1351  * Open: probe the packetizer and return score
1352  *****************************************************************************/
1353 static int Open( vlc_object_t *p_this )
1354 {
1355     decoder_t     *p_dec = (decoder_t*)p_this;
1356     decoder_sys_t *p_sys;
1357
1358     if( p_dec->fmt_in.i_codec !=  VLC_CODEC_DIRAC )
1359         return VLC_EGENERIC;
1360
1361     p_dec->pf_packetize = Packetize;
1362
1363     /* Create the output format */
1364     es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
1365     p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
1366
1367     if( !p_sys )
1368         return VLC_ENOMEM;
1369
1370     p_sys->i_eu_pts = p_sys->i_eu_dts = VLC_TS_INVALID;
1371     p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;
1372     p_sys->i_dts_last_out = p_sys->i_pts_last_out = VLC_TS_INVALID;
1373
1374     p_sys->i_state = NOT_SYNCED;
1375     block_BytestreamInit( &p_sys->bytestream );
1376
1377     p_sys->pp_outqueue_last = &p_sys->p_outqueue;
1378     p_sys->pp_eu_last = &p_sys->p_eu;
1379
1380     date_Init( &p_sys->dts, 1, 1 );
1381     dirac_ReorderInit( &p_sys->reorder_buf );
1382
1383     if( p_dec->fmt_in.i_extra > 0 )
1384     {
1385         /* handle hacky systems like ogg that dump some headers
1386          * in p_extra. and packetizers that expect it to be filled
1387          * in before real startup */
1388         block_t *p_init = block_Alloc( p_dec->fmt_in.i_extra );
1389         if( !p_init )
1390         {
1391             /* memory might be avaliable soon.  it isn't the end of
1392              * the world that fmt_in.i_extra isn't handled */
1393             return VLC_SUCCESS;
1394         }
1395         memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
1396         /* in theory p_extra should contain just a seqhdr&EOS.  if just a
1397          * seqhdr, ensure it is extracted by appending an EOS with
1398          * prev_offset = seqhdr length, ie i_extra.  If all were actually
1399          * ok, this won't do anything bad */
1400         if( ( p_init->p_next = dirac_EmitEOS( p_dec, p_dec->fmt_in.i_extra ) ) )
1401         {
1402             /* to ensure that one of these two EOS dataunits gets extracted,
1403              * send a second one */
1404             p_init->p_next->p_next = dirac_EmitEOS( p_dec, 13 );
1405         }
1406
1407         block_t *p_block;
1408         while( ( p_block = Packetize( p_dec, &p_init ) ) )
1409             block_Release( p_block );
1410     }
1411
1412     return VLC_SUCCESS;
1413 }
1414
1415 /*****************************************************************************
1416  * Close:
1417  *****************************************************************************/
1418 static void Close( vlc_object_t *p_this )
1419 {
1420     decoder_t     *p_dec = (decoder_t*)p_this;
1421     decoder_sys_t *p_sys = p_dec->p_sys;
1422
1423     block_BytestreamRelease( &p_sys->bytestream );
1424     if( p_sys->p_outqueue )
1425         block_ChainRelease( p_sys->p_outqueue );
1426     if( p_sys->p_eu )
1427         block_ChainRelease( p_sys->p_eu );
1428     free( p_sys );
1429 }
1430