/*****************************************************************************
* h264.c: h264/avc video packetizer
*****************************************************************************
- * Copyright (C) 2001, 2002 VideoLAN
+ * Copyright (C) 2001, 2002, 2006 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
vlc_module_begin();
set_category( CAT_SOUT );
set_subcategory( SUBCAT_SOUT_PACKETIZER );
- set_description( _("H264 video packetizer") );
+ set_description( _("H.264 video packetizer") );
set_capability( "packetizer", 50 );
set_callbacks( Open, Close );
vlc_module_end();
block_t *p_frame;
vlc_bool_t b_sps;
+ vlc_bool_t b_pps;
/* avcC data */
int i_avcC_length_size;
+ block_t *p_sps;
+ block_t *p_pps;
/* Useful values of the Sequence Parameter Set */
int i_log2_max_frame_num;
p_sys->b_slice = VLC_FALSE;
p_sys->p_frame = NULL;
p_sys->b_sps = VLC_FALSE;
+ p_sys->b_pps = VLC_FALSE;
+ p_sys->p_sps = 0;
+ p_sys->p_pps = 0;
p_sys->i_nal_type = -1;
p_sys->i_nal_ref_idc = -1;
int i_length = GetWBE( p );
block_t *p_sps = nal_get_annexeb( p_dec, p + 2, i_length );
+ p_sys->p_sps = block_Duplicate( p_sps );
+ p_sps->i_pts = p_sps->i_dts = mdate();
ParseNALBlock( p_dec, p_sps );
p += 2 + i_length;
}
int i_length = GetWBE( p );
block_t *p_pps = nal_get_annexeb( p_dec, p + 2, i_length );
+ p_sys->p_pps = block_Duplicate( p_pps );
+ p_pps->i_pts = p_pps->i_dts = mdate();
ParseNALBlock( p_dec, p_pps );
p += 2 + i_length;
}
- msg_Dbg( p_dec, "avcC length size=%d sps=%d pps=%d",
+ msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d",
p_sys->i_avcC_length_size, i_sps, i_pps );
/* Set callback */
{
/* Set callback */
p_dec->pf_packetize = Packetize;
+
+ /* */
+ 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 );
+ }
+ }
}
return VLC_SUCCESS;
decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
+ if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
+ if( p_sys->p_sps ) block_Release( p_sys->p_sps );
+ if( p_sys->p_pps ) block_Release( p_sys->p_pps );
block_BytestreamRelease( &p_sys->bytestream );
free( p_sys );
}
case STATE_NEXT_SYNC:
/* Find the next startcode */
if( block_FindStartcodeFromOffset( &p_sys->bytestream,
- &p_sys->i_offset, p_sys->startcode, 3 ) != VLC_SUCCESS)
+ &p_sys->i_offset, p_sys->startcode+1, 3 ) != VLC_SUCCESS)
{
- if( block_FindStartcodeFromOffset( &p_sys->bytestream,
- &p_sys->i_offset, p_sys->startcode+1, 3 ) !=
- VLC_SUCCESS )
- {
- /* Need more data */
- return NULL;
- }
+ /* Need more data */
+ return NULL;
}
/* Get the new fragment and set the pts/dts */
block_GetBytes( &p_sys->bytestream, p_pic->p_buffer,
p_pic->i_buffer );
+ if( !p_pic->p_buffer[p_pic->i_buffer-1] ) p_pic->i_buffer--;
p_sys->i_offset = 0;
/* Parse the NAL */
p_block = *pp_block;
*pp_block = NULL;
+#if 0
+ if( //(p_block->i_flags & BLOCK_FLAG_TYPE_I) &&
+ p_sys->p_sps && p_sys->p_pps )
+ {
+ block_t *p_pic;
+ block_t *p_sps = block_Duplicate( p_sys->p_sps );
+ block_t *p_pps = block_Duplicate( p_sys->p_pps );
+ p_sps->i_dts = p_pps->i_dts = p_block->i_dts;
+ p_sps->i_pts = p_pps->i_pts = p_block->i_pts;
+ p_pic = ParseNALBlock( p_dec, p_sps );
+ if( p_pic ) block_ChainAppend( &p_ret, p_pic );
+ p_pic = ParseNALBlock( p_dec, p_pps );
+ if( p_pic ) block_ChainAppend( &p_ret, p_pic );
+ }
+#endif
+
for( p = p_block->p_buffer; p < &p_block->p_buffer[p_block->i_buffer]; )
{
block_t *p_pic;
}
p += i_size;
}
+ block_Release( p_block );
return p_ret;
}
}
p_sys->i_nal_type = i_nal_type;
- if( b_pic && p_sys->b_slice )
- OUTPUT;
+ if( b_pic && p_sys->b_slice ) OUTPUT;
p_sys->b_slice = VLC_TRUE;
bs_t s;
int i_tmp;
- msg_Dbg( p_dec, "found NAL_SPS" );
+ if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS" );
p_sys->b_sps = VLC_TRUE;
w = bs_read( &s, 16 );
h = bs_read( &s, 16 );
}
- p_dec->fmt_out.video.i_aspect =
- VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width /
- p_dec->fmt_out.video.i_height;
+ if( h != 0 )
+ p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * w /
+ h * p_dec->fmt_out.video.i_width /
+ p_dec->fmt_out.video.i_height;
+ else
+ p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR;
}
}
free( dec );
- if( p_sys->b_slice )
- OUTPUT;
+ if( p_sys->b_slice ) OUTPUT;
}
else if( i_nal_type == NAL_PPS )
{
bs_t s;
bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 );
+ if( !p_sys->b_pps ) msg_Dbg( p_dec, "found NAL_PPS" );
+ p_sys->b_pps = VLC_TRUE;
+
/* TODO */
- msg_Dbg( p_dec, "found NAL_PPS" );
- if( p_sys->b_slice )
- OUTPUT;
+ if( p_sys->b_slice ) OUTPUT;
}
else if( i_nal_type == NAL_AU_DELIMITER ||
i_nal_type == NAL_SEI ||
( i_nal_type >= 13 && i_nal_type <= 18 ) )
{
- if( p_sys->b_slice )
- OUTPUT;
+ if( p_sys->b_slice ) OUTPUT;
}
#undef OUTPUT