]> git.sesse.net Git - vlc/blobdiff - modules/packetizer/dirac.c
sftp: implement directory listing
[vlc] / modules / packetizer / dirac.c
index 002f7be5b4a2c26afa1af11bc9b7deb39b7c20e4..71b0b11a129601debc73663c68fe9bec88f6993f 100644 (file)
@@ -1,29 +1,29 @@
 /*****************************************************************************
  * dirac.c
  *****************************************************************************
- * Copyright (C) 2008 the VideoLAN team
+ * Copyright (C) 2008 VLC authors and VideoLAN
  * $Id$
  *
  * Authors: David Flynn <davidf@rd.bbc.co.uk>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation; either version 2 of the License
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /* Dirac packetizer, formed of three parts:
  *  1) Bitstream synchroniser (dirac_DoSync)
- *      - Given an arbitary sequence of bytes, extract whole Dirac Data Units
+ *      - Given an arbitrary sequence of bytes, extract whole Dirac Data Units
  *      - Maps timestamps in supplied block_t's to the extracted Data Unit
  *        A time stamp applies to the next Data Unit to commence at, or after
  *        the first byte of the block_t with the timestamp.
@@ -51,7 +51,7 @@
  *        distinguish from the fake dts case.)
  *
  *  DIRAC_NON_DATED is used to show a block should not have a time stamp
- *  associated (ie, don't interpolate a counter).  At the ouput, these
+ *  associated (ie, don't interpolate a counter).  At the output, these
  *  blocks get dated with the last used timestamp (or are merged with
  *  another encapsulation unit).
  */
@@ -70,8 +70,8 @@
 #include <vlc_codec.h>
 #include <vlc_block.h>
 
-#include "vlc_bits.h"
-#include "vlc_block_helper.h"
+#include <vlc_bits.h>
+#include <vlc_block_helper.h>
 
 #define SANITIZE_PREV_PARSE_OFFSET 1
 
@@ -128,9 +128,6 @@ struct decoder_sys_t
      * completed encapsulation units from the front */
     block_t *p_outqueue;
     block_t **pp_outqueue_last;
-    /* p_out_dts points to an element in p_outqueue.  It is used for VLC's
-     * fake pts hidden in DTS hack, as used by AVI */
-    block_t *p_out_dts;
 
     uint32_t u_tg_last_picnum; /*< most recent picturenumber output from RoB */
     bool b_tg_last_picnum; /*< u_tg_last_picnum valid */
@@ -170,7 +167,6 @@ typedef struct {
 } parse_info_t;
 
 typedef struct {
-    block_free_t pf_blk_release;
     /*> next_parse_offset of the final data unit in associated block_t */
     uint32_t u_last_next_offset;
     /*> picture number is invalid if block has flags DIRAC_NON_DATED */
@@ -185,9 +181,8 @@ enum {
 };
 
 enum {
-    DIRAC_EOS = 0x02000000,
-    DIRAC_NON_DATED = 0x04000000,
-    DIRAC_DISCARD = 0x08000000,
+    DIRAC_NON_DATED = (1 << BLOCK_FLAG_PRIVATE_SHIFT),
+    DIRAC_DISCARD   = (2 << BLOCK_FLAG_PRIVATE_SHIFT),
 };
 
 enum {
@@ -217,76 +212,62 @@ enum {
 typedef struct {
     block_t fake;
     block_t *p_orig;
-    void *p_priv;
+    dirac_block_encap_t *p_dbe;
 } fake_block_t;
 
 static dirac_block_encap_t *dirac_RemoveBlockEncap( block_t *p_block )
 {
     fake_block_t *p_fake = (fake_block_t *)p_block;
-    dirac_block_encap_t *dbe = p_fake->p_priv;
-    if( !dbe ) return NULL;
-    p_fake->p_priv = NULL;
-    dbe->pf_blk_release = NULL;
-    return dbe;
+    dirac_block_encap_t *p_dbe = p_fake->p_dbe;
+
+    p_fake->p_dbe = NULL;
+    return p_dbe;
 }
 
 static void dirac_ReleaseBlockAndEncap( block_t *p_block )
 {
     fake_block_t *p_fake = (fake_block_t *)p_block;
+
     free( dirac_RemoveBlockEncap( p_block ) );
-    p_fake->p_orig->pf_release( p_fake->p_orig );
+    block_Release( p_fake->p_orig );
     free( p_fake );
 }
 
 static void dirac_AddBlockEncap( block_t **pp_block, dirac_block_encap_t *p_dbe )
 {
-    fake_block_t *p_fake = calloc( 1, sizeof( *p_fake ) );
-    assert( p_fake ); /* must not fail, fixby: adding a p_priv to block_t */
-    p_fake->p_orig = *pp_block;
-    memcpy( &p_fake->fake, *pp_block, sizeof( block_t ) );
-    *pp_block = &p_fake->fake;
-
-    p_fake->p_priv = p_dbe;
-    p_dbe->pf_blk_release = p_fake->p_orig->pf_release;
-    p_fake->fake.pf_release = dirac_ReleaseBlockAndEncap;
+    /* must not fail, fixby: adding a p_priv to block_t */
+    fake_block_t *p_fake = xcalloc( 1, sizeof( *p_fake ) );
+    block_t *in = *pp_block, *out = &p_fake->fake;
+
+    block_Init( out, in->p_buffer, in->i_buffer );
+    out->i_flags = in->i_flags;
+    out->i_nb_samples = in->i_nb_samples;
+    out->i_pts = in->i_pts;
+    out->i_dts = in->i_dts;
+    out->i_length = in->i_length;
+    out->pf_release = dirac_ReleaseBlockAndEncap;
+    p_fake->p_orig = in;
+    p_fake->p_dbe = p_dbe;
+
+    *pp_block = out;
 }
 
 static dirac_block_encap_t *dirac_NewBlockEncap( block_t **pp_block )
 {
-    dirac_block_encap_t *dbe = calloc( 1, sizeof( *dbe ) );
-    if( dbe ) dirac_AddBlockEncap( pp_block, dbe );
-    return dbe;
+    dirac_block_encap_t *p_dbe = calloc( 1, sizeof( *p_dbe ) );
+    if( p_dbe ) dirac_AddBlockEncap( pp_block, p_dbe );
+    return p_dbe;
 }
 
 static dirac_block_encap_t *dirac_GetBlockEncap( block_t *p_block )
 {
-    return (dirac_block_encap_t*) ((fake_block_t *)p_block)->p_priv;
+    return ((fake_block_t *)p_block)->p_dbe;
 }
 
 /***
  * General utility funcions
  */
 
-/* decrement a date. opposite to date_Increment */
-static mtime_t date_Decrement( date_t *p_date, uint32_t i_nb_samples )
-{
-    mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000 * p_date->i_divider_den;
-    p_date->date -= i_dividend / p_date->i_divider_num;
-    unsigned u_rem_adjust = i_dividend % p_date->i_divider_num;
-
-    if( p_date->i_remainder < u_rem_adjust )
-    {
-        /* This is Bresenham algorithm. */
-        assert( p_date->i_remainder > -p_date->i_divider_num);
-        p_date->date -= 1;
-        p_date->i_remainder += p_date->i_divider_num;
-    }
-
-    p_date->i_remainder -= u_rem_adjust;
-
-    return p_date->date;
-}
-
 /**
  * given a chain of block_t, allocate and return an array containing
  * pointers to all the blocks. (Acts as a replacement for the old p_prev
@@ -296,24 +277,24 @@ static int block_ChainToArray( block_t *p_block, block_t ***ppp_array)
     if( !ppp_array )
         return 0;
 
-    int num_blocks;
-    block_ChainProperties( p_block, &num_blocks, NULL, NULL );
+    int i_num_blocks;
+    block_ChainProperties( p_block, &i_num_blocks, NULL, NULL );
 
-    *ppp_array = malloc( sizeof( block_t* ) * num_blocks );
-    if( !ppp_array ) return 0;
+    *ppp_array = calloc( i_num_blocks, sizeof( block_t* ) );
+    if( !*ppp_array ) return 0;
 
-    for( int i = 0; i < num_blocks; i++ )
+    for( int i = 0; i < i_num_blocks; i++ )
     {
         (*ppp_array)[i] = p_block;
         p_block = p_block->p_next;
     }
 
-    return num_blocks;
+    return i_num_blocks;
 }
 
 /**
  * Destructively find and recover the earliest timestamp from start of
- * bytestream, upto i_length.
+ * bytestream, up to i_length.
  */
 static void dirac_RecoverTimestamps ( decoder_t *p_dec, size_t i_length )
 {
@@ -332,7 +313,7 @@ static void dirac_RecoverTimestamps ( decoder_t *p_dec, size_t i_length )
     i_offset += i_length;
     for(; p_block != NULL; p_block = p_block->p_next )
     {
-        if( p_sys->i_sync_pts == VLC_TS_INVALID && p_sys->i_sync_dts == VLC_TS_INVALID )
+        if( p_sys->i_sync_pts <= VLC_TS_INVALID && p_sys->i_sync_dts <= VLC_TS_INVALID )
         {
             /* oldest timestamp wins */
             p_sys->i_sync_pts = p_block->i_pts;
@@ -359,7 +340,7 @@ static void dirac_BackdateDTS( block_t *p_block, block_t *p_last, date_t *p_dts
     {
         if( pp_array[n]->i_flags & DIRAC_NON_DATED )
             continue;
-        if( pp_array[n]->i_dts == VLC_TS_INVALID )
+        if( pp_array[n]->i_dts <= VLC_TS_INVALID )
             pp_array[n]->i_dts = date_Decrement( p_dts, 1 );
     }
     free( pp_array );
@@ -377,7 +358,7 @@ static void dirac_BackdatePTS( block_t *p_block, block_t *p_last, date_t *p_pts,
     {
         if( pp_array[n]->i_flags & DIRAC_NON_DATED )
             continue;
-        if( pp_array[n]->i_dts != VLC_TS_INVALID )
+        if( pp_array[n]->i_dts > VLC_TS_INVALID )
             continue;
         dirac_block_encap_t *dbe = dirac_GetBlockEncap( pp_array[n] );
         int32_t u_pic_num = dbe ? dbe->u_picture_number : 0;
@@ -418,9 +399,8 @@ static void dirac_ReorderInit( struct dirac_reorder_buffer *p_rb )
     p_rb->p_empty = p_rb->p_entries;
     p_rb->p_entries[31].p_next = NULL;
 
-    for( int i = 0; i < 31; i++ ) {
+    for( int i = 0; i < 31; i++ )
         p_rb->p_entries[i].p_next = &p_rb->p_entries[i+1];
-    }
 }
 
 /* simulate the dirac picture reorder buffer */
@@ -508,15 +488,14 @@ static bool dirac_UnpackParseInfo( parse_info_t *p_pi, block_bytestream_t *p_bs,
 
 static uint32_t dirac_uint( bs_t *p_bs )
 {
-  uint32_t count = 0, value = 0;
-  while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
-  {
-    count++;
-    value <<= 1;
-    value |= bs_read( p_bs, 1 );
-  }
-
-  return (1 << count) - 1 + value;
+    uint32_t u_count = 0, u_value = 0;
+    while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
+    {
+        u_count++;
+        u_value <<= 1;
+        u_value |= bs_read( p_bs, 1 );
+    }
+    return (1 << u_count) - 1 + u_value;
 }
 
 static int dirac_bool( bs_t *p_bs )
@@ -538,7 +517,7 @@ static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
     uint32_t u_video_format = dirac_uint( &bs ); /* index */
     if( u_video_format > 20 )
     {
-        /* dont know how to parse this header */
+        /* don't know how to parse this header */
         return false;
     }
 
@@ -589,13 +568,13 @@ static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
     if( dirac_bool( &bs ) )
     {
         uint32_t frame_rate_index = dirac_uint( &bs );
-        p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n;
-        p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d;
         if( frame_rate_index >= dirac_frate_tbl_size )
         {
             /* invalid header */
             return false;
         }
+        p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n;
+        p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d;
         if( frame_rate_index == 0 )
         {
             p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */
@@ -668,19 +647,18 @@ static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block )
 
 static block_t *dirac_EmitEOS( decoder_t *p_dec, uint32_t i_prev_parse_offset )
 {
-    const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
-    block_t *p_block = block_New( p_dec, 13 );
+    const uint8_t p_eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
+    block_t *p_block = block_Alloc( 13 );
     if( !p_block )
         return NULL;
-    memcpy( p_block->p_buffer, eos, 13 );
+    memcpy( p_block->p_buffer, p_eos, 13 );
 
     SetDWBE( p_block->p_buffer + 9, i_prev_parse_offset );
 
     p_block->i_flags = DIRAC_NON_DATED;
 
-    return p_block;
-
     (void) p_dec;
+    return p_block;
 }
 
 /***
@@ -696,7 +674,8 @@ static block_t *dirac_DoSync( decoder_t *p_dec )
     do {
         switch( p_sys->i_state )
         {
-        case NOT_SYNCED: {
+        case NOT_SYNCED:
+        {
             if( VLC_SUCCESS !=
                 block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_parsecode, 4 ) )
             {
@@ -752,21 +731,21 @@ static block_t *dirac_DoSync( decoder_t *p_dec )
             {
                 return NULL; /* retry later */
             }
-            /* attempt to syncronise backwards from pu.u_next_offset */
+            /* attempt to synchronise backwards from pu.u_next_offset */
             p_sys->i_offset = pu.u_next_offset;
             /* fall through */
-        case TRY_SYNC: { /* -> SYNCED | NOT_SYNCED */
-            if( !p_sys->i_offset ) {
+        case TRY_SYNC: /* -> SYNCED | NOT_SYNCED */
+        {
+            if( !p_sys->i_offset )
                 goto sync_fail; /* if a is at start of bytestream, b can't be in buffer */
-            }
 
             parse_info_t pu_a;
             bool a = dirac_UnpackParseInfo( &pu_a, &p_sys->bytestream, p_sys->i_offset );
-            if( !a || (pu_a.u_prev_offset > p_sys->i_offset) ) {
+            if( !a || (pu_a.u_prev_offset > p_sys->i_offset) )
                 goto sync_fail; /* b lies beyond start of bytestream: can't sync */
-            }
 
-            if( !pu_a.u_prev_offset ) {
+            if( !pu_a.u_prev_offset )
+            {
                 if( p_sys->i_state == TRY_SYNC )
                 {
                     goto sync_fail; /* can't find different pu_b from pu_a */
@@ -779,7 +758,8 @@ static block_t *dirac_DoSync( decoder_t *p_dec )
 
             parse_info_t *pu_b = &pu;
             bool b = dirac_UnpackParseInfo( pu_b, &p_sys->bytestream, p_sys->i_offset - pu_a.u_prev_offset );
-            if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) ) {
+            if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) )
+            {
                 /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
                  * just rely on finding a valid pu_b from pu_a. */
                 goto sync_fail;
@@ -807,13 +787,13 @@ sync_fail:
     /* recover any timestamps from the data that is about to be flushed */
     dirac_RecoverTimestamps( p_dec, p_sys->i_offset );
 
-    /* flush everything upto the start of the DU */
+    /* flush everything up to the start of the DU */
     block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
     block_BytestreamFlush( &p_sys->bytestream );
     p_sys->i_offset = 0;
 
     /* setup the data unit buffer */
-    block_t *p_block = block_New( p_dec, pu.u_next_offset );
+    block_t *p_block = block_Alloc( pu.u_next_offset );
     if( !p_block )
         return NULL;
 
@@ -827,8 +807,8 @@ sync_fail:
     block_GetBytes( &p_sys->bytestream, p_block->p_buffer, p_block->i_buffer );
 
     /* save parse offset in private area for later use */
-    dirac_block_encap_t *dbe = dirac_NewBlockEncap( &p_block );
-    if( dbe ) dbe->u_last_next_offset = pu.u_next_offset;
+    dirac_block_encap_t *p_dbe = dirac_NewBlockEncap( &p_block );
+    if( p_dbe ) p_dbe->u_last_next_offset = pu.u_next_offset;
 
     return p_block;
 }
@@ -854,7 +834,7 @@ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t
             return DIRAC_DU_IN_EU;
         }
         /* p_block is an EOS packet */
-        p_eu->i_flags |= DIRAC_EOS;
+        p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
         /* for the moment, let this end an encapsulation unit */
         /* seeing an eos packet requires a flush of the packetizer
          * this is detected by the caller of this function */
@@ -867,7 +847,7 @@ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t
         Actually, this is a bad idea:
          - It sets the discontinuity for every dirac EOS packet
            which doesnt imply a time discontinuity.
-         - When the syncronizer detects a real discontinuity, it
+         - When the synchronizer detects a real discontinuity, it
            should copy the flags through.
         p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
         */
@@ -895,12 +875,12 @@ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t
              * random access point flags are not set */
             p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
         }
-        dirac_block_encap_t *dbe = dirac_GetBlockEncap( p_block );
-        if( dbe && p_block->i_buffer > 13+4 )
+        dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
+        if( p_dbe && p_block->i_buffer > 13+4 )
         {
             /* record the picture number to save the time gen functions
              * from having to inspect the data for it */
-            dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
+            p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
         }
         return DIRAC_DU_ENDS_EU;
     }
@@ -927,8 +907,8 @@ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t
                    , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );
 
         /* when field coding, dts needs to be incremented in terms of field periods */
-        int u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
-        if (p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING)
+        unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
+        if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING )
         {
             u_pics_per_sec *= 2;
         }
@@ -943,8 +923,7 @@ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t
          *  - required for ogg muxing
          *  - useful for error checking
          *  - it isn't allowed to change until an eos */
-        if( p_es->p_extra )
-            free( p_es->p_extra );
+        free( p_es->p_extra );
         p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
         if( !p_es->p_extra )
         {
@@ -978,12 +957,12 @@ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block
 
     assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer ));
 
-    if( p_sys->i_eu_pts == VLC_TS_INVALID && p_sys->i_eu_dts == VLC_TS_INVALID )
+    if( p_sys->i_eu_pts <= VLC_TS_INVALID && p_sys->i_eu_dts <= VLC_TS_INVALID )
     {
         /* earliest block with pts/dts gets to set the pts/dts for the dated
          * encapsulation unit as a whole */
         /* NB, the 'earliest block' criteria is aribtary */
-        if( p_block->i_pts != VLC_TS_INVALID || p_block->i_dts != VLC_TS_INVALID )
+        if( p_block->i_pts > VLC_TS_INVALID || p_block->i_dts > VLC_TS_INVALID )
         {
             p_sys->i_eu_pts = p_block->i_pts;
             p_sys->i_eu_dts = p_block->i_dts;
@@ -1009,14 +988,14 @@ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block
 
     block_ChainLastAppend( &p_sys->pp_eu_last, p_block );
 
-    dirac_block_encap_t *dbe = dirac_GetBlockEncap( p_block );
+    dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
 #ifdef SANITIZE_PREV_PARSE_OFFSET
     /* fixup prev_parse_offset to point to the last data unit
      * to arrive */
-    if( dbe )
+    if( p_dbe )
     {
         SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo );
-        p_sys->u_eu_last_npo = dbe->u_last_next_offset;
+        p_sys->u_eu_last_npo = p_dbe->u_last_next_offset;
     }
 #endif
 
@@ -1029,7 +1008,7 @@ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block
     /* gather up encapsulation unit, reassociating the final
      * private state with the gathered block */
     block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next );
-    dbe = dirac_RemoveBlockEncap( p_eu_last );
+    p_dbe = dirac_RemoveBlockEncap( p_eu_last );
 
     uint8_t u_parse_code = p_block->p_buffer[4];
 
@@ -1038,9 +1017,9 @@ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block
     assert( p_block ); /* block_ChainGather doesn't define when it frees chain */
 
     p_block->i_flags |= DIRAC_NON_DATED;
-    if( dbe )
+    if( p_dbe )
     {
-        dirac_AddBlockEncap( &p_block, dbe );
+        dirac_AddBlockEncap( &p_block, p_dbe );
         if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED;
     }
     p_sys->p_eu = NULL;
@@ -1055,15 +1034,15 @@ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block
  *
  * Returns:
  *  0: everything ok
- *  1: EOS occured, please flush and reset
+ *  1: EOS occurred, please flush and reset
  *  2: picture number discontinuity, please flush and reset
  */
 static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    dirac_block_encap_t *dbe;
+    dirac_block_encap_t *p_dbe;
 
-    if( p_block_in->i_flags & DIRAC_EOS )
+    if( p_block_in->i_flags & BLOCK_FLAG_END_OF_SEQUENCE )
     {
         /* NB, this test occurs after the timegen push, so as to
          * push the block into the output queue */
@@ -1077,8 +1056,8 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
         return 0;
     }
 
-    dbe = dirac_GetBlockEncap( p_block_in );
-    uint32_t u_picnum = dbe ? dbe->u_picture_number : 0;
+    p_dbe = dirac_GetBlockEncap( p_block_in );
+    uint32_t u_picnum = p_dbe ? p_dbe->u_picture_number : 0;
     /*
      * Simple DTS regeneration:
      *  - DTS values linearly increase in stream order.
@@ -1100,7 +1079,7 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
      * Stage 1, sync to input timestamps, backdate timestamps for old
      * EUs that are in the outqueue with missing dates
      */
-    if( p_block_in->i_dts != VLC_TS_INVALID )
+    if( p_block_in->i_dts > VLC_TS_INVALID )
     do {
         /* if timestamps exist, sync to them */
         if( p_sys->b_dts )
@@ -1111,7 +1090,7 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
         dirac_BackdateDTS( p_sys->p_outqueue, p_block_in, &dts );
     } while( 0 );
 
-    if( p_block_in->i_pts != VLC_TS_INVALID )
+    if( p_block_in->i_pts > VLC_TS_INVALID )
     do {
         /* if timestamps exist, sync to them */
         p_sys->u_pts_picnum = u_picnum;
@@ -1137,13 +1116,13 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
     /*
      * Stage 3, for block_in, interpolate any missing timestamps
      */
-    if( p_sys->b_dts && p_block_in->i_dts == VLC_TS_INVALID )
+    if( p_sys->b_dts && p_block_in->i_dts <= VLC_TS_INVALID )
     {
         /* dts has previously been seen, but not this time, interpolate */
         p_block_in->i_dts = date_Increment( &p_sys->dts, 1 );
     }
 
-    if( p_sys->b_pts && p_block_in->i_pts == VLC_TS_INVALID )
+    if( p_sys->b_pts && p_block_in->i_pts <= VLC_TS_INVALID )
     {
         /* pts has previously been seen, but not this time, interpolate */
         date_t pts = p_sys->dts;
@@ -1161,9 +1140,6 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
     if( p_sys->b_dts == p_sys->b_pts )
         return 0;
 
-    if( !p_sys->p_out_dts )
-        p_sys->p_out_dts = p_sys->p_outqueue;
-
     /* model the reorder buffer */
     block_t *p_block = dirac_Reorder( p_dec, p_block_in, u_picnum );
     if( !p_block )
@@ -1173,8 +1149,8 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
      * the first packet is output -- interpolate the past and freewheel for
      * the future */
 
-    dbe = dirac_GetBlockEncap( p_block );
-    u_picnum = dbe ? dbe->u_picture_number : 0;
+    p_dbe = dirac_GetBlockEncap( p_block );
+    u_picnum = p_dbe ? p_dbe->u_picture_number : 0;
     if( p_sys->b_tg_last_picnum )
     {
         if( dirac_PictureNbeforeM( u_picnum, p_sys->u_tg_last_picnum ) )
@@ -1186,8 +1162,8 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
              * a discontinuity, some pictures will get stuck in the RoB.
              * flush the RoB. */
             /* this could be a bit less indiscriminate */
-            dbe = dirac_GetBlockEncap( p_sys->p_outqueue );
-            uint32_t u_prev_parse_offset = dbe ? dbe->u_last_next_offset : 0;
+            p_dbe = dirac_GetBlockEncap( p_sys->p_outqueue );
+            uint32_t u_prev_parse_offset = p_dbe ? p_dbe->u_last_next_offset : 0;
             block_ChainRelease( p_sys->p_outqueue );
             p_sys->p_outqueue = dirac_EmitEOS( p_dec, u_prev_parse_offset );
             if( p_sys->p_outqueue )
@@ -1200,25 +1176,35 @@ static int dirac_TimeGenPush( decoder_t *p_dec, block_t *p_block_in )
     p_sys->b_tg_last_picnum = true;
     p_sys->u_tg_last_picnum = u_picnum;
 
-    if( !p_sys->b_pts )
+    return 0;
+}
+
+
+static void dirac_ReorderDequeueAndReleaseBlock( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    /* Check if that block is present in reorder queue and release it
+       if needed */
+    struct dirac_reorder_entry **pp_at = &p_sys->reorder_buf.p_head;
+    for( ; *pp_at; pp_at = &(*pp_at)->p_next )
     {
-        /* some demuxers (eg, AVI) will provide a series of fake dts values,
-         * which are actually inorder pts values (ie, what should be seen at
-         * the output of a decoder.  A main reason for simulating the reorder
-         * buffer is to turn the inorder fakedts into an out-of-order pts */
-        p_block->i_pts = p_sys->p_out_dts->i_dts;
-        p_sys->p_out_dts->i_dts = VLC_TS_INVALID;
-    }
+        /* backup address in case we remove member */
+        struct dirac_reorder_entry *p_entry = *pp_at;
+        if ( p_entry->p_eu == p_block )
+        {
+            /* unlink member */
+            *pp_at = (*pp_at)->p_next;
 
-    /* If pts was copied from dts, the dts needs to be corrected to account for reordering*/
-    /* If dts has never been seen, the same needs to happen */
-    p_sys->p_out_dts->i_dts = p_block->i_pts - p_sys->i_pts_offset;
+            /* Add to empty reorder entry list*/
+            p_entry->p_next = p_sys->reorder_buf.p_empty;
+            p_sys->reorder_buf.p_empty = p_entry;
 
-    /* move dts pointer */
-    if( p_sys->p_out_dts )
-        p_sys->p_out_dts = p_sys->p_out_dts->p_next;
+            p_sys->reorder_buf.u_size--;
+            break;
+        }
+    }
 
-    return 0;
+    block_Release( p_block );
 }
 
 /*****************************************************************************
@@ -1230,21 +1216,11 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
     block_t *p_block = NULL;
     int i_flushing = 0;
 
-    while( pp_block && *pp_block )
+    if( pp_block && *pp_block )
     {
         p_block = *pp_block;
-        *pp_block = p_block->p_next;
-        p_block->p_next = NULL;
+        *pp_block = NULL;
 
-        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
-        {
-            /* silently discard corruption sentinels,
-             * synchronizer will then discard affected data units.
-             * do not produce an EOS data unit as this is very
-             * disruptive to the stream (and may make a larger error). */
-            block_Release( p_block );
-            continue;
-        }
         if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
         {
             /* pre-emptively insert an EOS at a discontinuity, protects
@@ -1254,15 +1230,25 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
             if( p_block )
             {
                 p_block->p_next = dirac_EmitEOS( p_dec, 13 );
-                /* need two EOS to ensure it gets detected by syncro
+                /* need two EOS to ensure it gets detected by synchro
                  * duplicates get discarded in forming encapsulation unit */
             }
         }
-        block_BytestreamPush( &p_sys->bytestream, p_block );
+        else if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
+        {
+            /* silently discard corruption sentinels,
+             * synchronizer will then discard affected data units.
+             * do not produce an EOS data unit as this is very
+             * disruptive to the stream (and may make a larger error). */
+            block_Release( p_block );
+            p_block = NULL;
+        }
+        if( p_block )
+            block_BytestreamPush( &p_sys->bytestream, p_block );
     }
 
     /* form as many encapsulation units as possible, give up
-     * when the syncronizer runs out of input data */
+     * when the synchronizer runs out of input data */
     while( ( p_block = dirac_DoSync( p_dec ) ) )
     {
         p_block = dirac_BuildEncapsulationUnit( p_dec, p_block );
@@ -1280,7 +1266,7 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
     block_t *p_output = NULL;
     block_t **pp_output = &p_output;
 
-    /* extract all the dated packets from the head of the ouput queue */
+    /* extract all the dated packets from the head of the output queue */
     /* explicitly nondated packets repeat the previous timestamps to
      * stop vlc discarding them */
     while( (p_block = p_sys->p_outqueue) )
@@ -1298,8 +1284,8 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
             p_block->i_dts = p_sys->i_dts_last_out;
             p_block->i_pts = p_sys->i_pts_last_out;
         }
-        else if( p_block->i_pts == VLC_TS_INVALID ) break;
-        else if( p_block->i_dts == VLC_TS_INVALID ) break;
+        else if( p_block->i_pts <= VLC_TS_INVALID ) break;
+        else if( p_block->i_dts <= VLC_TS_INVALID ) break;
 
         p_sys->i_dts_last_out = p_block->i_dts;
         p_sys->i_pts_last_out = p_block->i_pts;
@@ -1331,7 +1317,6 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
         dirac_ReorderInit( &p_sys->reorder_buf );
 
         assert( p_sys->p_outqueue == NULL );
-        p_sys->p_out_dts = NULL;
     }
 
     /* perform sanity check:
@@ -1340,20 +1325,17 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
      *  the output queue would grow bounded by the stream length.
      * If there are 10 data units in the output queue, assume this
      * has happened and purge all blocks that fail extraction criteria */
-    unsigned count = 0;
-    for( p_block = p_sys->p_outqueue; p_block; p_block = p_block->p_next )
-    {
-        count++;
-    }
-    if( count > 9 )
+    int i_count;
+    block_ChainProperties( p_sys->p_outqueue, &i_count, NULL, NULL );
+    if( i_count > 9 )
     {
         p_block = p_sys->p_outqueue;
         while( p_block )
         {
             block_t *p_block_next = p_block->p_next;
-            if( p_block->i_pts != VLC_TS_INVALID && p_block->i_dts != VLC_TS_INVALID )
+            if( p_block->i_pts > VLC_TS_INVALID && p_block->i_dts > VLC_TS_INVALID )
                 break;
-            block_Release( p_block );
+            dirac_ReorderDequeueAndReleaseBlock( p_dec, p_block );
             p_sys->p_outqueue = p_block = p_block_next;
         }
     }
@@ -1373,7 +1355,7 @@ static int Open( vlc_object_t *p_this )
     decoder_t     *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys;
 
-    if( p_dec->fmt_in.i_codec !=  VLC_FOURCC( 'd','r','a','c' ) )
+    if( p_dec->fmt_in.i_codec !=  VLC_CODEC_DIRAC )
         return VLC_EGENERIC;
 
     p_dec->pf_packetize = Packetize;
@@ -1390,7 +1372,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_dts_last_out = p_sys->i_pts_last_out = VLC_TS_INVALID;
 
     p_sys->i_state = NOT_SYNCED;
-    p_sys->bytestream = block_BytestreamInit();
+    block_BytestreamInit( &p_sys->bytestream );
 
     p_sys->pp_outqueue_last = &p_sys->p_outqueue;
     p_sys->pp_eu_last = &p_sys->p_eu;
@@ -1403,7 +1385,7 @@ static int Open( vlc_object_t *p_this )
         /* handle hacky systems like ogg that dump some headers
          * in p_extra. and packetizers that expect it to be filled
          * in before real startup */
-        block_t *p_init = block_New( p_dec, p_dec->fmt_in.i_extra );
+        block_t *p_init = block_Alloc( p_dec->fmt_in.i_extra );
         if( !p_init )
         {
             /* memory might be avaliable soon.  it isn't the end of
@@ -1438,9 +1420,6 @@ static void Close( vlc_object_t *p_this )
     decoder_t     *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( !p_sys )
-        return;
-
     block_BytestreamRelease( &p_sys->bytestream );
     if( p_sys->p_outqueue )
         block_ChainRelease( p_sys->p_outqueue );