/* 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.
#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
};
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 {
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;
+ dirac_block_encap_t *p_dbe = p_fake->p_priv;
+ if( !p_dbe ) return NULL;
p_fake->p_priv = NULL;
- dbe->pf_blk_release = NULL;
- return dbe;
+ p_dbe->pf_blk_release = NULL;
+ return p_dbe;
}
static void dirac_ReleaseBlockAndEncap( block_t *p_block )
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 )
* 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
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;
}
/**
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 */
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 )
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 };
+ const uint8_t p_eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
block_t *p_block = block_New( p_dec, 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 );
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 ) )
{
/* attempt to syncronise 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 */
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;
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;
}
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 */
* 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;
}
, 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;
}
* - 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 )
{
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
/* 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];
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;
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 */
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.
* 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 ) )
* 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 )
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
* 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
* 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 )
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;
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 );