Commit 0da5762a authored by Francois Cartegnie's avatar Francois Cartegnie

packetizer: h264: update sps/pps parsing

parent 5f685c9f
...@@ -419,9 +419,9 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD) ...@@ -419,9 +419,9 @@ libiomx_plugin_la_LIBADD = $(libomxil_plugin_la_LIBADD)
libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil libmediacodec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/codec/omxil
libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacodec.h \ libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacodec.h \
codec/omxil/mediacodec_jni.c codec/omxil/mediacodec_ndk.c codec/omxil/utils.c \ codec/omxil/mediacodec_jni.c codec/omxil/mediacodec_ndk.c codec/omxil/utils.c \
video_chroma/copy.c video_chroma/copy.c \
video_output/android/utils.c video_output/android/utils.h video_output/android/utils.c video_output/android/utils.h \
packetizer/h264_nal.c packetizer/h264_nal.h packetizer/hxxx_nal.h packetizer/h264_nal.c packetizer/h264_nal.h \
packetizer/hevc_nal.c packetizer/hevc_nal.h packetizer/hevc_nal.c packetizer/hevc_nal.h
codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout) codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout)
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "mediacodec.h" #include "mediacodec.h"
#include "../../packetizer/h264_nal.h" #include "../../packetizer/h264_nal.h"
#include "../../packetizer/hevc_nal.h" #include "../../packetizer/hevc_nal.h"
#include "../../packetizer/hxxx_nal.h"
#include <OMX_Core.h> #include <OMX_Core.h>
#include <OMX_Component.h> #include <OMX_Component.h>
#include "omxil_utils.h" #include "omxil_utils.h"
...@@ -262,19 +263,31 @@ static int H264SetCSD(decoder_t *p_dec, void *p_buf, size_t i_size, ...@@ -262,19 +263,31 @@ static int H264SetCSD(decoder_t *p_dec, void *p_buf, size_t i_size,
bool *p_size_changed) bool *p_size_changed)
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
struct h264_nal_sps sps;
uint8_t *p_sps_buf = NULL, *p_pps_buf = NULL; uint8_t *p_sps_buf = NULL, *p_pps_buf = NULL;
size_t i_sps_size = 0, i_pps_size = 0; size_t i_sps_size = 0, i_pps_size = 0;
/* Check if p_buf contains a valid SPS PPS */ /* Check if p_buf contains a valid SPS PPS */
if (h264_get_spspps(p_buf, i_size, &p_sps_buf, &i_sps_size, if (h264_get_spspps(p_buf, i_size, &p_sps_buf, &i_sps_size,
&p_pps_buf, &i_pps_size) == 0 &p_pps_buf, &i_pps_size) == 0 )
&& h264_parse_sps(p_sps_buf, i_sps_size, &sps) == 0
&& sps.i_width && sps.i_height)
{ {
struct csd csd[2]; struct csd csd[2];
int i_csd_count = 0; int i_csd_count = 0;
const uint8_t *p_buffer = p_sps_buf;
size_t i_buffer = i_sps_size;
if(!hxxx_strip_AnnexB_startcode(&p_buffer, &i_buffer))
return VLC_EGENERIC;
h264_sequence_parameter_set_t *p_sps = h264_decode_sps(p_buffer, i_buffer, true);
if( !p_sps )
return VLC_EGENERIC;
if( !p_sps->i_width || !p_sps->i_height )
{
h264_release_sps( p_sps );
return VLC_EGENERIC;
}
if (i_sps_size) if (i_sps_size)
{ {
csd[i_csd_count].p_buf = p_sps_buf; csd[i_csd_count].p_buf = p_sps_buf;
...@@ -292,23 +305,32 @@ static int H264SetCSD(decoder_t *p_dec, void *p_buf, size_t i_size, ...@@ -292,23 +305,32 @@ static int H264SetCSD(decoder_t *p_dec, void *p_buf, size_t i_size,
if (!CSDCmp(p_dec, csd, i_csd_count)) if (!CSDCmp(p_dec, csd, i_csd_count))
{ {
msg_Warn(p_dec, "New SPS/PPS found, id: %d size: %dx%d sps: %d pps: %d", msg_Warn(p_dec, "New SPS/PPS found, id: %d size: %dx%d sps: %d pps: %d",
sps.i_id, sps.i_width, sps.i_height, p_sps->i_id, p_sps->i_width, p_sps->i_height,
i_sps_size, i_pps_size); i_sps_size, i_pps_size);
/* In most use cases, p_sys->p_csd[0] contains a SPS, and /* In most use cases, p_sys->p_csd[0] contains a SPS, and
* p_sys->p_csd[1] contains a PPS */ * p_sys->p_csd[1] contains a PPS */
if (CSDDup(p_dec, csd, i_csd_count)) if (CSDDup(p_dec, csd, i_csd_count))
{
h264_release_sps( p_sps );
return VLC_ENOMEM; return VLC_ENOMEM;
}
if (p_size_changed) if (p_size_changed)
*p_size_changed = (sps.i_width != p_sys->u.video.i_width *p_size_changed = (p_sps->i_width != p_sys->u.video.i_width
|| sps.i_height != p_sys->u.video.i_height); || p_sps->i_height != p_sys->u.video.i_height);
p_sys->u.video.i_width = p_sps->i_width;
p_sys->u.video.i_height = p_sps->i_height;
h264_release_sps( p_sps );
p_sys->u.video.i_width = sps.i_width;
p_sys->u.video.i_height = sps.i_height;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
h264_release_sps( p_sps );
} }
return VLC_EGENERIC; return VLC_EGENERIC;
} }
......
...@@ -704,74 +704,89 @@ static block_t *OutputPicture( decoder_t *p_dec ) ...@@ -704,74 +704,89 @@ static block_t *OutputPicture( decoder_t *p_dec )
static void PutSPS( decoder_t *p_dec, block_t *p_frag ) static void PutSPS( decoder_t *p_dec, block_t *p_frag )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
struct h264_nal_sps sps;
if( h264_parse_sps( p_frag->p_buffer, p_frag->i_buffer, &sps ) != 0 ) const uint8_t *p_buffer = p_frag->p_buffer;
size_t i_buffer = p_frag->i_buffer;
if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
return;
h264_sequence_parameter_set_t *p_sps = h264_decode_sps( p_buffer, i_buffer, true );
if( !p_sps )
{ {
msg_Warn( p_dec, "invalid SPS (sps_id=%d)", sps.i_id ); msg_Warn( p_dec, "invalid SPS (sps_id=%d)", p_sps->i_id );
block_Release( p_frag ); block_Release( p_frag );
return; return;
} }
p_dec->fmt_out.i_profile = sps.i_profile; p_dec->fmt_out.i_profile = p_sps->i_profile;
p_dec->fmt_out.i_level = sps.i_level; p_dec->fmt_out.i_level = p_sps->i_level;
p_dec->fmt_out.video.i_width = sps.i_width; p_dec->fmt_out.video.i_width = p_sps->i_width;
p_dec->fmt_out.video.i_height = sps.i_height; p_dec->fmt_out.video.i_height = p_sps->i_height;
if( sps.vui.i_sar_num != 0 && sps.vui.i_sar_den != 0 ) if( p_sps->vui.i_sar_num != 0 && p_sps->vui.i_sar_den != 0 )
{ {
p_dec->fmt_out.video.i_sar_num = sps.vui.i_sar_num; p_dec->fmt_out.video.i_sar_num = p_sps->vui.i_sar_num;
p_dec->fmt_out.video.i_sar_den = sps.vui.i_sar_den; p_dec->fmt_out.video.i_sar_den = p_sps->vui.i_sar_den;
} }
p_sys->i_log2_max_frame_num = sps.i_log2_max_frame_num; p_sys->i_log2_max_frame_num = p_sps->i_log2_max_frame_num;
p_sys->b_frame_mbs_only = sps.b_frame_mbs_only; p_sys->b_frame_mbs_only = p_sps->b_frame_mbs_only;
p_sys->i_pic_order_cnt_type = sps.i_pic_order_cnt_type; p_sys->i_pic_order_cnt_type = p_sps->i_pic_order_cnt_type;
p_sys->i_delta_pic_order_always_zero_flag = sps.i_delta_pic_order_always_zero_flag; p_sys->i_delta_pic_order_always_zero_flag = p_sps->i_delta_pic_order_always_zero_flag;
p_sys->i_log2_max_pic_order_cnt_lsb = sps.i_log2_max_pic_order_cnt_lsb; p_sys->i_log2_max_pic_order_cnt_lsb = p_sps->i_log2_max_pic_order_cnt_lsb;
if( sps.vui.b_valid ) if( p_sps->vui.b_valid )
{ {
p_sys->b_timing_info_present_flag = sps.vui.b_timing_info_present_flag; p_sys->b_timing_info_present_flag = p_sps->vui.b_timing_info_present_flag;
p_sys->i_num_units_in_tick = sps.vui.i_num_units_in_tick; p_sys->i_num_units_in_tick = p_sps->vui.i_num_units_in_tick;
p_sys->i_time_scale = sps.vui.i_time_scale; p_sys->i_time_scale = p_sps->vui.i_time_scale;
p_sys->b_fixed_frame_rate = sps.vui.b_fixed_frame_rate; p_sys->b_fixed_frame_rate = p_sps->vui.b_fixed_frame_rate;
p_sys->b_pic_struct_present_flag = sps.vui.b_pic_struct_present_flag; p_sys->b_pic_struct_present_flag = p_sps->vui.b_pic_struct_present_flag;
p_sys->b_cpb_dpb_delays_present_flag = sps.vui.b_cpb_dpb_delays_present_flag; p_sys->b_cpb_dpb_delays_present_flag = p_sps->vui.b_cpb_dpb_delays_present_flag;
p_sys->i_cpb_removal_delay_length_minus1 = sps.vui.i_cpb_removal_delay_length_minus1; p_sys->i_cpb_removal_delay_length_minus1 = p_sps->vui.i_cpb_removal_delay_length_minus1;
p_sys->i_dpb_output_delay_length_minus1 = sps.vui.i_dpb_output_delay_length_minus1; p_sys->i_dpb_output_delay_length_minus1 = p_sps->vui.i_dpb_output_delay_length_minus1;
} }
/* We have a new SPS */ /* We have a new SPS */
if( !p_sys->b_sps ) if( !p_sys->b_sps )
msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", sps.i_id ); msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", p_sps->i_id );
p_sys->b_sps = true; p_sys->b_sps = true;
if( p_sys->pp_sps[sps.i_id] ) if( p_sys->pp_sps[p_sps->i_id] )
block_Release( p_sys->pp_sps[sps.i_id] ); block_Release( p_sys->pp_sps[p_sps->i_id] );
p_sys->pp_sps[sps.i_id] = p_frag; p_sys->pp_sps[p_sps->i_id] = p_frag;
h264_release_sps( p_sps );
} }
static void PutPPS( decoder_t *p_dec, block_t *p_frag ) static void PutPPS( decoder_t *p_dec, block_t *p_frag )
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
struct h264_nal_pps pps; const uint8_t *p_buffer = p_frag->p_buffer;
size_t i_buffer = p_frag->i_buffer;
if( h264_parse_pps( p_frag->p_buffer, p_frag->i_buffer, &pps ) != 0 ) if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
return;
h264_picture_parameter_set_t *p_pps = h264_decode_pps( p_buffer, i_buffer, true );
if( !p_pps )
{ {
msg_Warn( p_dec, "invalid PPS (pps_id=%d sps_id=%d)", pps.i_id, pps.i_sps_id ); msg_Warn( p_dec, "invalid PPS (pps_id=%d sps_id=%d)", p_pps->i_id, p_pps->i_sps_id );
block_Release( p_frag ); block_Release( p_frag );
return; return;
} }
p_sys->i_pic_order_present_flag = pps.i_pic_order_present_flag; p_sys->i_pic_order_present_flag = p_pps->i_pic_order_present_flag;
/* We have a new PPS */ /* We have a new PPS */
if( !p_sys->b_pps ) if( !p_sys->b_pps )
msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", pps.i_id, pps.i_sps_id ); msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", p_pps->i_id, p_pps->i_sps_id );
p_sys->b_pps = true; p_sys->b_pps = true;
if( p_sys->pp_pps[pps.i_id] ) if( p_sys->pp_pps[p_pps->i_id] )
block_Release( p_sys->pp_pps[pps.i_id] ); block_Release( p_sys->pp_pps[p_pps->i_id] );
p_sys->pp_pps[pps.i_id] = p_frag; p_sys->pp_pps[p_pps->i_id] = p_frag;
h264_release_pps( p_pps );
} }
static bool ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice, static bool ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
......
...@@ -399,30 +399,24 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf, ...@@ -399,30 +399,24 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
return 0; return 0;
} }
int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, void h264_release_sps( h264_sequence_parameter_set_t *p_sps )
struct h264_nal_sps *p_sps )
{ {
bs_t s; free( p_sps );
int i_tmp; }
if (i_sps_size < 5 || (p_sps_buf[4] & 0x1f) != H264_NAL_SPS)
return -1;
memset( p_sps, 0, sizeof(struct h264_nal_sps) );
bs_init( &s, &p_sps_buf[5], i_sps_size - 5 ); static bool h264_parse_sequence_parameter_set_rbsp( bs_t *p_bs,
unsigned i_bitflow = 0; h264_sequence_parameter_set_t *p_sps )
s.p_fwpriv = &i_bitflow; {
s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ int i_tmp;
int i_profile_idc = bs_read( &s, 8 ); int i_profile_idc = bs_read( p_bs, 8 );
p_sps->i_profile = i_profile_idc; p_sps->i_profile = i_profile_idc;
p_sps->i_profile_compatibility = bs_read( &s, 8 ); p_sps->i_profile_compatibility = bs_read( p_bs, 8 );
p_sps->i_level = bs_read( &s, 8 ); p_sps->i_level = bs_read( p_bs, 8 );
/* sps id */ /* sps id */
p_sps->i_id = bs_read_ue( &s ); p_sps->i_id = bs_read_ue( p_bs );
if( p_sps->i_id >= H264_SPS_MAX ) if( p_sps->i_id >= H264_SPS_MAX )
return -1; return false;
if( i_profile_idc == PROFILE_H264_HIGH || if( i_profile_idc == PROFILE_H264_HIGH ||
i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_10 ||
...@@ -439,23 +433,23 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -439,23 +433,23 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
i_profile_idc == PROFILE_H264_MFC_HIGH ) i_profile_idc == PROFILE_H264_MFC_HIGH )
{ {
/* chroma_format_idc */ /* chroma_format_idc */
const int i_chroma_format_idc = bs_read_ue( &s ); const int i_chroma_format_idc = bs_read_ue( p_bs );
if( i_chroma_format_idc == 3 ) if( i_chroma_format_idc == 3 )
bs_skip( &s, 1 ); /* separate_colour_plane_flag */ bs_skip( p_bs, 1 ); /* separate_colour_plane_flag */
/* bit_depth_luma_minus8 */ /* bit_depth_luma_minus8 */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* bit_depth_chroma_minus8 */ /* bit_depth_chroma_minus8 */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* qpprime_y_zero_transform_bypass_flag */ /* qpprime_y_zero_transform_bypass_flag */
bs_skip( &s, 1 ); bs_skip( p_bs, 1 );
/* seq_scaling_matrix_present_flag */ /* seq_scaling_matrix_present_flag */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ ) for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ )
{ {
/* seq_scaling_list_present_flag[i] */ /* seq_scaling_list_present_flag[i] */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( !i_tmp ) if( !i_tmp )
continue; continue;
const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64;
...@@ -467,7 +461,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -467,7 +461,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
if( i_nextscale != 0 ) if( i_nextscale != 0 )
{ {
/* delta_scale */ /* delta_scale */
i_tmp = bs_read_se( &s ); i_tmp = bs_read_se( p_bs );
i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256;
/* useDefaultScalingMatrixFlag = ... */ /* useDefaultScalingMatrixFlag = ... */
} }
...@@ -479,15 +473,15 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -479,15 +473,15 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
} }
/* Skip i_log2_max_frame_num */ /* Skip i_log2_max_frame_num */
p_sps->i_log2_max_frame_num = bs_read_ue( &s ); p_sps->i_log2_max_frame_num = bs_read_ue( p_bs );
if( p_sps->i_log2_max_frame_num > 12) if( p_sps->i_log2_max_frame_num > 12)
p_sps->i_log2_max_frame_num = 12; p_sps->i_log2_max_frame_num = 12;
/* Read poc_type */ /* Read poc_type */
p_sps->i_pic_order_cnt_type = bs_read_ue( &s ); p_sps->i_pic_order_cnt_type = bs_read_ue( p_bs );
if( p_sps->i_pic_order_cnt_type == 0 ) if( p_sps->i_pic_order_cnt_type == 0 )
{ {
/* skip i_log2_max_poc_lsb */ /* skip i_log2_max_poc_lsb */
p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( p_bs );
if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 )
p_sps->i_log2_max_pic_order_cnt_lsb = 12; p_sps->i_log2_max_pic_order_cnt_lsb = 12;
} }
...@@ -495,61 +489,61 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -495,61 +489,61 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
{ {
int i_cycle; int i_cycle;
/* skip b_delta_pic_order_always_zero */ /* skip b_delta_pic_order_always_zero */
p_sps->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 ); p_sps->i_delta_pic_order_always_zero_flag = bs_read( p_bs, 1 );
/* skip i_offset_for_non_ref_pic */ /* skip i_offset_for_non_ref_pic */
bs_read_se( &s ); bs_read_se( p_bs );
/* skip i_offset_for_top_to_bottom_field */ /* skip i_offset_for_top_to_bottom_field */
bs_read_se( &s ); bs_read_se( p_bs );
/* read i_num_ref_frames_in_poc_cycle */ /* read i_num_ref_frames_in_poc_cycle */
i_cycle = bs_read_ue( &s ); i_cycle = bs_read_ue( p_bs );
if( i_cycle > 256 ) i_cycle = 256; if( i_cycle > 256 ) i_cycle = 256;
while( i_cycle > 0 ) while( i_cycle > 0 )
{ {
/* skip i_offset_for_ref_frame */ /* skip i_offset_for_ref_frame */
bs_read_se(&s ); bs_read_se(p_bs );
i_cycle--; i_cycle--;
} }
} }
/* i_num_ref_frames */ /* i_num_ref_frames */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* b_gaps_in_frame_num_value_allowed */ /* b_gaps_in_frame_num_value_allowed */
bs_skip( &s, 1 ); bs_skip( p_bs, 1 );
/* Read size */ /* Read size */
p_sps->i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_sps->i_width = 16 * ( bs_read_ue( p_bs ) + 1 );
p_sps->i_height = 16 * ( bs_read_ue( &s ) + 1 ); p_sps->i_height = 16 * ( bs_read_ue( p_bs ) + 1 );
/* b_frame_mbs_only */ /* b_frame_mbs_only */
p_sps->b_frame_mbs_only = bs_read( &s, 1 ); p_sps->b_frame_mbs_only = bs_read( p_bs, 1 );
p_sps->i_height *= ( 2 - p_sps->b_frame_mbs_only ); p_sps->i_height *= ( 2 - p_sps->b_frame_mbs_only );
if( p_sps->b_frame_mbs_only == 0 ) if( p_sps->b_frame_mbs_only == 0 )
{ {
bs_skip( &s, 1 ); bs_skip( p_bs, 1 );
} }
/* b_direct8x8_inference */ /* b_direct8x8_inference */
bs_skip( &s, 1 ); bs_skip( p_bs, 1 );
/* crop */ /* crop */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
/* left */ /* left */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* right */ /* right */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* top */ /* top */
bs_read_ue( &s ); bs_read_ue( p_bs );
/* bottom */ /* bottom */
bs_read_ue( &s ); bs_read_ue( p_bs );
} }
/* vui */ /* vui */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
p_sps->vui.b_valid = true; p_sps->vui.b_valid = true;
/* read the aspect ratio part if any */ /* read the aspect ratio part if any */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
static const struct { int w, h; } sar[17] = static const struct { int w, h; } sar[17] =
...@@ -560,7 +554,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -560,7 +554,7 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
{ 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 },
{ 2, 1 }, { 2, 1 },
}; };
int i_sar = bs_read( &s, 8 ); int i_sar = bs_read( p_bs, 8 );
int w, h; int w, h;
if( i_sar < 17 ) if( i_sar < 17 )
...@@ -570,8 +564,8 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -570,8 +564,8 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
} }
else if( i_sar == 255 ) else if( i_sar == 255 )
{ {
w = bs_read( &s, 16 ); w = bs_read( p_bs, 16 );
h = bs_read( &s, 16 ); h = bs_read( p_bs, 16 );
} }
else else
{ {
...@@ -592,97 +586,125 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, ...@@ -592,97 +586,125 @@ int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
} }
/* overscan */ /* overscan */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if ( i_tmp ) if ( i_tmp )
bs_read( &s, 1 ); bs_read( p_bs, 1 );
/* video signal type */ /* video signal type */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
bs_read( &s, 4 ); bs_read( p_bs, 4 );
/* colour desc */ /* colour desc */
bs_read( &s, 1 ); bs_read( p_bs, 1 );
if ( i_tmp ) if ( i_tmp )
bs_read( &s, 24 ); bs_read( p_bs, 24 );
} }
/* chroma loc info */ /* chroma loc info */
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
bs_read_ue( &s ); bs_read_ue( p_bs );
bs_read_ue( &s ); bs_read_ue( p_bs );
} }
/* timing info */ /* timing info */
p_sps->vui.b_timing_info_present_flag = bs_read( &s, 1 ); p_sps->vui.b_timing_info_present_flag = bs_read( p_bs, 1 );
if( p_sps->vui.b_timing_info_present_flag ) if( p_sps->vui.b_timing_info_present_flag )
{ {
p_sps->vui.i_num_units_in_tick = bs_read( &s, 32 ); p_sps->vui.i_num_units_in_tick = bs_read( p_bs, 32 );
p_sps->vui.i_time_scale = bs_read( &s, 32 ); p_sps->vui.i_time_scale = bs_read( p_bs, 32 );
p_sps->vui.b_fixed_frame_rate = bs_read( &s, 1 ); p_sps->vui.b_fixed_frame_rate = bs_read( p_bs, 1 );
} }
/* Nal hrd & VC1 hrd parameters */ /* Nal hrd & VC1 hrd parameters */
p_sps->vui.b_cpb_dpb_delays_present_flag = false; p_sps->vui.b_cpb_dpb_delays_present_flag = false;
for ( int i=0; i<2; i++ ) for ( int i=0; i<2; i++ )
{ {
i_tmp = bs_read( &s, 1 ); i_tmp = bs_read( p_bs, 1 );
if( i_tmp ) if( i_tmp )
{ {
p_sps->vui.b_cpb_dpb_delays_present_flag = true; p_sps->vui.b_cpb_dpb_delays_present_flag = true;
uint32_t count = bs_read_ue( &s ) + 1; uint32_t count = bs_read_ue( p_bs ) + 1;
bs_read( &s, 4 ); bs_read( p_bs, 4 );
bs_read( &s, 4 ); bs_read( p_bs, 4 );
for( uint32_t i=0; i<count; i++ ) for( uint32_t i=0; i<count; i++ )
{ {
bs_read_ue( &s ); bs_read_ue( p_bs );
bs_read_ue( &s ); bs_read_ue( p_bs );
bs_read( &s, 1 ); bs_read( p_bs, 1 );
} }
bs_read( &s, 5 ); bs_read( p_bs, 5 );
p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( &s, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( p_bs, 5 );
p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( &s, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( p_bs, 5 );
bs_read( &s, 5 ); bs_read( p_bs, 5 );
} }
} }
if( p_sps->vui.b_cpb_dpb_delays_present_flag ) if( p_sps->vui.b_cpb_dpb_delays_present_flag )
bs_read( &s, 1 ); bs_read( p_bs, 1 );
/* pic struct info */ /* pic struct info */
p_sps->vui.b_pic_struct_present_flag = bs_read( &s, 1 ); p_sps->vui.b_pic_struct_present_flag = bs_read( p_bs, 1 );
/* + unparsed remains */ /* + unparsed remains */
} }
return 0; return true;
} }
int h264_parse_pps( const uint8_t *p_pps_buf, int i_pps_size, void h264_release_pps( h264_picture_parameter_set_t *p_pps )
struct h264_nal_pps *p_pps )
{ {
bs_t s; free( p_pps );
}
if (i_pps_size < 5 || (p_pps_buf[4] & 0x1f) != H264_NAL_PPS)
return -1;
memset( p_pps, 0, sizeof(struct h264_nal_pps) ); static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs,
bs_init( &s, &p_pps_buf[5], i_pps_size - 5 ); h264_picture_parameter_set_t *p_pps )
p_pps->i_id = bs_read_ue( &s ); // pps id {
p_pps->i_sps_id = bs_read_ue( &s ); // sps id p_pps->i_id = bs_read_ue( p_bs ); // pps id
p_pps->i_sps_id = bs_read_ue( p_bs ); // sps id
if( p_pps->i_id >= H264_PPS_MAX || p_pps->i_sps_id >= H264_SPS_MAX ) if( p_pps->i_id >= H264_PPS_MAX || p_pps->i_sps_id >= H264_SPS_MAX )
{ return false;
return -1;
} bs_skip( p_bs, 1 ); // entropy coding mode flag
bs_skip( &s, 1 ); // entropy coding mode flag p_pps->i_pic_order_present_flag = bs_read( p_bs, 1 );
p_pps->i_pic_order_present_flag = bs_read( &s, 1 );
/* TODO */ /* TODO */
return 0; return true;
} }
#define IMPL_h264_generic_decode( name, h264type, decode, release ) \
h264type * name( const uint8_t *p_buf, size_t i_buf, bool b_escaped ) \
{ \
h264type *p_h264type = calloc(1, sizeof(h264type)); \
if(likely(p_h264type)) \
{ \
bs_t bs; \
bs_init( &bs, p_buf, i_buf ); \
unsigned i_bitflow = 0; \
if( b_escaped ) \
{ \
bs.p_fwpriv = &i_bitflow; \
bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ \
} \
else (void) i_bitflow;\
bs_skip( &bs, 8 ); /* Skip nal_unit_header */ \
if( !decode( &bs, p_h264type ) ) \
{ \
release( p_h264type ); \
p_h264type = NULL; \
} \
} \
return p_h264type; \
}
IMPL_h264_generic_decode( h264_decode_sps, h264_sequence_parameter_set_t,
h264_parse_sequence_parameter_set_rbsp, h264_release_sps )
IMPL_h264_generic_decode( h264_decode_pps, h264_picture_parameter_set_t,
h264_parse_picture_parameter_set_rbsp, h264_release_pps )
block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size, block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size,
const uint8_t *p_sps_buf, const uint8_t *p_sps_buf,
size_t i_sps_size, size_t i_sps_size,
......
...@@ -72,7 +72,16 @@ enum h264_sei_type_e ...@@ -72,7 +72,16 @@ enum h264_sei_type_e
H264_SEI_RECOVERY_POINT = 6 H264_SEI_RECOVERY_POINT = 6
}; };
struct h264_nal_sps typedef struct h264_sequence_parameter_set_t h264_sequence_parameter_set_t;
typedef struct h264_picture_parameter_set_t h264_picture_parameter_set_t;
h264_sequence_parameter_set_t * h264_decode_sps( const uint8_t *, size_t, bool );
h264_picture_parameter_set_t * h264_decode_pps( const uint8_t *, size_t, bool );
void h264_release_sps( h264_sequence_parameter_set_t * );
void h264_release_pps( h264_picture_parameter_set_t * );
struct h264_sequence_parameter_set_t
{ {
int i_id; int i_id;
int i_profile, i_profile_compatibility, i_level; int i_profile, i_profile_compatibility, i_level;
...@@ -97,7 +106,7 @@ struct h264_nal_sps ...@@ -97,7 +106,7 @@ struct h264_nal_sps
} vui; } vui;
}; };
struct h264_nal_pps struct h264_picture_parameter_set_t
{ {
int i_id; int i_id;
int i_sps_id; int i_sps_id;
...@@ -130,16 +139,6 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf, ...@@ -130,16 +139,6 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
uint8_t **pp_sps, size_t *p_sps_size, uint8_t **pp_sps, size_t *p_sps_size,
uint8_t **pp_pps, size_t *p_pps_size ); uint8_t **pp_pps, size_t *p_pps_size );
/* Parse a SPS into the struct nal_sps
* Returns 0 in case of success */
int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
struct h264_nal_sps *p_sps );
/* Parse a PPS into the struct nal_pps
* Returns 0 in case of success */
int h264_parse_pps( const uint8_t *p_pps_buf, int i_pps_size,
struct h264_nal_pps *p_pps );
/* Create a AVCDecoderConfigurationRecord from SPS/PPS /* Create a AVCDecoderConfigurationRecord from SPS/PPS
* Returns a valid block_t on success, must be freed with block_Release */ * Returns a valid block_t on success, must be freed with block_Release */
block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size, block_t *h264_AnnexB_NAL_to_avcC( uint8_t i_nal_length_size,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment