JM ldecod分析: 分帧处理

接上节获取slice获取slice,现在根据不同的帧类型进行处理,此过程是解码的主要工作。
为了可以进行解码,帧stream中总是sps pps在前,第一步是分析SPS 和 PPS.

SPS 处理

//! DataPartition
typedef struct datapartition_dec
{Bitstream           *bitstream;DecodingEnvironment de_cabac;int     (*readSyntaxElement)(struct macroblock_dec *currMB, struct syntaxelement_dec *, struct datapartition_dec *);/*!< virtual function;actual method depends on chosen data partition andentropy coding method  */
} DataPartition;

在解码slice之前,必须要先读到sps和pps,并且首先要读到sps。

case NALU_TYPE_SPS://printf ("Found NALU_TYPE_SPS\n");ProcessSPS(p_Vid, nalu);break;
void ProcessSPS (VideoParameters *p_Vid, NALU_t *nalu)
{  DataPartition *dp = AllocPartition(1);seq_parameter_set_rbsp_t *sps = AllocSPS();memcpy (dp->bitstream->streamBuffer, &nalu->buf[1], nalu->len-1);dp->bitstream->code_len = dp->bitstream->bitstream_length = RBSPtoSODB (dp->bitstream->streamBuffer, nalu->len-1);dp->bitstream->ei_flag = 0;dp->bitstream->read_len = dp->bitstream->frame_bitoffset = 0;InterpretSPS (p_Vid, dp, sps);
#if (MVC_EXTENSION_ENABLE)get_max_dec_frame_buf_size(sps);
#endifif (sps->Valid){if (p_Vid->active_sps){if (sps->seq_parameter_set_id == p_Vid->active_sps->seq_parameter_set_id){if (!sps_is_equal(sps, p_Vid->active_sps)){if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs) //?{// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_sps=NULL;}}}// SPSConsistencyCheck (pps);MakeSPSavailable (p_Vid, sps->seq_parameter_set_id, sps);
#if (MVC_EXTENSION_ENABLE)if (p_Vid->profile_idc < (int) sps->profile_idc){p_Vid->profile_idc = sps->profile_idc;}
#elsep_Vid->profile_idc = sps->profile_idc;
#endifp_Vid->separate_colour_plane_flag = sps->separate_colour_plane_flag;if( p_Vid->separate_colour_plane_flag ){p_Vid->ChromaArrayType = 0;}else{p_Vid->ChromaArrayType = sps->chroma_format_idc;}}FreePartition (dp, 1);FreeSPS (sps);
}

InterpretSPS() 是processSPS的关键 (sps内容参见 sps 组成 )

// fill sps with content of pint InterpretSPS (VideoParameters *p_Vid, DataPartition *p, seq_parameter_set_rbsp_t *sps)
{unsigned i;unsigned n_ScalingList;int reserved_zero;Bitstream *s = p->bitstream;assert (p != NULL);assert (p->bitstream != NULL);assert (p->bitstream->streamBuffer != 0);assert (sps != NULL);p_Dec->UsedBits = 0;sps->profile_idc                            = read_u_v  (8, "SPS: profile_idc"                           , s, &p_Dec->UsedBits);if ((sps->profile_idc!=BASELINE       ) &&(sps->profile_idc!=MAIN           ) &&(sps->profile_idc!=EXTENDED       ) &&(sps->profile_idc!=FREXT_HP       ) &&(sps->profile_idc!=FREXT_Hi10P    ) &&(sps->profile_idc!=FREXT_Hi422    ) &&(sps->profile_idc!=FREXT_Hi444    ) &&(sps->profile_idc!=FREXT_CAVLC444 )
#if (MVC_EXTENSION_ENABLE)&& (sps->profile_idc!=MVC_HIGH)&& (sps->profile_idc!=STEREO_HIGH)
#endif){printf("Invalid Profile IDC (%d) encountered. \n", sps->profile_idc);return p_Dec->UsedBits;}sps->constrained_set0_flag                  = read_u_1  (   "SPS: constrained_set0_flag"                 , s, &p_Dec->UsedBits);sps->constrained_set1_flag                  = read_u_1  (   "SPS: constrained_set1_flag"                 , s, &p_Dec->UsedBits);sps->constrained_set2_flag                  = read_u_1  (   "SPS: constrained_set2_flag"                 , s, &p_Dec->UsedBits);sps->constrained_set3_flag                  = read_u_1  (   "SPS: constrained_set3_flag"                 , s, &p_Dec->UsedBits);
#if (MVC_EXTENSION_ENABLE)sps->constrained_set4_flag                  = read_u_1  (   "SPS: constrained_set4_flag"                 , s, &p_Dec->UsedBits);sps->constrained_set5_flag                  = read_u_1  (   "SPS: constrained_set5_flag"                 , s, &p_Dec->UsedBits);reserved_zero                               = read_u_v  (2, "SPS: reserved_zero_2bits"                   , s, &p_Dec->UsedBits);
#elsereserved_zero                               = read_u_v  (4, "SPS: reserved_zero_4bits"                   , s, &p_Dec->UsedBits);
#endif//assert (reserved_zero==0);if (reserved_zero != 0){printf("Warning, reserved_zero flag not equal to 0. Possibly new constrained_setX flag introduced.\n");}sps->level_idc                              = read_u_v  (8, "SPS: level_idc"                             , s, &p_Dec->UsedBits);sps->seq_parameter_set_id                   = read_ue_v ("SPS: seq_parameter_set_id"                     , s, &p_Dec->UsedBits);// Fidelity Range Extensions stuffsps->chroma_format_idc = 1;sps->bit_depth_luma_minus8   = 0;sps->bit_depth_chroma_minus8 = 0;sps->lossless_qpprime_flag   = 0;sps->separate_colour_plane_flag = 0;if((sps->profile_idc==FREXT_HP   ) ||(sps->profile_idc==FREXT_Hi10P) ||(sps->profile_idc==FREXT_Hi422) ||(sps->profile_idc==FREXT_Hi444) ||(sps->profile_idc==FREXT_CAVLC444)
#if (MVC_EXTENSION_ENABLE)|| (sps->profile_idc==MVC_HIGH)|| (sps->profile_idc==STEREO_HIGH)
#endif){sps->chroma_format_idc                      = read_ue_v ("SPS: chroma_format_idc"                       , s, &p_Dec->UsedBits);if(sps->chroma_format_idc == YUV444){sps->separate_colour_plane_flag           = read_u_1  ("SPS: separate_colour_plane_flag"              , s, &p_Dec->UsedBits);}sps->bit_depth_luma_minus8                  = read_ue_v ("SPS: bit_depth_luma_minus8"                   , s, &p_Dec->UsedBits);sps->bit_depth_chroma_minus8                = read_ue_v ("SPS: bit_depth_chroma_minus8"                 , s, &p_Dec->UsedBits);//checking;if((sps->bit_depth_luma_minus8+8 > sizeof(imgpel)*8) || (sps->bit_depth_chroma_minus8+8> sizeof(imgpel)*8))error ("Source picture has higher bit depth than imgpel data type. \nPlease recompile with larger data type for imgpel.", 500);sps->lossless_qpprime_flag                  = read_u_1  ("SPS: lossless_qpprime_y_zero_flag"            , s, &p_Dec->UsedBits);sps->seq_scaling_matrix_present_flag        = read_u_1  (   "SPS: seq_scaling_matrix_present_flag"       , s, &p_Dec->UsedBits);if(sps->seq_scaling_matrix_present_flag){n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;for(i=0; i<n_ScalingList; i++){sps->seq_scaling_list_present_flag[i]   = read_u_1  (   "SPS: seq_scaling_list_present_flag"         , s, &p_Dec->UsedBits);if(sps->seq_scaling_list_present_flag[i]){if(i<6)Scaling_List(sps->ScalingList4x4[i], 16, &sps->UseDefaultScalingMatrix4x4Flag[i], s);elseScaling_List(sps->ScalingList8x8[i-6], 64, &sps->UseDefaultScalingMatrix8x8Flag[i-6], s);}}}}sps->log2_max_frame_num_minus4              = read_ue_v ("SPS: log2_max_frame_num_minus4"                , s, &p_Dec->UsedBits);sps->pic_order_cnt_type                     = read_ue_v ("SPS: pic_order_cnt_type"                       , s, &p_Dec->UsedBits);if (sps->pic_order_cnt_type == 0)sps->log2_max_pic_order_cnt_lsb_minus4 = read_ue_v ("SPS: log2_max_pic_order_cnt_lsb_minus4"           , s, &p_Dec->UsedBits);else if (sps->pic_order_cnt_type == 1){sps->delta_pic_order_always_zero_flag      = read_u_1  ("SPS: delta_pic_order_always_zero_flag"       , s, &p_Dec->UsedBits);sps->offset_for_non_ref_pic                = read_se_v ("SPS: offset_for_non_ref_pic"                 , s, &p_Dec->UsedBits);sps->offset_for_top_to_bottom_field        = read_se_v ("SPS: offset_for_top_to_bottom_field"         , s, &p_Dec->UsedBits);sps->num_ref_frames_in_pic_order_cnt_cycle = read_ue_v ("SPS: num_ref_frames_in_pic_order_cnt_cycle"  , s, &p_Dec->UsedBits);for(i=0; i<sps->num_ref_frames_in_pic_order_cnt_cycle; i++)sps->offset_for_ref_frame[i]               = read_se_v ("SPS: offset_for_ref_frame[i]"              , s, &p_Dec->UsedBits);}sps->num_ref_frames                        = read_ue_v ("SPS: num_ref_frames"                         , s, &p_Dec->UsedBits);sps->gaps_in_frame_num_value_allowed_flag  = read_u_1  ("SPS: gaps_in_frame_num_value_allowed_flag"   , s, &p_Dec->UsedBits);sps->pic_width_in_mbs_minus1               = read_ue_v ("SPS: pic_width_in_mbs_minus1"                , s, &p_Dec->UsedBits);sps->pic_height_in_map_units_minus1        = read_ue_v ("SPS: pic_height_in_map_units_minus1"         , s, &p_Dec->UsedBits);sps->frame_mbs_only_flag                   = read_u_1  ("SPS: frame_mbs_only_flag"                    , s, &p_Dec->UsedBits);if (!sps->frame_mbs_only_flag){sps->mb_adaptive_frame_field_flag        = read_u_1  ("SPS: mb_adaptive_frame_field_flag"           , s, &p_Dec->UsedBits);}//printf("interlace flags %d %d\n", sps->frame_mbs_only_flag, sps->mb_adaptive_frame_field_flag);sps->direct_8x8_inference_flag             = read_u_1  ("SPS: direct_8x8_inference_flag"              , s, &p_Dec->UsedBits);sps->frame_cropping_flag                   = read_u_1  ("SPS: frame_cropping_flag"                    , s, &p_Dec->UsedBits);if (sps->frame_cropping_flag){sps->frame_crop_left_offset      = read_ue_v ("SPS: frame_crop_left_offset"           , s, &p_Dec->UsedBits);sps->frame_crop_right_offset     = read_ue_v ("SPS: frame_crop_right_offset"          , s, &p_Dec->UsedBits);sps->frame_crop_top_offset       = read_ue_v ("SPS: frame_crop_top_offset"            , s, &p_Dec->UsedBits);sps->frame_crop_bottom_offset    = read_ue_v ("SPS: frame_crop_bottom_offset"         , s, &p_Dec->UsedBits);}sps->vui_parameters_present_flag           = (Boolean) read_u_1  ("SPS: vui_parameters_present_flag"      , s, &p_Dec->UsedBits);InitVUI(sps);ReadVUI(p, sps);sps->Valid = TRUE;return p_Dec->UsedBits;
}

当seq_scaling_list_present_flag 为1时,放大系数以下面的函数的过程来从sps中获取。一般情况下seq_scaling_list_present_flag都为0,即使用默认的放大系数。

// syntax for scaling list matrix values
void Scaling_List(int *scalingList, int sizeOfScalingList, Boolean *UseDefaultScalingMatrix, Bitstream *s)
{int j, scanj;int delta_scale, lastScale, nextScale;lastScale      = 8;nextScale      = 8;for(j=0; j<sizeOfScalingList; j++){scanj = (sizeOfScalingList==16) ? ZZ_SCAN[j]:ZZ_SCAN8[j];if(nextScale!=0){delta_scale = read_se_v (   "   : delta_sl   "                           , s, &p_Dec->UsedBits);nextScale = (lastScale + delta_scale + 256) % 256;*UseDefaultScalingMatrix = (Boolean) (scanj==0 && nextScale==0);}scalingList[scanj] = (nextScale==0) ? lastScale:nextScale;lastScale = scalingList[scanj];}
}

PPS 处理

ProcessSPS(p_Vid, nalu);
void ProcessPPS (VideoParameters *p_Vid, NALU_t *nalu){DataPartition *dp = AllocPartition(1);pic_parameter_set_rbsp_t *pps = AllocPPS();//讲nalu中的数据拷贝到bitstreammemcpy (dp->bitstream->streamBuffer, &nalu->buf[1], nalu->len-1);dp->bitstream->code_len = dp->bitstream->bitstream_length = RBSPtoSODB (dp->bitstream->streamBuffer, nalu->len-1);dp->bitstream->ei_flag = 0;dp->bitstream->read_len = dp->bitstream->frame_bitoffset = 0;InterpretPPS (p_Vid, dp, pps);// PPSConsistencyCheck (pps);if (p_Vid->active_pps){if (pps->pic_parameter_set_id == p_Vid->active_pps->pic_parameter_set_id){if(!pps_is_equal(pps, p_Vid->active_pps)){//copy to next PPS;memcpy(p_Vid->pNextPPS, p_Vid->active_pps, sizeof (pic_parameter_set_rbsp_t));{if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_pps = NULL;}}}}MakePPSavailable (p_Vid, pps->pic_parameter_set_id, pps);FreePartition (dp, 1);FreePPS (pps);}

slice 和IDR

根据读到的nalu,填充slice。

 case NALU_TYPE_SLICE:case NALU_TYPE_IDR:if (p_Vid->recovery_point || nalu->nal_unit_type == NALU_TYPE_IDR){if (p_Vid->recovery_point_found == 0){if (nalu->nal_unit_type != NALU_TYPE_IDR){printf("Warning: Decoding does not start with an IDR picture.\n");p_Vid->non_conforming_stream = 1;}elsep_Vid->non_conforming_stream = 0;}p_Vid->recovery_point_found = 1;}if (p_Vid->recovery_point_found == 0)break;currSlice->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR);currSlice->nal_reference_idc = nalu->nal_reference_idc;currSlice->dp_mode = PAR_DP_1;currSlice->max_part_nr = 1;
#if (MVC_EXTENSION_ENABLE)if (currSlice->svc_extension_flag != 0){currStream = currSlice->partArr[0].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;fast_memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);}
#else datapartion 在malloc_slice中分配,nr 为3,bitstream同时也在此时分配,下边填充bitstreamcurrStream = currSlice->partArr[0].bitstream;currStream->ei_flag = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);
#endif#if (MVC_EXTENSION_ENABLE)if(currSlice->svc_extension_flag == 0){  //MVC//if(is_MVC_profile(p_Vid->active_sps->profile_idc))//{currSlice->view_id = currSlice->NaluHeaderMVCExt.view_id;currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;//}}else if(currSlice->svc_extension_flag == -1) //SVC and the normal AVC;{if(p_Vid->active_subset_sps == NULL){currSlice->view_id = GetBaseViewId(p_Vid, &p_Vid->active_subset_sps);if(currSlice->NaluHeaderMVCExt.iPrefixNALU >0){assert(currSlice->view_id == currSlice->NaluHeaderMVCExt.view_id);currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;}else{currSlice->inter_view_flag = 1;currSlice->anchor_pic_flag = currSlice->idr_flag;}}else{assert(p_Vid->active_subset_sps->num_views_minus1 >=0);// prefix NALU availableif(currSlice->NaluHeaderMVCExt.iPrefixNALU >0){currSlice->view_id = currSlice->NaluHeaderMVCExt.view_id;currSlice->inter_view_flag = currSlice->NaluHeaderMVCExt.inter_view_flag;currSlice->anchor_pic_flag = currSlice->NaluHeaderMVCExt.anchor_pic_flag;}else{ //no prefix NALU;currSlice->view_id = p_Vid->active_subset_sps->view_id[0];currSlice->inter_view_flag = 1;currSlice->anchor_pic_flag = currSlice->idr_flag;}}}currSlice->layer_id = currSlice->view_id = GetVOIdx( p_Vid, currSlice->view_id );
#endif// Some syntax of the Slice Header depends on the parameter set, which depends on// the parameter set ID of the SLice header.  Hence, read the pic_parameter_set_id// of the slice header first, then setup the active parameter sets, and then read// the rest of the slice headerBitsUsedByHeader = FirstPartOfSliceHeader(currSlice);UseParameterSet (currSlice);currSlice->active_sps = p_Vid->active_sps;currSlice->active_pps = p_Vid->active_pps;currSlice->Transform8x8Mode = p_Vid->active_pps->transform_8x8_mode_flag;currSlice->chroma444_not_separate = (p_Vid->active_sps->chroma_format_idc==YUV444)&&((p_Vid->separate_colour_plane_flag == 0));BitsUsedByHeader += RestOfSliceHeader (currSlice);
#if (MVC_EXTENSION_ENABLE)if(currSlice->view_id >=0){currSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->view_id];}
#endifassign_quant_params (currSlice);        // if primary slice is replaced with redundant slice, set the correct image typeif(currSlice->redundant_pic_cnt && p_Vid->Is_primary_correct==0 && p_Vid->Is_redundant_correct){p_Vid->dec_picture->slice_type = p_Vid->type;}if(is_new_picture(p_Vid->dec_picture, currSlice, p_Vid->old_slice)){if(p_Vid->iSliceNumOfCurrPic==0)init_picture(p_Vid, currSlice, p_Inp);current_header = SOP;//check zero_byte if it is also the first NAL unit in the access unitCheckZeroByteVCL(p_Vid, nalu);}elsecurrent_header = SOS;setup_slice_methods(currSlice);// From here on, p_Vid->active_sps, p_Vid->active_pps and the slice header are validif (currSlice->mb_aff_frame_flag)currSlice->current_mb_nr = currSlice->start_mb_nr << 1;elsecurrSlice->current_mb_nr = currSlice->start_mb_nr;if (p_Vid->active_pps->entropy_coding_mode_flag){int ByteStartPosition = currStream->frame_bitoffset/8;if (currStream->frame_bitoffset%8 != 0){++ByteStartPosition;}arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len);}// printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS");//FreeNALU(nalu);p_Vid->recovery_point = 0;return current_header;break;case NALU_TYPE_DPA:if (p_Vid->recovery_point_found == 0)break;// read DP_AcurrSlice->dpB_NotPresent =1; currSlice->dpC_NotPresent =1; currSlice->idr_flag          = FALSE;currSlice->nal_reference_idc = nalu->nal_reference_idc;currSlice->dp_mode     = PAR_DP_3;currSlice->max_part_nr = 3;currSlice->ei_flag     = 0;
#if MVC_EXTENSION_ENABLEcurrSlice->p_Dpb = p_Vid->p_Dpb_layer[0];
#endifcurrStream             = currSlice->partArr[0].bitstream;currStream->ei_flag    = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);
#if MVC_EXTENSION_ENABLEcurrSlice->view_id = GetBaseViewId(p_Vid, &p_Vid->active_subset_sps);currSlice->inter_view_flag = 1;currSlice->layer_id = currSlice->view_id = GetVOIdx( p_Vid, currSlice->view_id );currSlice->anchor_pic_flag = currSlice->idr_flag;
#endifBitsUsedByHeader = FirstPartOfSliceHeader(currSlice);UseParameterSet (currSlice);currSlice->active_sps = p_Vid->active_sps;currSlice->active_pps = p_Vid->active_pps;currSlice->Transform8x8Mode = p_Vid->active_pps->transform_8x8_mode_flag;currSlice->chroma444_not_separate = (p_Vid->active_sps->chroma_format_idc==YUV444)&&((p_Vid->separate_colour_plane_flag == 0));BitsUsedByHeader += RestOfSliceHeader (currSlice);
#if MVC_EXTENSION_ENABLEcurrSlice->p_Dpb = p_Vid->p_Dpb_layer[currSlice->view_id];
#endifassign_quant_params (currSlice);        当该slice是一副新图像,一般情况下一个slice都是一副新图像。if(is_new_picture(p_Vid->dec_picture, currSlice, p_Vid->old_slice)){ 当slice是第一个slice时if(p_Vid->iSliceNumOfCurrPic==0)init_picture(p_Vid, currSlice, p_Inp);current_header = SOP;//check zero_byte if it is also the first NAL unit in the access unitCheckZeroByteVCL(p_Vid, nalu);}elsecurrent_header = SOS;setup_slice_methods(currSlice);// From here on, p_Vid->active_sps, p_Vid->active_pps and the slice header are validif (currSlice->mb_aff_frame_flag)currSlice->current_mb_nr = currSlice->start_mb_nr << 1;elsecurrSlice->current_mb_nr = currSlice->start_mb_nr;// Now I need to read the slice ID, which depends on the value of// redundant_pic_cnt_present_flagslice_id_a  = read_ue_v("NALU: DP_A slice_id", currStream, &p_Dec->UsedBits);if (p_Vid->active_pps->entropy_coding_mode_flag)error ("received data partition with CABAC, this is not allowed", 500);// continue with reading next DPif (0 == read_next_nalu(p_Vid, nalu))return current_header;if ( NALU_TYPE_DPB == nalu->nal_unit_type){// we got a DPBcurrStream             = currSlice->partArr[1].bitstream;currStream->ei_flag    = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);slice_id_b  = read_ue_v("NALU: DP_B slice_id", currStream, &p_Dec->UsedBits);currSlice->dpB_NotPresent = 0; if ((slice_id_b != slice_id_a) || (nalu->lost_packets)){printf ("Waning: got a data partition B which does not match DP_A (DP loss!)\n");currSlice->dpB_NotPresent =1; currSlice->dpC_NotPresent =1; }else{if (p_Vid->active_pps->redundant_pic_cnt_present_flag)read_ue_v("NALU: DP_B redundant_pic_cnt", currStream, &p_Dec->UsedBits);// we're finished with DP_B, so let's continue with next DPif (0 == read_next_nalu(p_Vid, nalu))return current_header;}}else{currSlice->dpB_NotPresent =1; }// check if we got DP_Cif ( NALU_TYPE_DPC == nalu->nal_unit_type){currStream             = currSlice->partArr[2].bitstream;currStream->ei_flag    = 0;currStream->frame_bitoffset = currStream->read_len = 0;memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1);currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1);currSlice->dpC_NotPresent = 0;slice_id_c  = read_ue_v("NALU: DP_C slice_id", currStream, &p_Dec->UsedBits);if ((slice_id_c != slice_id_a)|| (nalu->lost_packets)){printf ("Warning: got a data partition C which does not match DP_A(DP loss!)\n");//currSlice->dpB_NotPresent =1;currSlice->dpC_NotPresent =1;}if (p_Vid->active_pps->redundant_pic_cnt_present_flag)read_ue_v("NALU:SLICE_C redudand_pic_cnt", currStream, &p_Dec->UsedBits);}else{currSlice->dpC_NotPresent =1;pending_nalu = nalu;}// check if we read anything else than the expected partitionsif ((nalu->nal_unit_type != NALU_TYPE_DPB) && (nalu->nal_unit_type != NALU_TYPE_DPC) && (!currSlice->dpC_NotPresent)){// we have a NALI that we can't process here, so restart processinggoto process_nalu;// yes, "goto" should not be used, but it's really the best way here before we restructure the decoding loop// (which should be taken care of anyway)}//FreeNALU(nalu);return current_header;break;
/*!************************************************************************* \brief*    Initializes the parameters for a new picture*************************************************************************/
static void init_picture(VideoParameters *p_Vid, Slice *currSlice, InputParameters *p_Inp)
{int i;int nplane;StorablePicture *dec_picture = NULL;seq_parameter_set_rbsp_t *active_sps = p_Vid->active_sps;DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;p_Vid->PicHeightInMbs = p_Vid->FrameHeightInMbs / ( 1 + currSlice->field_pic_flag );p_Vid->PicSizeInMbs   = p_Vid->PicWidthInMbs * p_Vid->PicHeightInMbs;p_Vid->FrameSizeInMbs = p_Vid->PicWidthInMbs * p_Vid->FrameHeightInMbs;p_Vid->bFrameInit = 1;if (p_Vid->dec_picture) // && p_Vid->num_dec_mb == p_Vid->PicSizeInMbs){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->dpb_layer_id = currSlice->layer_id;//set buffers;setup_buffers(p_Vid, currSlice->layer_id);if (p_Vid->recovery_point)p_Vid->recovery_frame_num = (currSlice->frame_num + p_Vid->recovery_frame_cnt) % p_Vid->max_frame_num;if (currSlice->idr_flag)p_Vid->recovery_frame_num = currSlice->frame_num;if (p_Vid->recovery_point == 0 &&currSlice->frame_num != p_Vid->pre_frame_num &&currSlice->frame_num != (p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num){if (active_sps->gaps_in_frame_num_value_allowed_flag == 0){// picture error concealmentif(p_Inp->conceal_mode !=0){if((currSlice->frame_num) < ((p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num)){/* Conceal lost IDR frames and any frames immediatelyfollowing the IDR. Use frame copy for these sincelists cannot be formed correctly for motion copy*/p_Vid->conceal_mode = 1;p_Vid->IDR_concealment_flag = 1;conceal_lost_frames(p_Dpb, currSlice);//reset to original concealment mode for future dropsp_Vid->conceal_mode = p_Inp->conceal_mode;}else{//reset to original concealment mode for future dropsp_Vid->conceal_mode = p_Inp->conceal_mode;p_Vid->IDR_concealment_flag = 0;conceal_lost_frames(p_Dpb, currSlice);}}else{   /* Advanced Error Concealment would be called here to combat unintentional loss of pictures. */error("An unintentional loss of pictures occurs! Exit\n", 100);}}if(p_Vid->conceal_mode == 0)fill_frame_num_gap(p_Vid, currSlice);}if(currSlice->nal_reference_idc){p_Vid->pre_frame_num = currSlice->frame_num;}//p_Vid->num_dec_mb = 0;//calculate POCdecode_poc(p_Vid, currSlice);if (p_Vid->recovery_frame_num == (int) currSlice->frame_num && p_Vid->recovery_poc == 0x7fffffff)p_Vid->recovery_poc = currSlice->framepoc;if(currSlice->nal_reference_idc)p_Vid->last_ref_pic_poc = currSlice->framepoc;//  dumppoc (p_Vid);if (currSlice->structure==FRAME ||currSlice->structure==TOP_FIELD){gettime (&(p_Vid->start_time));             // start time}dec_picture = p_Vid->dec_picture = alloc_storable_picture (p_Vid, currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);dec_picture->top_poc=currSlice->toppoc;dec_picture->bottom_poc=currSlice->bottompoc;dec_picture->frame_poc=currSlice->framepoc;dec_picture->qp = currSlice->qp;dec_picture->slice_qp_delta = currSlice->slice_qp_delta;dec_picture->chroma_qp_offset[0] = p_Vid->active_pps->chroma_qp_index_offset;dec_picture->chroma_qp_offset[1] = p_Vid->active_pps->second_chroma_qp_index_offset;dec_picture->iCodingType = currSlice->structure==FRAME? (currSlice->mb_aff_frame_flag? FRAME_MB_PAIR_CODING:FRAME_CODING): FIELD_CODING; //currSlice->slice_type;dec_picture->layer_id = currSlice->layer_id;
#if (MVC_EXTENSION_ENABLE)dec_picture->view_id         = currSlice->view_id;dec_picture->inter_view_flag = currSlice->inter_view_flag;dec_picture->anchor_pic_flag = currSlice->anchor_pic_flag;if (dec_picture->view_id == 1){if((p_Vid->profile_idc == MVC_HIGH) || (p_Vid->profile_idc == STEREO_HIGH))init_mvc_picture(currSlice);}
#endif// reset all variables of the error concealment instance before decoding of every frame.// here the third parameter should, if perfectly, be equal to the number of slices per frame.// using little value is ok, the code will allocate more memory if the slice number is larger
#if (DISABLE_ERC == 0)ercReset(p_Vid->erc_errorVar, p_Vid->PicSizeInMbs, p_Vid->PicSizeInMbs, dec_picture->size_x);
#endifp_Vid->erc_mvperMB = 0;switch (currSlice->structure ){case TOP_FIELD:{dec_picture->poc = currSlice->toppoc;p_Vid->number *= 2;break;}case BOTTOM_FIELD:{dec_picture->poc = currSlice->bottompoc;p_Vid->number = p_Vid->number * 2 + 1;break;}case FRAME:{dec_picture->poc = currSlice->framepoc;break;}default:error("p_Vid->structure not initialized", 235);}//p_Vid->current_slice_nr=0;if (p_Vid->type > SI_SLICE){set_ec_flag(p_Vid, SE_PTYPE);p_Vid->type = P_SLICE;  // concealed element}// CAVLC initif (p_Vid->active_pps->entropy_coding_mode_flag == (Boolean) CAVLC){memset(p_Vid->nz_coeff[0][0][0], -1, p_Vid->PicSizeInMbs * 48 *sizeof(byte)); // 3 * 4 * 4}// Set the slice_nr member of each MB to -1, to ensure correct when packet loss occurs// TO set Macroblock Map (mark all MBs as 'have to be concealed')if( (p_Vid->separate_colour_plane_flag != 0) ){for( nplane=0; nplane<MAX_PLANE; ++nplane ){      Macroblock *currMB = p_Vid->mb_data_JV[nplane];char *intra_block = p_Vid->intra_block_JV[nplane];for(i=0; i<(int)p_Vid->PicSizeInMbs; ++i){reset_mbs(currMB++);}fast_memset(p_Vid->ipredmode_JV[nplane][0], DC_PRED, 16 * p_Vid->FrameHeightInMbs * p_Vid->PicWidthInMbs * sizeof(char));if(p_Vid->active_pps->constrained_intra_pred_flag){for (i=0; i<(int)p_Vid->PicSizeInMbs; ++i){intra_block[i] = 1;}}}}else{#if 0 //defined(OPENMP)
#pragma omp parallel forfor(i=0; i<(int)p_Vid->PicSizeInMbs; ++i)reset_mbs(&p_Vid->mb_data[i]);
#elseMacroblock *currMB = p_Vid->mb_data;for(i=0; i<(int)p_Vid->PicSizeInMbs; ++i)reset_mbs(currMB++);
#endifif(p_Vid->active_pps->constrained_intra_pred_flag){for (i=0; i<(int)p_Vid->PicSizeInMbs; ++i){p_Vid->intra_block[i] = 1;}}fast_memset(p_Vid->ipredmode[0], DC_PRED, 16 * p_Vid->FrameHeightInMbs * p_Vid->PicWidthInMbs * sizeof(char));}  dec_picture->slice_type = p_Vid->type;dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0);dec_picture->idr_flag = currSlice->idr_flag;dec_picture->no_output_of_prior_pics_flag = currSlice->no_output_of_prior_pics_flag;dec_picture->long_term_reference_flag     = currSlice->long_term_reference_flag;dec_picture->adaptive_ref_pic_buffering_flag = currSlice->adaptive_ref_pic_buffering_flag;dec_picture->dec_ref_pic_marking_buffer = currSlice->dec_ref_pic_marking_buffer;currSlice->dec_ref_pic_marking_buffer   = NULL;dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag;dec_picture->PicWidthInMbs     = p_Vid->PicWidthInMbs;p_Vid->get_mb_block_pos = dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff : get_mb_block_pos_normal;p_Vid->getNeighbour     = dec_picture->mb_aff_frame_flag ? getAffNeighbour : getNonAffNeighbour;dec_picture->pic_num   = currSlice->frame_num;dec_picture->frame_num = currSlice->frame_num;dec_picture->recovery_frame = (unsigned int) ((int) currSlice->frame_num == p_Vid->recovery_frame_num);dec_picture->coded_frame = (currSlice->structure==FRAME);dec_picture->chroma_format_idc = active_sps->chroma_format_idc;dec_picture->frame_mbs_only_flag = active_sps->frame_mbs_only_flag;dec_picture->frame_cropping_flag = active_sps->frame_cropping_flag;if (dec_picture->frame_cropping_flag){dec_picture->frame_crop_left_offset   = active_sps->frame_crop_left_offset;dec_picture->frame_crop_right_offset  = active_sps->frame_crop_right_offset;dec_picture->frame_crop_top_offset    = active_sps->frame_crop_top_offset;dec_picture->frame_crop_bottom_offset = active_sps->frame_crop_bottom_offset;}#if (ENABLE_OUTPUT_TONEMAPPING)// store the necessary tone mapping sei into StorablePicture structureif (p_Vid->seiToneMapping->seiHasTone_mapping){int coded_data_bit_max = (1 << p_Vid->seiToneMapping->coded_data_bit_depth);dec_picture->seiHasTone_mapping    = 1;dec_picture->tone_mapping_model_id = p_Vid->seiToneMapping->model_id;dec_picture->tonemapped_bit_depth  = p_Vid->seiToneMapping->sei_bit_depth;dec_picture->tone_mapping_lut      = malloc(coded_data_bit_max * sizeof(int));if (NULL == dec_picture->tone_mapping_lut){no_mem_exit("init_picture: tone_mapping_lut");}memcpy(dec_picture->tone_mapping_lut, p_Vid->seiToneMapping->lut, sizeof(imgpel) * coded_data_bit_max);update_tone_mapping_sei(p_Vid->seiToneMapping);}elsedec_picture->seiHasTone_mapping = 0;
#endifif( (p_Vid->separate_colour_plane_flag != 0) ){p_Vid->dec_picture_JV[0] = p_Vid->dec_picture;p_Vid->dec_picture_JV[1] = alloc_storable_picture (p_Vid, (PictureStructure) currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);copy_dec_picture_JV( p_Vid, p_Vid->dec_picture_JV[1], p_Vid->dec_picture_JV[0] );p_Vid->dec_picture_JV[2] = alloc_storable_picture (p_Vid, (PictureStructure) currSlice->structure, p_Vid->width, p_Vid->height, p_Vid->width_cr, p_Vid->height_cr, 1);copy_dec_picture_JV( p_Vid, p_Vid->dec_picture_JV[2], p_Vid->dec_picture_JV[0] );}
}

slice header 处理

  1. 当该nalu为IDR和普通slice 时,这里就是一个刷新点。然后开始读取slice header,由于sliceheader字段依赖图像参数集,这里的读取sliceheader分为两部分。

FirstPartOfSliceHeader(currSlice) 获取sliceheader字段中不依赖图像参数集的部分
sliceheader字段描述

/*!************************************************************************* \brief*    read the first part of the header (only the pic_parameter_set_id)* \return*    Length of the first part of the slice header (in bits)*************************************************************************/
int FirstPartOfSliceHeader(Slice *currSlice)
{VideoParameters *p_Vid = currSlice->p_Vid;byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER];DataPartition *partition = &(currSlice->partArr[dP_nr]);Bitstream *currStream = partition->bitstream;int tmp;p_Dec->UsedBits= partition->bitstream->frame_bitoffset; // was hardcoded to 31 for previous start-code. This is better.// Get first_mb_in_slicecurrSlice->start_mb_nr = read_ue_v ("SH: first_mb_in_slice", currStream, &p_Dec->UsedBits);tmp = read_ue_v ("SH: slice_type", currStream, &p_Dec->UsedBits);if (tmp > 4) tmp -= 5;p_Vid->type = currSlice->slice_type = (SliceType) tmp;currSlice->pic_parameter_set_id = read_ue_v ("SH: pic_parameter_set_id", currStream, &p_Dec->UsedBits);if( p_Vid->separate_colour_plane_flag )currSlice->colour_plane_id = read_u_v (2, "SH: colour_plane_id", currStream, &p_Dec->UsedBits);elsecurrSlice->colour_plane_id = PLANE_Y;return p_Dec->UsedBits;
}

slice_type 为1~5,上面代码中会有映射

typedef enum
{P_SLICE = 0,B_SLICE = 1,I_SLICE = 2,SP_SLICE = 3,SI_SLICE = 4,NUM_SLICE_TYPES = 5
} SliceType;

UseParameterSet (Slice *currSlice)

在读到其他帧之前一定要先读到sps 和pps 才能够进行解码。下边是激活sps 和pps,并根据读到的pps的熵编码类型设置读取函数。

void UseParameterSet (Slice *currSlice)
{VideoParameters *p_Vid = currSlice->p_Vid;int PicParsetId = currSlice->pic_parameter_set_id;  pic_parameter_set_rbsp_t *pps = &p_Vid->PicParSet[PicParsetId];seq_parameter_set_rbsp_t *sps = &p_Vid->SeqParSet[pps->seq_parameter_set_id];int i;if (pps->Valid != TRUE)printf ("Trying to use an invalid (uninitialized) Picture Parameter Set with ID %d, expect the unexpected...\n", PicParsetId);
#if (MVC_EXTENSION_ENABLE)if (currSlice->svc_extension_flag == -1){if (sps->Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);}else{// Set SPS to the subset SPS parametersp_Vid->active_subset_sps = p_Vid->SubsetSeqParSet + pps->seq_parameter_set_id;sps = &(p_Vid->active_subset_sps->sps);if (p_Vid->SubsetSeqParSet[pps->seq_parameter_set_id].Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Subset Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);}
#elseif (sps->Valid != TRUE)printf ("PicParset %d references an invalid (uninitialized) Sequence Parameter Set with ID %d, expect the unexpected...\n", PicParsetId, (int) pps->seq_parameter_set_id);
#endif// In theory, and with a well-designed software, the lines above// are everything necessary.  In practice, we need to patch many values// in p_Vid-> (but no more in p_Inp-> -- these have been taken care of)// Set Sequence Parameter Stuff first//  printf ("Using Picture Parameter set %d and associated Sequence Parameter Set %d\n", PicParsetId, pps->seq_parameter_set_id);if ((int) sps->pic_order_cnt_type < 0 || sps->pic_order_cnt_type > 2)  // != 1{printf ("invalid sps->pic_order_cnt_type = %d\n", (int) sps->pic_order_cnt_type);error ("pic_order_cnt_type != 1", -1000);}if (sps->pic_order_cnt_type == 1){if(sps->num_ref_frames_in_pic_order_cnt_cycle >= MAXnum_ref_frames_in_pic_order_cnt_cycle){error("num_ref_frames_in_pic_order_cnt_cycle too large",-1011);}}p_Vid->dpb_layer_id = currSlice->layer_id;activate_sps(p_Vid, sps);activate_pps(p_Vid, pps);// currSlice->dp_mode is set by read_new_slice (NALU first byte available there)if (pps->entropy_coding_mode_flag == (Boolean) CAVLC){currSlice->nal_startcode_follows = uvlc_startcode_follows;for (i=0; i<3; i++){currSlice->partArr[i].readSyntaxElement = readSyntaxElement_UVLC;      }}else{currSlice->nal_startcode_follows = cabac_startcode_follows;for (i=0; i<3; i++){currSlice->partArr[i].readSyntaxElement = readSyntaxElement_CABAC;}}p_Vid->type = currSlice->slice_type;

activate_sps() & activate_pps()

/*!************************************************************************* \brief*    Activate Sequence Parameter Sets**************************************************************************/
void activate_sps (VideoParameters *p_Vid, seq_parameter_set_rbsp_t *sps)
{InputParameters *p_Inp = p_Vid->p_Inp;
激活sps时,p_Vid中activate_sps是NULLif (p_Vid->active_sps != sps){if (p_Vid->dec_picture){// this may only happen on slice lossexit_picture(p_Vid, &p_Vid->dec_picture);}p_Vid->active_sps = sps;if(p_Vid->dpb_layer_id==0 && is_BL_profile(sps->profile_idc) && !p_Vid->p_Dpb_layer[0]->init_done){将sps中的相关参数加入到解码参数结构中set_coding_par(sps, p_Vid->p_EncodePar[0]);setup_layer_info( p_Vid, sps, p_Vid->p_LayerPar[0]);}else if(p_Vid->dpb_layer_id==1 && is_EL_profile(sps->profile_idc) && !p_Vid->p_Dpb_layer[1]->init_done){set_coding_par(sps, p_Vid->p_EncodePar[1]);setup_layer_info(p_Vid, sps, p_Vid->p_LayerPar[1]);}//to be removed in future;set_global_coding_par(p_Vid, p_Vid->p_EncodePar[p_Vid->dpb_layer_id]);
//end;#if (MVC_EXTENSION_ENABLE)//init_frext(p_Vid);if (/*p_Vid->last_pic_width_in_mbs_minus1 != p_Vid->active_sps->pic_width_in_mbs_minus1|| p_Vid->last_pic_height_in_map_units_minus1 != p_Vid->active_sps->pic_height_in_map_units_minus1|| p_Vid->last_max_dec_frame_buffering != GetMaxDecFrameBuffering(p_Vid)|| */(p_Vid->last_profile_idc != p_Vid->active_sps->profile_idc && is_BL_profile(p_Vid->active_sps->profile_idc) && !p_Vid->p_Dpb_layer[0]->init_done /*&& is_BL_profile(p_Vid->last_profile_idc)*/)){//init_frext(p_Vid);init_global_buffers(p_Vid, 0);if (!p_Vid->no_output_of_prior_pics_flag){flush_dpb(p_Vid->p_Dpb_layer[0]);flush_dpb(p_Vid->p_Dpb_layer[1]);}init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);}else if(p_Vid->last_profile_idc != p_Vid->active_sps->profile_idc && (is_MVC_profile(p_Vid->last_profile_idc) || is_MVC_profile(p_Vid->active_sps->profile_idc))&& (!p_Vid->p_Dpb_layer[1]->init_done)){assert(p_Vid->p_Dpb_layer[0]->init_done);//init_frext(p_Vid);if(p_Vid->p_Dpb_layer[0]->init_done){free_dpb(p_Vid->p_Dpb_layer[0]);init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);}init_global_buffers(p_Vid, 1);// for now lets re_init both buffers. Later, we should only re_init appropriate one// Note that we seem to be doing this for every frame which seems not good.//re_init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#if MVC_EXTENSION_ENABLEinit_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#endif//p_Vid->last_profile_idc = p_Vid->active_sps->profile_idc;}//p_Vid->p_Dpb_layer[0]->num_ref_frames = p_Vid->active_sps->num_ref_frames;//p_Vid->p_Dpb_layer[1]->num_ref_frames = p_Vid->active_sps->num_ref_frames;p_Vid->last_pic_width_in_mbs_minus1 = p_Vid->active_sps->pic_width_in_mbs_minus1;  p_Vid->last_pic_height_in_map_units_minus1 = p_Vid->active_sps->pic_height_in_map_units_minus1;p_Vid->last_max_dec_frame_buffering = GetMaxDecFrameBuffering(p_Vid);p_Vid->last_profile_idc = p_Vid->active_sps->profile_idc;#else//init_frext(p_Vid);init_global_buffers(p_Vid, 0);if (!p_Vid->no_output_of_prior_pics_flag){flush_dpb(p_Vid->p_Dpb_layer[0]);}init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0);// for now lets init both buffers. Later, we should only re_init appropriate one//init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 1);// obviously this is not needed her but just adding it for completeness//init_dpb(p_Vid, p_Vid->p_Dpb_layer[1], 2);
#endif#if (DISABLE_ERC == 0)ercInit(p_Vid, p_Vid->width, p_Vid->height, 1);if(p_Vid->dec_picture){ercReset(p_Vid->erc_errorVar, p_Vid->PicSizeInMbs, p_Vid->PicSizeInMbs, p_Vid->dec_picture->size_x);p_Vid->erc_mvperMB = 0;}
#endif}reset_format_info(sps, p_Vid, &p_Inp->source, &p_Inp->output);
}

在激活sps时,有init_global_buffers()

int init_global_buffers(VideoParameters *p_Vid, int layer_id)
{int memory_size=0;int i;CodingParameters *cps = p_Vid->p_EncodePar[layer_id];BlockPos* PicPos;if (p_Vid->global_init_done[layer_id]){free_layer_buffers(p_Vid, layer_id);}// allocate memory for reference frame in find_snrmemory_size += get_mem2Dpel(&cps->imgY_ref, cps->height, cps->width);if (cps->yuv_format != YUV400){memory_size += get_mem3Dpel(&cps->imgUV_ref, 2, cps->height_cr, cps->width_cr);}elsecps->imgUV_ref = NULL;// allocate memory in structure p_Vidif( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){if(((cps->mb_data_JV[i]) = (Macroblock *) calloc(cps->FrameSizeInMbs, sizeof(Macroblock))) == NULL)no_mem_exit("init_global_buffers: cps->mb_data_JV");}cps->mb_data = NULL;}else{if(((cps->mb_data) = (Macroblock *) calloc(cps->FrameSizeInMbs, sizeof(Macroblock))) == NULL)no_mem_exit("init_global_buffers: cps->mb_data");}if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){if(((cps->intra_block_JV[i]) = (char*) calloc(cps->FrameSizeInMbs, sizeof(char))) == NULL)no_mem_exit("init_global_buffers: cps->intra_block_JV");}cps->intra_block = NULL;}else{if(((cps->intra_block) = (char*) calloc(cps->FrameSizeInMbs, sizeof(char))) == NULL)no_mem_exit("init_global_buffers: cps->intra_block");}//memory_size += get_mem2Dint(&PicPos,p_Vid->FrameSizeInMbs + 1,2);  //! Helper array to access macroblock positions. We add 1 to also consider last MB.if(((cps->PicPos) = (BlockPos*) calloc(cps->FrameSizeInMbs + 1, sizeof(BlockPos))) == NULL)no_mem_exit("init_global_buffers: PicPos");PicPos = cps->PicPos;for (i = 0; i < (int) cps->FrameSizeInMbs + 1;++i){PicPos[i].x = (short) (i % cps->PicWidthInMbs);PicPos[i].y = (short) (i / cps->PicWidthInMbs);}if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){get_mem2D(&(cps->ipredmode_JV[i]), 4*cps->FrameHeightInMbs, 4*cps->PicWidthInMbs);}cps->ipredmode = NULL;}elsememory_size += get_mem2D(&(cps->ipredmode), 4*cps->FrameHeightInMbs, 4*cps->PicWidthInMbs);// CAVLC memmemory_size += get_mem4D(&(cps->nz_coeff), cps->FrameSizeInMbs, 3, BLOCK_SIZE, BLOCK_SIZE);if( (cps->separate_colour_plane_flag != 0) ){for( i=0; i<MAX_PLANE; ++i ){get_mem2Dint(&(cps->siblock_JV[i]), cps->FrameHeightInMbs, cps->PicWidthInMbs);if(cps->siblock_JV[i]== NULL)no_mem_exit("init_global_buffers: p_Vid->siblock_JV");}cps->siblock = NULL;}else{memory_size += get_mem2Dint(&(cps->siblock), cps->FrameHeightInMbs, cps->PicWidthInMbs);}init_qp_process(cps);cps->oldFrameSizeInMbs = cps->FrameSizeInMbs;if(layer_id == 0 )init_output(cps, ((cps->pic_unit_bitsize_on_disk+7) >> 3));elsecps->img2buf = p_Vid->p_EncodePar[0]->img2buf;p_Vid->global_init_done[layer_id] = 1;return (memory_size);
}

qp 到反向量化矩阵是一个映射关系,由一个表定义。qp/6 和qp%6的值决定了矩阵中的相应位置上的值。CodingParameters中的qp_per_matrix 是qp/6的值的数组,qp_rem_matrix是qp%6的数组,便于直接通过qp获取到这两个值。init_qp_process 的工作就是初始化这两个数组。

void init_qp_process(CodingParameters *cps)
{int bitdepth_qp_scale = imax(cps->bitdepth_luma_qp_scale, cps->bitdepth_chroma_qp_scale);int i;// We should allocate memory outside of this process since maybe we will have a change of SPS // and we may need to recreate these. Currently should only support same bitdepthif (cps->qp_per_matrix == NULL)if ((cps->qp_per_matrix = (int*)malloc((MAX_QP + 1 +  bitdepth_qp_scale)*sizeof(int))) == NULL)no_mem_exit("init_qp_process: cps->qp_per_matrix");if (cps->qp_rem_matrix == NULL)if ((cps->qp_rem_matrix = (int*)malloc((MAX_QP + 1 +  bitdepth_qp_scale)*sizeof(int))) == NULL)no_mem_exit("init_qp_process: cps->qp_rem_matrix");for (i = 0; i < MAX_QP + bitdepth_qp_scale + 1; i++){cps->qp_per_matrix[i] = i / 6;cps->qp_rem_matrix[i] = i % 6;}
}
static void set_coding_par(seq_parameter_set_rbsp_t *sps, CodingParameters *cps)
{// maximum vertical motion vector range in luma quarter pixel unitscps->profile_idc = sps->profile_idc;cps->lossless_qpprime_flag   = sps->lossless_qpprime_flag;if (sps->level_idc <= 10){cps->max_vmv_r = 64 * 4;}else if (sps->level_idc <= 20){cps->max_vmv_r = 128 * 4;}else if (sps->level_idc <= 30){cps->max_vmv_r = 256 * 4;}else{cps->max_vmv_r = 512 * 4; // 512 pixels in quarter pixels}// Fidelity Range Extensions stuff (part 1)cps->bitdepth_chroma = 0;cps->width_cr        = 0;cps->height_cr       = 0;亮度bit深度cps->bitdepth_luma       = (short) (sps->bit_depth_luma_minus8 + 8);cps->bitdepth_scale[0]   = 1 << sps->bit_depth_luma_minus8;if (sps->chroma_format_idc != YUV400){有色度分量时cps->bitdepth_chroma   = (short) (sps->bit_depth_chroma_minus8 + 8);cps->bitdepth_scale[1] = 1 << sps->bit_depth_chroma_minus8;}
最大帧号cps->max_frame_num = 1<<(sps->log2_max_frame_num_minus4+4);cps->PicWidthInMbs = (sps->pic_width_in_mbs_minus1 +1);cps->PicHeightInMapUnits = (sps->pic_height_in_map_units_minus1 +1);cps->FrameHeightInMbs = ( 2 - sps->frame_mbs_only_flag ) * cps->PicHeightInMapUnits;cps->FrameSizeInMbs = cps->PicWidthInMbs * cps->FrameHeightInMbs;
输入原始图像格式cps->yuv_format=sps->chroma_format_idc;色彩通道是否分离[source参数描述](https://blog.csdn.net/dongkun152/article/details/118912591?spm=1001.2014.3001.5501)cps->separate_colour_plane_flag = sps->separate_colour_plane_flag;if( cps->separate_colour_plane_flag ){cps->ChromaArrayType = 0;}else{cps->ChromaArrayType = sps->chroma_format_idc;}
宏块尺寸默认16*16cps->width = cps->PicWidthInMbs * MB_BLOCK_SIZE;cps->height = cps->FrameHeightInMbs * MB_BLOCK_SIZE;  cps->iLumaPadX = MCBUF_LUMA_PAD_X;cps->iLumaPadY = MCBUF_LUMA_PAD_Y;cps->iChromaPadX = MCBUF_CHROMA_PAD_X;cps->iChromaPadY = MCBUF_CHROMA_PAD_Y;if (sps->chroma_format_idc == YUV420){YUV420时 色度是亮度的一半cps->width_cr  = (cps->width  >> 1);cps->height_cr = (cps->height >> 1);}else if (sps->chroma_format_idc == YUV422){cps->width_cr  = (cps->width >> 1);cps->height_cr = cps->height;cps->iChromaPadY = MCBUF_CHROMA_PAD_Y*2;}else if (sps->chroma_format_idc == YUV444){//YUV444cps->width_cr = cps->width;cps->height_cr = cps->height;cps->iChromaPadX = cps->iLumaPadX;cps->iChromaPadY = cps->iLumaPadY;}//pel bitdepth initcps->bitdepth_luma_qp_scale   = 6 * (cps->bitdepth_luma - 8);if(cps->bitdepth_luma > cps->bitdepth_chroma || sps->chroma_format_idc == YUV400)cps->pic_unit_bitsize_on_disk = (cps->bitdepth_luma > 8)? 16:8;elsecps->pic_unit_bitsize_on_disk = (cps->bitdepth_chroma > 8)? 16:8;cps->dc_pred_value_comp[0]    = 1<<(cps->bitdepth_luma - 1);cps->max_pel_value_comp[0] = (1<<cps->bitdepth_luma) - 1;宏块只存16*16cps->mb_size[0][0] = cps->mb_size[0][1] = MB_BLOCK_SIZE;if (sps->chroma_format_idc != YUV400){//for chrominance partcps->bitdepth_chroma_qp_scale = 6 * (cps->bitdepth_chroma - 8);cps->dc_pred_value_comp[1]    = (1 << (cps->bitdepth_chroma - 1));cps->dc_pred_value_comp[2]    = cps->dc_pred_value_comp[1];cps->max_pel_value_comp[1]    = (1 << cps->bitdepth_chroma) - 1;cps->max_pel_value_comp[2]    = (1 << cps->bitdepth_chroma) - 1;cps->num_blk8x8_uv = (1 << sps->chroma_format_idc) & (~(0x1));cps->num_uv_blocks = (cps->num_blk8x8_uv >> 1);cps->num_cdc_coeff = (cps->num_blk8x8_uv << 1);cps->mb_size[1][0] = cps->mb_size[2][0] = cps->mb_cr_size_x  = (sps->chroma_format_idc==YUV420 || sps->chroma_format_idc==YUV422)?  8 : 16;cps->mb_size[1][1] = cps->mb_size[2][1] = cps->mb_cr_size_y  = (sps->chroma_format_idc==YUV444 || sps->chroma_format_idc==YUV422)? 16 :  8;cps->subpel_x    = cps->mb_cr_size_x == 8 ? 7 : 3;cps->subpel_y    = cps->mb_cr_size_y == 8 ? 7 : 3;cps->shiftpel_x  = cps->mb_cr_size_x == 8 ? 3 : 2;cps->shiftpel_y  = cps->mb_cr_size_y == 8 ? 3 : 2;cps->total_scale = cps->shiftpel_x + cps->shiftpel_y;}else{cps->bitdepth_chroma_qp_scale = 0;cps->max_pel_value_comp[1] = 0;cps->max_pel_value_comp[2] = 0;cps->num_blk8x8_uv = 0;cps->num_uv_blocks = 0;cps->num_cdc_coeff = 0;cps->mb_size[1][0] = cps->mb_size[2][0] = cps->mb_cr_size_x  = 0;cps->mb_size[1][1] = cps->mb_size[2][1] = cps->mb_cr_size_y  = 0;cps->subpel_x      = 0;cps->subpel_y      = 0;cps->shiftpel_x    = 0;cps->shiftpel_y    = 0;cps->total_scale   = 0;}cps->mb_cr_size = cps->mb_cr_size_x * cps->mb_cr_size_y;cps->mb_size_blk[0][0] = cps->mb_size_blk[0][1] = cps->mb_size[0][0] >> 2;cps->mb_size_blk[1][0] = cps->mb_size_blk[2][0] = cps->mb_size[1][0] >> 2;cps->mb_size_blk[1][1] = cps->mb_size_blk[2][1] = cps->mb_size[1][1] >> 2;cps->mb_size_shift[0][0] = cps->mb_size_shift[0][1] = CeilLog2_sf (cps->mb_size[0][0]);cps->mb_size_shift[1][0] = cps->mb_size_shift[2][0] = CeilLog2_sf (cps->mb_size[1][0]);cps->mb_size_shift[1][1] = cps->mb_size_shift[2][1] = CeilLog2_sf (cps->mb_size[1][1]);cps->rgb_output =  (sps->vui_seq_parameters.matrix_coefficients==0);
}

分配量化参数

/*!************************************************************************* \brief*    For mapping the q-matrix to the active id and calculate quantisation values** \param currSlice*    Slice pointer* \param pps*    Picture parameter set* \param sps*    Sequence parameter set**************************************************************************/
void assign_quant_params(Slice *currSlice)
{seq_parameter_set_rbsp_t* sps = currSlice->active_sps;pic_parameter_set_rbsp_t* pps = currSlice->active_pps;int i;int n_ScalingList;
当sps和pps中放大系数矩阵都不存在时,使用的默认的参数if(!pps->pic_scaling_matrix_present_flag && !sps->seq_scaling_matrix_present_flag){for(i=0; i<12; i++)currSlice->qmatrix[i] = (i < 6) ? quant_org : quant8_org;}else{n_ScalingList = (sps->chroma_format_idc != YUV444) ? 8 : 12;if(sps->seq_scaling_matrix_present_flag) // check sps first{for(i=0; i<n_ScalingList; i++){if(i<6){if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A{if(i==0)currSlice->qmatrix[i] = quant_intra_default;else if(i==3)currSlice->qmatrix[i] = quant_inter_default;elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-1];}else{if(sps->UseDefaultScalingMatrix4x4Flag[i])currSlice->qmatrix[i] = (i<3) ? quant_intra_default : quant_inter_default;elsecurrSlice->qmatrix[i] = sps->ScalingList4x4[i];}}else{if(!sps->seq_scaling_list_present_flag[i]) // fall-back rule A{if(i==6)currSlice->qmatrix[i] = quant8_intra_default;else if(i==7)currSlice->qmatrix[i] = quant8_inter_default;elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-2];}else{if(sps->UseDefaultScalingMatrix8x8Flag[i-6])currSlice->qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;elsecurrSlice->qmatrix[i] = sps->ScalingList8x8[i-6];}}}}if(pps->pic_scaling_matrix_present_flag) // then check pps{for(i=0; i<n_ScalingList; i++){if(i<6){if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B{if (i==0){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant_intra_default;}else if (i==3){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant_inter_default;}elsecurrSlice->qmatrix[i] = currSlice->qmatrix[i-1];}else{if(pps->UseDefaultScalingMatrix4x4Flag[i])currSlice->qmatrix[i] = (i<3) ? quant_intra_default:quant_inter_default;elsecurrSlice->qmatrix[i] = pps->ScalingList4x4[i];}}else{if(!pps->pic_scaling_list_present_flag[i]) // fall-back rule B{if (i==6){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant8_intra_default;}else if(i==7){if(!sps->seq_scaling_matrix_present_flag)currSlice->qmatrix[i] = quant8_inter_default;}else  currSlice->qmatrix[i] = currSlice->qmatrix[i-2];}else{if(pps->UseDefaultScalingMatrix8x8Flag[i-6])currSlice->qmatrix[i] = (i==6 || i==8 || i==10) ? quant8_intra_default:quant8_inter_default;elsecurrSlice->qmatrix[i] = pps->ScalingList8x8[i-6];}}}}}
计算实际使用的4x4量化参数CalculateQuant4x4Param(currSlice);if(pps->transform_8x8_mode_flag)CalculateQuant8x8Param(currSlice);
}

计算量化参数就是在 dequant_coef反量化系数矩阵每个元素上乘以默认放大矩阵的每个元素。

/*!************************************************************************* \brief*    For calculating the quantisation values at frame level**************************************************************************/
void CalculateQuant4x4Param(Slice *currSlice)
{int k;const int (*p_dequant_coef)[4][4] = dequant_coef;int  (*InvLevelScale4x4_Intra_0)[4][4] = currSlice->InvLevelScale4x4_Intra[0];int  (*InvLevelScale4x4_Intra_1)[4][4] = currSlice->InvLevelScale4x4_Intra[1];int  (*InvLevelScale4x4_Intra_2)[4][4] = currSlice->InvLevelScale4x4_Intra[2];int  (*InvLevelScale4x4_Inter_0)[4][4] = currSlice->InvLevelScale4x4_Inter[0];int  (*InvLevelScale4x4_Inter_1)[4][4] = currSlice->InvLevelScale4x4_Inter[1];int  (*InvLevelScale4x4_Inter_2)[4][4] = currSlice->InvLevelScale4x4_Inter[2];for(k=0; k<6; k++){set_dequant4x4(*InvLevelScale4x4_Intra_0++, *p_dequant_coef  , currSlice->qmatrix[0]);set_dequant4x4(*InvLevelScale4x4_Intra_1++, *p_dequant_coef  , currSlice->qmatrix[1]);set_dequant4x4(*InvLevelScale4x4_Intra_2++, *p_dequant_coef  , currSlice->qmatrix[2]);set_dequant4x4(*InvLevelScale4x4_Inter_0++, *p_dequant_coef  , currSlice->qmatrix[3]);set_dequant4x4(*InvLevelScale4x4_Inter_1++, *p_dequant_coef  , currSlice->qmatrix[4]);set_dequant4x4(*InvLevelScale4x4_Inter_2++, *p_dequant_coef++, currSlice->qmatrix[5]);}
}static void set_dequant4x4(int (*InvLevelScale4x4)[4],  const int (*dequant)[4], int *qmatrix)
{int j;for(j=0; j<4; j++){*(*InvLevelScale4x4      ) = *(*dequant      ) * *qmatrix++;*(*InvLevelScale4x4   + 1) = *(*dequant   + 1) * *qmatrix++;*(*InvLevelScale4x4   + 2) = *(*dequant   + 2) * *qmatrix++;*(*InvLevelScale4x4++ + 3) = *(*dequant++ + 3) * *qmatrix++;}
}

反量化关于QP的函数矩阵如下
参考变换和量化

//! Dequantization coefficients
static const int dequant_coef[6][4][4] = {{{ 10, 13, 10, 13},{ 13, 16, 13, 16},{ 10, 13, 10, 13},{ 13, 16, 13, 16}},{{ 11, 14, 11, 14},{ 14, 18, 14, 18},{ 11, 14, 11, 14},{ 14, 18, 14, 18}},{{ 13, 16, 13, 16},{ 16, 20, 16, 20},{ 13, 16, 13, 16},{ 16, 20, 16, 20}},{{ 14, 18, 14, 18},{ 18, 23, 18, 23},{ 14, 18, 14, 18},{ 18, 23, 18, 23}},{{ 16, 20, 16, 20},{ 20, 25, 20, 25},{ 16, 20, 16, 20},{ 20, 25, 20, 25}},{{ 18, 23, 18, 23},{ 23, 29, 23, 29},{ 18, 23, 18, 23},{ 23, 29, 23, 29}}
};

slice_data 处理

开始读取slice_data, setup_slice_methods()根据不同的slice type 设置回调函数。

/*!************************************************************************* \brief*    Set mode interpretation based on slice type*************************************************************************/
void setup_slice_methods(Slice *currSlice)
{setup_read_macroblock (currSlice);switch (currSlice->slice_type){case P_SLICE: currSlice->interpret_mb_mode         = interpret_mb_mode_P;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_p_slice;currSlice->decode_one_component      = decode_one_component_p_slice;currSlice->update_direct_mv_info     = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists                = currSlice->view_id ? init_lists_p_slice_mvc : init_lists_p_slice;
#elsecurrSlice->init_lists                = init_lists_p_slice;
#endifbreak;case SP_SLICE:currSlice->interpret_mb_mode         = interpret_mb_mode_P;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_p_slice;currSlice->decode_one_component      = decode_one_component_sp_slice;currSlice->update_direct_mv_info     = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists                = currSlice->view_id ? init_lists_p_slice_mvc : init_lists_p_slice;
#elsecurrSlice->init_lists                = init_lists_p_slice;
#endifbreak;case B_SLICE:currSlice->interpret_mb_mode         = interpret_mb_mode_B;currSlice->read_motion_info_from_NAL = read_motion_info_from_NAL_b_slice;currSlice->decode_one_component      = decode_one_component_b_slice;update_direct_types(currSlice);
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists                = currSlice->view_id ? init_lists_b_slice_mvc : init_lists_b_slice;
#elsecurrSlice->init_lists                = init_lists_b_slice;
#endifbreak;case I_SLICE: currSlice->interpret_mb_mode         = interpret_mb_mode_I;currSlice->read_motion_info_from_NAL = NULL;currSlice->decode_one_component      = decode_one_component_i_slice;currSlice->update_direct_mv_info     = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists                = currSlice->view_id ? init_lists_i_slice_mvc : init_lists_i_slice;
#elsecurrSlice->init_lists                = init_lists_i_slice;
#endifbreak;case SI_SLICE: currSlice->interpret_mb_mode         = interpret_mb_mode_SI;currSlice->read_motion_info_from_NAL = NULL;currSlice->decode_one_component      = decode_one_component_i_slice;currSlice->update_direct_mv_info     = NULL;
#if (MVC_EXTENSION_ENABLE)currSlice->init_lists                = currSlice->view_id ? init_lists_i_slice_mvc : init_lists_i_slice;
#elsecurrSlice->init_lists                = init_lists_i_slice;
#endifbreak;default:printf("Unsupported slice type\n");break;}set_intra_prediction_modes(currSlice);if ( currSlice->p_Vid->active_sps->chroma_format_idc==YUV444 && (currSlice->p_Vid->separate_colour_plane_flag == 0) )currSlice->read_coeff_4x4_CAVLC = read_coeff_4x4_CAVLC_444;elsecurrSlice->read_coeff_4x4_CAVLC = read_coeff_4x4_CAVLC;switch(currSlice->p_Vid->active_pps->entropy_coding_mode_flag){case CABAC:set_read_CBP_and_coeffs_cabac(currSlice);break;case CAVLC:set_read_CBP_and_coeffs_cavlc(currSlice);break;default:printf("Unsupported entropy coding mode\n");break;}
}
void set_intra_prediction_modes(Slice *currSlice)
{ if (currSlice->mb_aff_frame_flag){currSlice->intra_pred_4x4    = intra_pred_4x4_mbaff;currSlice->intra_pred_8x8    = intra_pred_8x8_mbaff;currSlice->intra_pred_16x16  = intra_pred_16x16_mbaff;    currSlice->intra_pred_chroma = intra_pred_chroma_mbaff;}else{currSlice->intra_pred_4x4    = intra_pred_4x4_normal;  currSlice->intra_pred_8x8    = intra_pred_8x8_normal;currSlice->intra_pred_16x16  = intra_pred_16x16_normal;currSlice->intra_pred_chroma = intra_pred_chroma;   }
}
void set_read_CBP_and_coeffs_cabac(Slice *currSlice)
{switch (currSlice->p_Vid->active_sps->chroma_format_idc){case YUV444:if (currSlice->p_Vid->separate_colour_plane_flag == 0){currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_444;}else{currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_400;}break;case YUV422:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_422;break;case YUV420:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_420;break;case YUV400:currSlice->read_CBP_and_coeffs_from_NAL = read_CBP_and_coeffs_from_NAL_CABAC_400;break;default:assert (1);currSlice->read_CBP_and_coeffs_from_NAL = NULL;break;}
}

JM ldecod分析: 分帧处理相关推荐

  1. 基于MATLAB的语音信号的时域特性分析(一)——分帧、窗函数

      语音信号是一个非稳态的.时变的信号.但在"短时间"范围内可以认为语音信号是稳态的.时不变的.这个短时间一般值10~30ms.由于有这个特性,故常把语音信号称为"准稳态 ...

  2. 关于语音分帧时有重叠部分的原因分析

    在用Matlab进行语音分析时,通常会用读入的数据进行分帧处理.在分帧中,往往设置在相邻两帧之间有一部分重叠. 其原因是:语音信号是时变的,在短时范围内特征变化较小,所以做为稳态来处理:但超出这短时范 ...

  3. 语音信号分析(语音分帧)

    语音分帧 不管是进行什么参数分析以及采用什么分析方法,都需要一些预先的处理,如语音信号的数字化.语音信号的端点检测.预加重.加窗和分帧等,这些也是不可忽视的语音信号分析的关键技术.贯穿于语音分析全过程 ...

  4. 音频处理四:(音频的分帧)

    程序设计四:音频的分帧 一:需求分析 为了分析读人数据,通常进行分帧处理.在分帧中,往往设置在相邻两帧之间有一部分重叠.其原因是:语音信号是时变的,在短时范围内特征变化较小,所以作为稳态来处理;但超出 ...

  5. 语音信号处理基础(五)——语音分帧与加窗

    文章目录 原理 1.加窗 2.分帧 一般而言语音处理的目的有两种: 一种是对语音信号进行分析,提取特征参数,用于后续处理: 提取的特征参数主要有语音的短时能量和平均幅度.短时平均过零率.短时自相关函数 ...

  6. 语音信号处理中怎么理解分帧?

    那么一帧有多长呢?帧长要满足两个条件: 从宏观上看,它必须足够短来保证帧内信号是平稳的. 前面说过,口型的变化是导致信号不平稳的原因,所以在一帧的期间内口型不能有明显变化,即一帧的长度应当小于一个音素 ...

  7. 已开源!Flutter 基于分帧渲染的流畅度优化组件 Keframe

    大家好,这里是承香墨影! 今天给大家推荐一个,Flutter 中利用分帧渲染优化流程度的开源库,刚开源,还热乎着.这次开源可真波折,看着 @Nayuta 前前后后在公司内部流程走了一个多月吧,太艰难了 ...

  8. matlab语音分帧加窗,语音信号的加窗处理

    平稳的随机过程是研究语音信号的主要手段,但是语音信号本身并不是平衡的. 一,语音信号不平稳 语音信号在产生过程中与环境和发声器官的联系很紧密,与各种运动都是相关的,信号本身是不平移的信号.主要是由于发 ...

  9. python对语音信号读取、分帧、加窗

    python对语音信号读取.分帧.加窗 一.读入音频信号 语音信号有三个重要的参数:声道数.取样频率和量化位数. 声道数:单声道或者双声道 采样频率:一秒钟对声音采样的次数,例如10000HZ代表一秒 ...

最新文章

  1. 全国自考微型计算机原理及其应用,2010年10月全国自考微型计算机原理及应用试题...
  2. hdu4081 最小树+DFS或者次小树的变形
  3. 不动产登记证书曝光 一个“改变”必须注意(图)
  4. ES-PHP向ES批量添加文档报No alive nodes found in your cluster
  5. .NET Core系列 : 2 、project.json 这葫芦里卖的什么药
  6. 编写高性能 Web 应用程序的 10 个技巧 (转)
  7. vb.net 窗体接收键盘事件_(十五)C#WinFrom自定义控件系列-键盘(二)
  8. Oracle杂谈二 SQL*PLUS命令的使用大全
  9. Eclipse Egit 安装
  10. Android图片的三级缓存整理
  11. 蓝桥杯题目练习 水题 [蓝桥杯2019初赛]矩形切割
  12. 基于STM32战舰开发板的内部温度传感器实验
  13. 如今表情包的天下,曾经可是颜文字和Emoji的啊...
  14. Python每日一练(23)-基于百度 AI 识别抓取的表情包
  15. 多目标进化算法详细讲解及代码实现(样例:MOEA/D、NSGA-Ⅱ求解多目标(柔性)作业车间调度问题)
  16. 概率统计Python计算:贝叶斯公式
  17. 【数字IC/FPGA】仲裁器进阶--Round Robin Arbiter
  18. 如何高效地使用ERP管理系统
  19. 卡罗拉 (COROLLA) - 油箱盖
  20. LMS自适应滤波matlab仿真

热门文章

  1. 如何利用互联网工具深入调研你仰慕已久的网站
  2. 8086 引脚及其功能
  3. 前端js实现在线预览pdf、word、xls、ppt等文件
  4. 真香!IDEA 最新版本,支持免打扰模式!
  5. AMD葫芦里面卖的什么药?
  6. 修改Windows10电脑日期时间格式显示星期
  7. 基于Qt的类QQ气泡聊天的界面开发(二)
  8. 深圳市住房公积金管理中心
  9. 女仆萝莉装的花边如何画?超简单的荷叶褶边画法
  10. 环境变量 env 设置 c语言 头文件,CentOS 设置环境变量