#include "vlc_block_helper.h"
#include "vlc_bits.h"
#include "../codec/cc.h"
+#include "packetizer_helper.h"
/*****************************************************************************
* Module descriptor
/****************************************************************************
* Local prototypes
****************************************************************************/
-static block_t *Packetize( decoder_t *, block_t ** );
-static block_t *PacketizeAVC1( decoder_t *, block_t ** );
-static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] );
-
typedef struct
{
int i_nal_type;
#define PPS_MAX (256)
struct decoder_sys_t
{
- block_bytestream_t bytestream;
-
- int i_state;
- size_t i_offset;
- uint8_t startcode[4];
+ /* */
+ packetizer_t packetizer;
+ /* */
bool b_slice;
block_t *p_frame;
cc_data_t cc_next;
};
-enum
-{
- STATE_NOSYNC,
- STATE_NEXT_SYNC,
-};
-
enum nal_unit_type_e
{
NAL_UNKNOWN = 0,
NAL_PRIORITY_HIGHEST = 3,
};
-static block_t *ParseNALBlock( decoder_t *, bool *pb_used_ts, block_t * );
+static block_t *Packetize( decoder_t *, block_t ** );
+static block_t *PacketizeAVC1( decoder_t *, block_t ** );
+static block_t *GetCc( decoder_t *p_dec, bool pb_present[4] );
+
+static void PacketizeReset( void *p_private, bool b_broken );
+static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * );
+static int PacketizeValidate( void *p_private, block_t * );
+static block_t *ParseNALBlock( decoder_t *, bool *pb_used_ts, block_t * );
static block_t *CreateAnnexbNAL( decoder_t *, const uint8_t *p, int );
static block_t *OutputPicture( decoder_t *p_dec );
static void ParseSei( decoder_t *, block_t * );
+static const uint8_t p_h264_startcode[3] = { 0x00, 0x00, 0x01 };
+
/*****************************************************************************
* Open: probe the packetizer and return score
* When opening after demux, the packetizer is only loaded AFTER the decoder
decoder_sys_t *p_sys;
int i;
- if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'h', '2', '6', '4') &&
+ if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 &&
p_dec->fmt_in.i_codec != VLC_FOURCC( 'H', '2', '6', '4') &&
p_dec->fmt_in.i_codec != VLC_FOURCC( 'V', 'S', 'S', 'H') &&
p_dec->fmt_in.i_codec != VLC_FOURCC( 'v', 's', 's', 'h') &&
{
return VLC_ENOMEM;
}
- p_sys->i_state = STATE_NOSYNC;
- p_sys->i_offset = 0;
- p_sys->startcode[0] = 0;
- p_sys->startcode[1] = 0;
- p_sys->startcode[2] = 0;
- p_sys->startcode[3] = 1;
- p_sys->bytestream = block_BytestreamInit();
+
+ packetizer_Init( &p_sys->packetizer,
+ p_h264_startcode, sizeof(p_h264_startcode),
+ p_h264_startcode, 1,
+ PacketizeReset, PacketizeParse, PacketizeValidate, p_dec );
+
p_sys->b_slice = false;
p_sys->p_frame = NULL;
p_sys->b_header= false;
/* Setup properties */
es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
- p_dec->fmt_out.i_codec = VLC_FOURCC( 'h', '2', '6', '4' );
+ p_dec->fmt_out.i_codec = VLC_CODEC_H264;
if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
{
/* */
if( p_dec->fmt_in.i_extra > 0 )
- {
- block_t *p_init = block_New( p_dec, p_dec->fmt_in.i_extra );
- block_t *p_pic;
-
- memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra,
- p_dec->fmt_in.i_extra );
-
- while( ( p_pic = Packetize( p_dec, &p_init ) ) )
- {
- /* Should not occur because we should only receive SPS/PPS */
- block_Release( p_pic );
- }
- }
+ packetizer_Header( &p_sys->packetizer,
+ p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
}
return VLC_SUCCESS;
if( p_sys->pp_pps[i] )
block_Release( p_sys->pp_pps[i] );
}
- block_BytestreamRelease( &p_sys->bytestream );
+ packetizer_Clean( &p_sys->packetizer );
+
if( p_dec->pf_get_cc )
{
cc_Exit( &p_sys->cc_next );
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
{
decoder_sys_t *p_sys = p_dec->p_sys;
- block_t *p_pic;
-
- if( !pp_block || !*pp_block )
- return NULL;
-
- if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
- {
- if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
- {
- p_sys->i_state = STATE_NOSYNC;
- block_BytestreamEmpty( &p_sys->bytestream );
-
- if( p_sys->p_frame )
- block_ChainRelease( p_sys->p_frame );
- p_sys->p_frame = NULL;
- p_sys->slice.i_frame_type = 0;
- p_sys->b_slice = false;
- }
- p_sys->i_frame_pts = -1;
- p_sys->i_frame_dts = -1;
-
- block_Release( *pp_block );
- return NULL;
- }
-
- block_BytestreamPush( &p_sys->bytestream, *pp_block );
-
- for( ;; )
- {
- bool b_used_ts;
-
- switch( p_sys->i_state )
- {
- case STATE_NOSYNC:
- /* Skip until 3 byte startcode 0 0 1 */
- if( block_FindStartcodeFromOffset( &p_sys->bytestream,
- &p_sys->i_offset, p_sys->startcode+1, 3 ) == VLC_SUCCESS)
- {
- p_sys->i_state = STATE_NEXT_SYNC;
- }
- if( p_sys->i_offset )
- {
- /* skip the data */
- block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
- p_sys->i_offset = 0;
- block_BytestreamFlush( &p_sys->bytestream );
- }
-
- if( p_sys->i_state != STATE_NEXT_SYNC )
- {
- /* Need more data */
- return NULL;
- }
-
- p_sys->i_offset = 1; /* To find next startcode */
-
- case STATE_NEXT_SYNC:
- /* Find the next 3 byte startcode 0 0 1*/
- if( block_FindStartcodeFromOffset( &p_sys->bytestream,
- &p_sys->i_offset, p_sys->startcode+1, 3 ) != VLC_SUCCESS)
- {
- /* Need more data */
- return NULL;
- }
- block_BytestreamFlush( &p_sys->bytestream );
-
- /* Get the new fragment and set the pts/dts */
- block_t *p_block_bytestream = p_sys->bytestream.p_block;
-
- p_pic = block_New( p_dec, p_sys->i_offset +1 );
- p_pic->i_pts = p_block_bytestream->i_pts;
- p_pic->i_dts = p_block_bytestream->i_dts;
-
- /* Force 4 byte startcode 0 0 0 1 */
- p_pic->p_buffer[0] = 0;
-
- block_GetBytes( &p_sys->bytestream, &p_pic->p_buffer[1],
- p_pic->i_buffer-1 );
-
- /* Remove trailing 0 bytes */
- while( p_pic->i_buffer && (!p_pic->p_buffer[p_pic->i_buffer-1] ) )
- p_pic->i_buffer--;
- p_sys->i_offset = 0;
-
- /* Parse the NAL */
- p_pic = ParseNALBlock( p_dec, &b_used_ts, p_pic );
- if( b_used_ts )
- {
- p_block_bytestream->i_dts = -1;
- p_block_bytestream->i_pts = -1;
- }
-
- if( !p_pic )
- {
- p_sys->i_state = STATE_NOSYNC;
- break;
- }
-#if 0
- msg_Dbg( p_dec, "pts=%"PRId64" dts=%"PRId64,
- p_pic->i_pts, p_pic->i_dts );
-#endif
-
- /* So p_block doesn't get re-added several times */
- *pp_block = block_BytestreamPop( &p_sys->bytestream );
-
- p_sys->i_state = STATE_NOSYNC;
-
- return p_pic;
- }
- }
+ return packetizer_Packetize( &p_sys->packetizer, pp_block );
}
/****************************************************************************
/****************************************************************************
* Helpers
****************************************************************************/
+static void PacketizeReset( void *p_private, bool b_broken )
+{
+ decoder_t *p_dec = p_private;
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if( b_broken )
+ {
+ if( p_sys->p_frame )
+ block_ChainRelease( p_sys->p_frame );
+ p_sys->p_frame = NULL;
+ p_sys->slice.i_frame_type = 0;
+ p_sys->b_slice = false;
+ }
+ p_sys->i_frame_pts = -1;
+ p_sys->i_frame_dts = -1;
+}
+static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block )
+{
+ decoder_t *p_dec = p_private;
+
+ /* Remove trailing 0 bytes */
+ while( p_block->i_buffer && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
+ p_block->i_buffer--;
+
+ return ParseNALBlock( p_dec, pb_ts_used, p_block );
+}
+static int PacketizeValidate( void *p_private, block_t *p_au )
+{
+ VLC_UNUSED(p_private);
+ VLC_UNUSED(p_au);
+ return VLC_SUCCESS;
+}
+
static block_t *CreateAnnexbNAL( decoder_t *p_dec, const uint8_t *p, int i_size )
{
block_t *p_nal;
p_pic = OutputPicture( p_dec );
/* Parse SEI for CC support */
- ParseSei( p_dec, p_frag );
+ if( i_nal_type == NAL_SEI )
+ ParseSei( p_dec, p_frag );
}
/* Append the block */