nengel@2: #include "h264_types.h" nengel@2: #include "h264_data.h" nengel@2: nengel@2: #include "golomb.h" nengel@2: #include "h264_sei.h" nengel@2: #include "h264_refs.h" nengel@2: #include "h264_ps.h" nengel@2: #include "h264_pred_mode.h" nengel@2: #include "h264_misc.h" nengel@2: nengel@2: static int ff_h264_decode_rbsp_trailing(const uint8_t *src){ nengel@2: int v= *src; nengel@2: int r; nengel@2: nengel@2: for(r=1; r<9; r++){ nengel@2: if(v&1) return r; nengel@2: v>>=1; nengel@2: } nengel@2: return 0; nengel@2: } nengel@2: nengel@2: static int pred_weight_table(H264Slice *s, GetBitContext *gb){ nengel@2: int luma_def, chroma_def; nengel@2: nengel@2: s->use_weight= 0; nengel@2: s->use_weight_chroma= 0; nengel@2: s->luma_log2_weight_denom= get_ue_golomb(gb); nengel@2: s->chroma_log2_weight_denom= get_ue_golomb(gb); nengel@2: luma_def = 1<luma_log2_weight_denom; nengel@2: chroma_def = 1<chroma_log2_weight_denom; nengel@2: nengel@2: for(int list=0; list<2; list++){ nengel@2: for(int i=0; iref_count[list]; i++){ nengel@2: int luma_weight_flag, chroma_weight_flag; nengel@2: nengel@2: luma_weight_flag= get_bits1(gb); nengel@2: if(luma_weight_flag){ nengel@2: s->luma_weight[i][list][0]= get_se_golomb(gb); nengel@2: s->luma_weight[i][list][1]= get_se_golomb(gb); nengel@2: if( s->luma_weight[i][list][0] != luma_def nengel@2: || s->luma_weight[i][list][1] != 0) { nengel@2: s->use_weight= 1; nengel@2: } nengel@2: }else{ nengel@2: s->luma_weight[i][list][0]= luma_def; nengel@2: s->luma_weight[i][list][1]= 0; nengel@2: } nengel@2: nengel@2: chroma_weight_flag= get_bits1(gb); nengel@2: if(chroma_weight_flag){ nengel@2: int j; nengel@2: for(j=0; j<2; j++){ nengel@2: s->chroma_weight[i][list][j][0]= get_se_golomb(gb); nengel@2: s->chroma_weight[i][list][j][1]= get_se_golomb(gb); nengel@2: if( s->chroma_weight[i][list][j][0] != chroma_def nengel@2: || s->chroma_weight[i][list][j][1] != 0) { nengel@2: s->use_weight_chroma= 1; nengel@2: } nengel@2: } nengel@2: }else{ nengel@2: int j; nengel@2: for(j=0; j<2; j++){ nengel@2: s->chroma_weight[i][list][j][0]= chroma_def; nengel@2: s->chroma_weight[i][list][j][1]= 0; nengel@2: } nengel@2: } nengel@2: } nengel@2: if(s->slice_type_nos != FF_B_TYPE) break; nengel@2: } nengel@2: s->use_weight= s->use_weight || s->use_weight_chroma; nengel@2: return 0; nengel@2: } nengel@2: nengel@2: /** nengel@2: * Initialize implicit_weight table. nengel@2: */ nengel@2: static void implicit_weight_table(H264Slice *s){ nengel@2: int ref0, ref1, cur_poc, ref_start, ref_count0, ref_count1; nengel@2: nengel@2: cur_poc = s->poc; nengel@2: if( s->ref_count[0] == 1 && s->ref_count[1] == 1 && s->ref_list[0][0]->poc + s->ref_list[1][0]->poc == 2*cur_poc){ nengel@2: s->use_weight= 0; nengel@2: s->use_weight_chroma= 0; nengel@2: return; nengel@2: } nengel@2: ref_start= 0; nengel@2: ref_count0= s->ref_count[0]; nengel@2: ref_count1= s->ref_count[1]; nengel@2: nengel@2: s->use_weight= 2; nengel@2: s->use_weight_chroma= 2; nengel@2: s->luma_log2_weight_denom= 5; nengel@2: s->chroma_log2_weight_denom= 5; nengel@2: nengel@2: for(ref0=ref_start; ref0 < ref_count0; ref0++){ nengel@2: int poc0 = s->ref_list[0][ref0]->poc; nengel@2: for(ref1=ref_start; ref1 < ref_count1; ref1++){ nengel@2: int poc1 = s->ref_list[1][ref1]->poc; nengel@2: int td = av_clip(poc1 - poc0, -128, 127); nengel@2: int w= 32; nengel@2: if(td){ nengel@2: int tb = av_clip(cur_poc - poc0, -128, 127); nengel@2: int tx = (16384 + (FFABS(td) >> 1)) / td; nengel@2: int dist_scale_factor = (tb*tx + 32) >> 8; nengel@2: if(dist_scale_factor >= -64 && dist_scale_factor <= 128) nengel@2: w = 64 - dist_scale_factor; nengel@2: } nengel@2: s->implicit_weight[ref0][ref1][0]= nengel@2: s->implicit_weight[ref0][ref1][1]= w; nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@2: /** nengel@2: * instantaneous decoder refresh. nengel@2: */ nengel@2: static void idr(NalContext *n, H264Slice *s){ nengel@2: ff_h264_remove_all_refs(n, s); nengel@2: n->prev_frame_num= 0; nengel@2: n->prev_frame_num_offset= 0; nengel@2: n->poc_offset += (n->prev_poc_msb<<16) + n->prev_poc_lsb; nengel@2: n->prev_poc_msb= nengel@2: n->prev_poc_lsb= 0; nengel@2: } nengel@2: nengel@2: static int init_poc(NalContext *n, H264Slice *s, GetBitContext *gb){ nengel@2: const int max_frame_num= 1<sps.log2_max_frame_num; nengel@2: int frame_poc; nengel@2: nengel@2: if(n->sps.poc_type==0){ nengel@2: n->poc_lsb= get_bits(gb, n->sps.log2_max_poc_lsb); nengel@2: } nengel@2: nengel@2: if(n->sps.poc_type==1 && !n->sps.delta_pic_order_always_zero_flag){ nengel@2: n->delta_poc= get_se_golomb(gb); nengel@2: } nengel@2: nengel@2: n->frame_num_offset= n->prev_frame_num_offset; nengel@2: if(n->frame_num < n->prev_frame_num) nengel@2: n->frame_num_offset += max_frame_num; nengel@2: nengel@2: if(n->sps.poc_type==0){ nengel@2: const int max_poc_lsb= 1<sps.log2_max_poc_lsb; nengel@2: nengel@2: if(n->poc_lsb < n->prev_poc_lsb && n->prev_poc_lsb - n->poc_lsb >= max_poc_lsb/2) nengel@2: n->poc_msb = n->prev_poc_msb + max_poc_lsb; nengel@2: else if(n->poc_lsb > n->prev_poc_lsb && n->prev_poc_lsb - n->poc_lsb < -max_poc_lsb/2) nengel@2: n->poc_msb = n->prev_poc_msb - max_poc_lsb; nengel@2: else nengel@2: n->poc_msb = n->prev_poc_msb; nengel@2: nengel@2: frame_poc = n->poc_msb + n->poc_lsb; nengel@2: }else if(n->sps.poc_type==1){ nengel@2: int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc; nengel@2: int i; nengel@2: nengel@2: if(n->sps.poc_cycle_length != 0) nengel@2: abs_frame_num = n->frame_num_offset + n->frame_num; nengel@2: else nengel@2: abs_frame_num = 0; nengel@2: nengel@2: if(s->nal_ref_idc==0 && abs_frame_num > 0) nengel@2: abs_frame_num--; nengel@2: nengel@2: expected_delta_per_poc_cycle = 0; nengel@2: for(i=0; i < n->sps.poc_cycle_length; i++) nengel@2: expected_delta_per_poc_cycle += n->sps.offset_for_ref_frame[ i ]; //FIXME integrate during sps parse nengel@2: nengel@2: if(abs_frame_num > 0){ nengel@2: int poc_cycle_cnt = (abs_frame_num - 1) / n->sps.poc_cycle_length; nengel@2: int frame_num_in_poc_cycle = (abs_frame_num - 1) % n->sps.poc_cycle_length; nengel@2: nengel@2: expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle; nengel@2: for(i = 0; i <= frame_num_in_poc_cycle; i++) nengel@2: expectedpoc = expectedpoc + n->sps.offset_for_ref_frame[ i ]; nengel@2: } else nengel@2: expectedpoc = 0; nengel@2: if(s->nal_ref_idc == 0) nengel@2: expectedpoc = expectedpoc + n->sps.offset_for_non_ref_pic; nengel@2: frame_poc = expectedpoc + n->delta_poc; nengel@2: }else{ nengel@2: int poc= 2*(n->frame_num_offset + n->frame_num); nengel@2: if(!s->nal_ref_idc) nengel@2: poc--; nengel@2: frame_poc= poc; nengel@2: } nengel@2: s->current_picture_info->poc= s->poc = frame_poc + n->poc_offset; nengel@2: s->coded_pic_num = n->coded_pic_num++; nengel@2: nengel@2: return 0; nengel@2: } nengel@2: nengel@2: static void ref2frame(NalContext *n, H264Slice *s){ nengel@2: for(int j=0; jlist_count; j++){ nengel@2: int *ref2frm= s->ref2frm[j]; nengel@2: nengel@2: ref2frm[0]= nengel@2: ref2frm[1]= -1; nengel@2: nengel@2: for(int i=0; iref_count[j]; i++){ nengel@2: ref2frm[i+2]= 15; nengel@2: if(s->ref_list[j][i]->cpn >=0){ nengel@2: int k; nengel@2: for(k=0; kshort_ref_count; k++){ nengel@2: if(n->short_ref[k]->cpn == s->ref_list[j][i]->cpn){ nengel@2: ref2frm[i+2]= k; nengel@2: break; nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@2: /** nengel@2: * decodes a slice header. nengel@2: * This will also call MPV_common_init() and frame_start() as needed. nengel@2: * nengel@2: * @param h h264context nengel@2: * @param h0 h264 master context (differs from 'h' when doing sliced based parallel decoding) nengel@2: * nengel@2: * @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded nengel@2: */ nengel@2: static int decode_slice_header(NalContext *n, H264Slice *s, GetBitContext *gb){ nengel@2: unsigned int first_mb_in_slice; nengel@2: unsigned int pps_id; nengel@2: int num_ref_idx_active_override_flag; nengel@2: unsigned int slice_type, tmp; nengel@2: nengel@2: first_mb_in_slice= get_ue_golomb(gb); nengel@2: (void) first_mb_in_slice; nengel@2: nengel@2: slice_type= get_ue_golomb_31(gb); nengel@2: if(slice_type > 9){ nengel@2: av_log(AV_LOG_ERROR, "slice type too large (%d)\n", s->slice_type); nengel@2: return -1; nengel@2: } nengel@2: if(slice_type > 4) nengel@2: slice_type -= 5; nengel@2: nengel@2: slice_type= golomb_to_pict_type[ slice_type ]; nengel@2: nengel@2: s->slice_type= slice_type; nengel@2: s->slice_type_nos= slice_type & 3; nengel@2: s->current_picture_info->slice_type_nos = s->slice_type_nos; nengel@2: s->current_picture_info->reference= s->nal_ref_idc? 2:0; nengel@2: s->key_frame = s->slice_type == FF_I_TYPE; nengel@2: nengel@2: pps_id= get_ue_golomb(gb); nengel@2: nengel@2: if(pps_id>=MAX_PPS_COUNT){ nengel@2: av_log(AV_LOG_ERROR, "pps_id out of range\n"); nengel@2: return -1; nengel@2: } nengel@2: if(!n->pps_buffers[pps_id]) { nengel@2: av_log(AV_LOG_ERROR, "non-existing PPS %u referenced\n", pps_id); nengel@2: return -1; nengel@2: } nengel@2: s->pps= *n->pps_buffers[pps_id]; nengel@2: nengel@2: if(!n->sps_buffers[s->pps.sps_id]) { nengel@2: av_log(AV_LOG_ERROR, "non-existing SPS %u referenced\n", s->pps.sps_id); nengel@2: return -1; nengel@2: } nengel@2: n->sps = *n->sps_buffers[s->pps.sps_id]; nengel@2: nengel@2: n->mb_width= n->sps.mb_width; nengel@2: n->mb_height= n->sps.mb_height; nengel@2: nengel@2: int chroma444 = (n->sps.chroma_format_idc == 3); nengel@2: n->width = 16*n->mb_width - (2>>chroma444)*FFMIN(n->sps.crop_right, (8<sps.frame_mbs_only_flag) nengel@2: n->height= 16*n->mb_height - (2>>chroma444)*FFMIN(n->sps.crop_bottom, (8<height= 16*n->mb_height - (4>>chroma444)*FFMIN(n->sps.crop_bottom, (8<direct_8x8_inference_flag = n->sps.direct_8x8_inference_flag; nengel@2: s->transform_bypass = n->sps.transform_bypass; nengel@2: nengel@2: n->frame_num= get_bits(gb, n->sps.log2_max_frame_num); nengel@2: if(n->frame_num != n->prev_frame_num && n->frame_num != (n->prev_frame_num+1)%(1<sps.log2_max_frame_num)){ nengel@2: av_log(AV_LOG_ERROR, "unexpected frame_num \n"); nengel@2: } nengel@2: nengel@2: s->current_picture_info->frame_num= n->frame_num; //FIXME frame_num cleanup nengel@2: n->max_pic_num= 1<< n->sps.log2_max_frame_num; nengel@2: nengel@2: if(s->nal_unit_type == NAL_IDR_SLICE){ nengel@2: get_ue_golomb(gb); /* idr_pic_id */ nengel@2: } nengel@2: nengel@2: init_poc(n, s, gb); nengel@2: nengel@2: if(s->pps.redundant_pic_cnt_present){ nengel@2: n->redundant_pic_count= get_ue_golomb(gb); nengel@2: } nengel@2: nengel@2: //set defaults, might be overridden a few lines later nengel@2: s->ref_count[0]= s->pps.ref_count[0]; nengel@2: s->ref_count[1]= s->pps.ref_count[1]; nengel@2: nengel@2: if(s->slice_type_nos != FF_I_TYPE){ nengel@2: if(s->slice_type_nos == FF_B_TYPE){ nengel@2: s->direct_spatial_mv_pred= get_bits1(gb); nengel@2: } nengel@2: num_ref_idx_active_override_flag= get_bits1(gb); nengel@2: nengel@2: if(num_ref_idx_active_override_flag){ nengel@2: s->ref_count[0]= get_ue_golomb(gb) + 1; nengel@2: if(s->slice_type_nos==FF_B_TYPE) nengel@2: s->ref_count[1]= get_ue_golomb(gb) + 1; nengel@2: nengel@2: if(s->ref_count[0]-1 > 32-1 || s->ref_count[1]-1 > 32-1){ nengel@2: av_log(AV_LOG_ERROR, "reference overflow\n"); nengel@2: s->ref_count[0]= s->ref_count[1]= 1; nengel@2: return -1; nengel@2: } nengel@2: } nengel@2: if(s->slice_type_nos == FF_B_TYPE) nengel@2: s->list_count= 2; nengel@2: else nengel@2: s->list_count= 1; nengel@2: }else nengel@2: s->list_count= 0; nengel@2: nengel@2: nengel@2: if(s->slice_type_nos!=FF_I_TYPE){ nengel@2: ff_h264_fill_default_ref_list(n, s); nengel@2: ff_h264_decode_ref_pic_list_reordering(n, s, gb); nengel@2: ref2frame(n, s); nengel@2: nengel@2: for(int i=0; i<2; i++){ nengel@2: for(int j=0; jref_count[i]; j++){ nengel@2: if (s->ref_list[i][j]==NULL || s->ref_list[i][j]->reference < 2) // Don't know why sometimes the ref_count=1 while there are no references nengel@2: s->ref_list_cpn[i][j] = -1; nengel@2: else nengel@2: s->ref_list_cpn[i][j] = s->ref_list[i][j]->cpn; nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@2: if( (s->pps.weighted_pred && s->slice_type_nos == FF_P_TYPE ) nengel@2: || (s->pps.weighted_bipred_idc==1 && s->slice_type_nos== FF_B_TYPE ) ){ nengel@2: pred_weight_table(s, gb); nengel@2: } nengel@2: else if(s->pps.weighted_bipred_idc==2 && s->slice_type_nos== FF_B_TYPE){ nengel@2: implicit_weight_table( s); nengel@2: }else { nengel@2: s->use_weight = 0; nengel@2: } nengel@2: nengel@2: if(s->nal_ref_idc){ nengel@2: ff_h264_ref_pic_marking(n, s, gb); nengel@2: n->prev_poc_msb= n->poc_msb; nengel@2: n->prev_poc_lsb= n->poc_lsb; nengel@2: } nengel@2: nengel@2: n->prev_frame_num_offset= n->frame_num_offset; nengel@2: n->prev_frame_num= n->frame_num; nengel@2: nengel@2: if(s->slice_type_nos != FF_B_TYPE){ nengel@2: s->ip_id= n->ip_id++; nengel@2: } nengel@2: nengel@2: if(s->slice_type_nos==FF_B_TYPE && !s->direct_spatial_mv_pred){ nengel@2: ff_h264_direct_dist_scale_factor(s); nengel@2: } nengel@2: ff_h264_direct_ref_list_init(s); nengel@2: nengel@2: nengel@2: if( s->slice_type_nos != FF_I_TYPE && s->pps.cabac ){ nengel@2: tmp = get_ue_golomb_31(gb); nengel@2: if(tmp > 2){ nengel@2: av_log(AV_LOG_ERROR, "cabac_init_idc overflow\n"); nengel@2: return -1; nengel@2: } nengel@2: s->cabac_init_idc= tmp; nengel@2: } nengel@2: nengel@2: tmp = s->pps.init_qp + get_se_golomb(gb); nengel@2: if(tmp>51){ nengel@2: av_log(AV_LOG_ERROR, "QP %u out of range\n", tmp); nengel@2: return -1; nengel@2: } nengel@2: s->qscale= tmp; nengel@2: nengel@2: //FIXME qscale / qp ... stuff nengel@2: if(s->slice_type == FF_SP_TYPE){ nengel@2: get_bits1(gb); /* sp_for_switch_flag */ nengel@2: } nengel@2: if(s->slice_type==FF_SP_TYPE || s->slice_type == FF_SI_TYPE){ nengel@2: get_se_golomb(gb); /* slice_qs_delta */ nengel@2: } nengel@2: nengel@2: s->slice_alpha_c0_offset = 52; nengel@2: s->slice_beta_offset = 52; nengel@2: if( s->pps.deblocking_filter_parameters_present ) { nengel@2: tmp= get_ue_golomb_31(gb); nengel@2: if(tmp > 1){ nengel@2: av_log(AV_LOG_ERROR, "deblocking_filter_idc %u out of range\n", tmp); nengel@2: return -1; nengel@2: } nengel@2: nengel@2: if(tmp < 2) nengel@2: tmp^= 1; // 1<->0 nengel@2: nengel@2: if( tmp ) { nengel@2: s->slice_alpha_c0_offset += get_se_golomb(gb) << 1; nengel@2: s->slice_beta_offset += get_se_golomb(gb) << 1; nengel@2: if( (unsigned) s->slice_alpha_c0_offset > 104U nengel@2: ||(unsigned) s->slice_beta_offset > 104U){ nengel@2: av_log(AV_LOG_ERROR, "deblocking filter parameters %d %d out of range\n", s->slice_alpha_c0_offset, s->slice_beta_offset); nengel@2: return -1; nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@2: s->qp_thresh= 15 + 52 - FFMIN(s->slice_alpha_c0_offset, s->slice_beta_offset) - FFMAX3(0, s->pps.chroma_qp_index_offset[0], s->pps.chroma_qp_index_offset[1]); nengel@2: nengel@2: return 0; nengel@2: } nengel@2: nengel@2: PictureInfo *get_pib_entry(NalContext *nc, int coded_pic_num){ nengel@2: PictureInfo *pic = NULL; nengel@2: nengel@2: for(int i=0; ipicture[i].reference==0){ nengel@2: pic= &nc->picture[i]; nengel@2: break; nengel@2: } nengel@2: } nengel@2: pic->cpn = coded_pic_num; nengel@2: nengel@2: return pic; nengel@2: } nengel@2: nengel@2: int decode_nal_units(NalContext *n, H264Slice *s, GetBitContext *gb1){ nengel@2: GetBitContext *gb = gb1; nengel@2: uint8_t *buf = gb1->raw; nengel@2: int buf_size = gb1->buf_size; nengel@2: int next_avc = buf_size; nengel@2: int buf_index=0; nengel@2: uint8_t *dst=NULL; nengel@2: // gb->raw = gb1->raw; nengel@2: // gb->rbsp = NULL; nengel@2: s->release_cnt=0; nengel@2: ff_h264_reset_sei(n); nengel@2: nengel@2: s->current_picture_info = get_pib_entry(n, n->coded_pic_num); nengel@2: nengel@2: for(;;){ nengel@2: int consumed; nengel@2: int dst_length; nengel@2: int bit_length; nengel@2: const uint8_t *ptr; nengel@2: int err; nengel@2: nengel@2: if (buf_index >= buf_size){ nengel@2: break; nengel@2: } else { nengel@2: // start code prefix search nengel@2: for(; buf_index + 3 < buf_size; buf_index++){ nengel@2: // This should always succeed in the first iteration. nengel@2: if(buf[buf_index] == 0 && buf[buf_index+1] == 0 && buf[buf_index+2] == 1) nengel@2: break; nengel@2: } nengel@2: if(buf_index+3 >= buf_size) break; nengel@2: buf_index+=3; nengel@2: } nengel@2: nengel@2: { nengel@2: int length = next_avc - buf_index; nengel@2: int i, si, di; nengel@2: uint8_t *src= buf+buf_index; nengel@2: // src[0]&0x80; //forbidden bit nengel@2: s->nal_ref_idc= src[0]>>5; nengel@2: s->nal_unit_type= src[0]&0x1F; nengel@2: nengel@2: src++; length--; nengel@2: nengel@2: for(i=0; i+10 && src[i-1]==0) i--; nengel@2: if(i+2=length-1){ //no escaped 0 nengel@2: dst_length= length; nengel@2: consumed= length+1; //+1 for the header nengel@2: ptr=src; nengel@2: }else{ nengel@2: av_fast_malloc(&gb->rbsp, &gb->rbsp_size, length+FF_INPUT_BUFFER_PADDING_SIZE); nengel@2: dst = gb->rbsp; nengel@2: // if (dst){ nengel@2: // av_free(dst); nengel@2: // } nengel@2: // dst = av_malloc(length+FF_INPUT_BUFFER_PADDING_SIZE); nengel@2: nengel@2: if (dst == NULL){ nengel@2: return -1; nengel@2: } nengel@2: nengel@2: //printf("decoding esc\n"); nengel@2: memcpy(dst, src, i); nengel@2: si=di=i; nengel@2: while(si+23){ nengel@2: dst[di++]= src[si++]; nengel@2: dst[di++]= src[si++]; nengel@2: }else if(src[si]==0 && src[si+1]==0){ nengel@2: if(src[si+2]==3){ //escape nengel@2: dst[di++]= 0; nengel@2: dst[di++]= 0; nengel@2: si+=3; nengel@2: continue; nengel@2: }else //next start code nengel@2: goto nsc; nengel@2: } nengel@2: nengel@2: dst[di++]= src[si++]; nengel@2: } nengel@2: while(sirbsp=ptr; nengel@2: } nengel@2: } nengel@2: if (ptr==NULL || dst_length < 0){ nengel@2: return -1; nengel@2: } nengel@2: nengel@2: //error prevention, should not touch dst_length nengel@2: while(ptr[dst_length - 1] == 0 && dst_length > 0) nengel@2: dst_length--; nengel@2: nengel@2: bit_length= !dst_length ? 0 : (8*dst_length - ff_h264_decode_rbsp_trailing(ptr + dst_length - 1)); nengel@2: buf_index += consumed; nengel@2: nengel@2: err = 0; nengel@2: init_get_bits(gb, ptr, bit_length); nengel@2: switch(s->nal_unit_type){ nengel@2: case NAL_IDR_SLICE: nengel@2: idr(n, s); //FIXME ensure we don't loose some frames if there is reordering nengel@2: case NAL_SLICE: nengel@2: if((err = decode_slice_header(n, s, gb))) nengel@2: break; nengel@2: s->key_frame |= (s->nal_unit_type == NAL_IDR_SLICE) || (n->sei_recovery_frame_cnt >= 0); nengel@2: break; nengel@2: case NAL_DPA: nengel@2: case NAL_DPB: nengel@2: case NAL_DPC: nengel@2: av_log(AV_LOG_ERROR,"no slices/data partitioning support\n"); nengel@2: break; nengel@2: case NAL_SEI: nengel@2: ff_h264_decode_sei(n, gb); nengel@2: break; nengel@2: case NAL_SPS: nengel@2: ff_h264_decode_seq_parameter_set(n, gb); nengel@2: break; nengel@2: case NAL_PPS: nengel@2: ff_h264_decode_picture_parameter_set(n, gb, bit_length); nengel@2: break; nengel@2: case NAL_AUD: nengel@2: case NAL_END_SEQUENCE: nengel@2: case NAL_END_STREAM: nengel@2: case NAL_FILLER_DATA: nengel@2: case NAL_SPS_EXT: nengel@2: case NAL_AUXILIARY_SLICE: nengel@2: break; nengel@2: default: nengel@2: av_log(AV_LOG_ERROR, "Unknown NAL code: %d (%d bits)\n", s->nal_unit_type, bit_length); nengel@2: } nengel@2: if (err < 0) nengel@2: av_log(AV_LOG_ERROR, "decode_slice_header error\n"); nengel@2: nengel@2: } nengel@2: nengel@2: return buf_index; nengel@2: } nengel@2: nengel@2: NalContext *get_nal_context(int width, int height){ nengel@2: const int mb_height = (height + 15) / 16; nengel@2: const int mb_width = (width + 15) / 16; nengel@2: const int mb_stride = ((mb_width+1)/16 + 1) *16; //align mb_stride to 16 nengel@2: nengel@2: NalContext *nc = av_mallocz(sizeof(NalContext)); nengel@2: nc->width = width; nengel@2: nc->height = height; nengel@2: nc->mb_height = mb_height; nengel@2: nc->mb_width = mb_width; nengel@2: nc->b4_stride = mb_width*4 + 1; nengel@2: nc->mb_stride = mb_stride; nengel@2: nc->outputed_poc = INT_MIN; nengel@2: nengel@2: for(int i=0; i<16; i++){ nengel@2: nc->picture[i].cpn =-1; nengel@2: } nengel@2: nengel@2: return nc; nengel@2: } nengel@2: nengel@2: void free_nal_context(NalContext *nc){ nengel@2: for(int i = 0; i < MAX_SPS_COUNT; i++){ nengel@2: if (nc->sps_buffers[i]){ nengel@2: av_free( nc->sps_buffers[i]); nengel@2: } nengel@2: } nengel@2: for(int i = 0; i < MAX_PPS_COUNT; i++){ nengel@2: if (nc->pps_buffers[i]){ nengel@2: av_free( nc->pps_buffers[i]); nengel@2: } nengel@2: } nengel@2: av_free(nc); nengel@2: }