博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JM8.6中NALU(此处指非VCL式的NALU,如SPS和PPS)是如何写进码流的?
阅读量:4141 次
发布时间:2019-05-25

本文共 8390 字,大约阅读时间需要 27 分钟。

       先看lencod.c中的GenerateParameterSets函数,进入其中:

void GenerateParameterSets (){  seq_parameter_set_rbsp_t *sps = NULL;   pic_parameter_set_rbsp_t *pps = NULL;  sps = AllocSPS();  // 分配堆空间  pps = AllocPPS();  // 分配堆空间  FillParameterSetStructures (sps, pps);    active_sps = sps; // active_sps和下面的active_pps都是global.h中定义的全局变量  active_pps = pps;}

      进入FillParameterSetStructures函数看看:

void FillParameterSetStructures (seq_parameter_set_rbsp_t *sps,                                  pic_parameter_set_rbsp_t *pps){  unsigned i;  // *************************************************************************  // Sequence Parameter Set  // *************************************************************************  assert (sps != NULL);  assert (pps != NULL);  // Profile and Level should be calculated using the info from the config  // file.  Calculation is hidden in IndetifyProfile() and IdentifyLevel()  sps->profile_idc = IdentifyProfile();  sps->level_idc = IdentifyLevel();  // needs to be set according to profile  sps->constrained_set0_flag = 0;  sps->constrained_set1_flag = 0;  sps->constrained_set2_flag = 0;  // Parameter Set ID hardcoded to zero  sps->seq_parameter_set_id = 0;  //! POC stuff:  //! The following values are hard-coded in init_poc().  Apparently,  //! the poc implementation covers only a subset of the poc functionality.  //! Here, the same subset is implemented.  Changes in the POC stuff have  //! also to be reflected here  sps->log2_max_frame_num_minus4 = log2_max_frame_num_minus4;  sps->log2_max_pic_order_cnt_lsb_minus4 = log2_max_pic_order_cnt_lsb_minus4;    sps->pic_order_cnt_type = input->pic_order_cnt_type;  sps->num_ref_frames_in_pic_order_cnt_cycle = img->num_ref_frames_in_pic_order_cnt_cycle;  sps->delta_pic_order_always_zero_flag = img->delta_pic_order_always_zero_flag;  sps->offset_for_non_ref_pic = img->offset_for_non_ref_pic;  sps->offset_for_top_to_bottom_field = img->offset_for_top_to_bottom_field;  for (i=0; i
num_ref_frames_in_pic_order_cnt_cycle; i++) { sps->offset_for_ref_frame[i] = img->offset_for_ref_frame[i]; } // End of POC stuff // Number of Reference Frames sps->num_ref_frames = IdentifyNumRefFrames(); //required_frame_num_update_behaviour_flag hardcoded to zero sps->gaps_in_frame_num_value_allowed_flag = FALSE; // double check sps->frame_mbs_only_flag = !(input->PicInterlace || input->MbInterlace); // Picture size, finally a simple one :-) sps->pic_width_in_mbs_minus1 = (input->img_width/16) -1; sps->pic_height_in_map_units_minus1 = ((input->img_height/16)/ (2 - sps->frame_mbs_only_flag)) - 1; // a couple of flags, simple sps->mb_adaptive_frame_field_flag = (FRAME_CODING != input->MbInterlace); sps->direct_8x8_inference_flag = input->directInferenceFlag; // Sequence VUI not implemented, signalled as not present sps->vui_parameters_present_flag = FALSE; { int PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs; int width, height; PicWidthInMbs = (sps->pic_width_in_mbs_minus1 +1); PicHeightInMapUnits = (sps->pic_height_in_map_units_minus1 +1); FrameHeightInMbs = ( 2 - sps->frame_mbs_only_flag ) * PicHeightInMapUnits; width = PicWidthInMbs * MB_BLOCK_SIZE; height = FrameHeightInMbs * MB_BLOCK_SIZE; Co_located = alloc_colocated (width, height,sps->mb_adaptive_frame_field_flag); } // ************************************************************************* // Picture Parameter Set // ************************************************************************* pps->seq_parameter_set_id = 0; pps->pic_parameter_set_id = 0; pps->entropy_coding_mode_flag = (input->symbol_mode==UVLC?0:1); // JVT-Fxxx (by Stephan Wenger, make this flag unconditional pps->pic_order_present_flag = img->pic_order_present_flag; // Begin FMO stuff pps->num_slice_groups_minus1 = input->num_slice_groups_minus1; //! Following set the parameter for different slice group types if (pps->num_slice_groups_minus1 > 0) switch (input->slice_group_map_type) { case 0: pps->slice_group_map_type = 0; for(i=0; i<=pps->num_slice_groups_minus1; i++) { pps->run_length_minus1[i]=input->run_length_minus1[i]; } break; case 1: pps->slice_group_map_type = 1; break; case 2: // i loops from 0 to num_slice_groups_minus1-1, because no info for background needed pps->slice_group_map_type = 2; for(i=0; i
num_slice_groups_minus1; i++) { pps->top_left[i] = input->top_left[i]; pps->bottom_right[i] = input->bottom_right[i]; } break; case 3: case 4: case 5: pps->slice_group_map_type = input->slice_group_map_type; pps->slice_group_change_direction_flag = input->slice_group_change_direction_flag; pps->slice_group_change_rate_minus1 = input->slice_group_change_rate_minus1; break; case 6: pps->slice_group_map_type = 6; pps->pic_size_in_map_units_minus1 = ((input->img_height/MB_BLOCK_SIZE)/(2-sps->frame_mbs_only_flag)) *(input->img_width/MB_BLOCK_SIZE) -1; for (i=0;i<=pps->pic_size_in_map_units_minus1; i++) pps->slice_group_id[i] = input->slice_group_id[i]; break; default: printf ("Parset.c: slice_group_map_type invalid, default\n"); assert (0==1); }// End FMO stuff pps->num_ref_idx_l0_active_minus1 = sps->frame_mbs_only_flag ? (sps->num_ref_frames-1) : (2 * sps->num_ref_frames - 1) ; // set defaults pps->num_ref_idx_l1_active_minus1 = sps->frame_mbs_only_flag ? (sps->num_ref_frames-1) : (2 * sps->num_ref_frames - 1) ; // set defaults //pps->num_ref_idx_l1_active_minus1 = sps->frame_mbs_only_flag ? 0 : 1 ; // set defaults pps->weighted_pred_flag = input->WeightedPrediction; pps->weighted_bipred_idc = input->WeightedBiprediction; pps->pic_init_qp_minus26 = 0; // hard coded to zero, QP lives in the slice header pps->pic_init_qs_minus26 = 0; pps->chroma_qp_index_offset = input->chroma_qp_index_offset; // double check: is this chroma fidelity thing already implemented??? pps->deblocking_filter_control_present_flag = input->LFSendParameters; pps->constrained_intra_pred_flag = input->UseConstrainedIntraPred; pps->redundant_pic_cnt_present_flag = 0; // the picture vui consists currently of the cropping rectangle, which cannot // used by the current decoder and hence is never sent. sps->frame_cropping_flag = FALSE;};

      可见,FillParameterSetStructures函数的作用是对sps->...和pps->...进行赋值,其中很多值都是从input->...和img->...中得到的,而后两者中的很多值是从配置文件中得到的. 经过对active_sps和active_pps赋值后,active_sps和active_pps就得到了相应的值(有些是间接从配置文件中获得的)

 

      继续看start_sequence函数:

int start_sequence(){  int len=0;  NALU_t *nalu;  switch(input->of_mode)  {    case PAR_OF_ANNEXB:      OpenAnnexbFile (input->outfile);      WriteNALU = WriteAnnexbNALU;      break;    case PAR_OF_RTP:      OpenRTPFile (input->outfile);      WriteNALU = WriteRTPNALU;      break;    default:      snprintf(errortext, ET_SIZE, "Output File Mode %d not supported", input->of_mode);      error(errortext,1);      return 1;  }  //! As a sequence header, here we write the both sequence and picture  //! parameter sets.  As soon as IDR is implemented, this should go to the  //! IDR part, as both parsets have to be transmitted as part of an IDR.  //! An alterbative may be to consider this function the IDR start function.    nalu = NULL;  nalu = GenerateSeq_parameter_set_NALU ();  len += WriteNALU (nalu);  FreeNALU (nalu);  nalu = NULL;  nalu = GeneratePic_parameter_set_NALU ();  len += WriteNALU (nalu);  FreeNALU (nalu);//  stat->bit_ctr_parametersets = len;    stat->bit_ctr_parametersets_n = len;  return 0;}

      进入GenerateSeq_parameter_set_NALU函数看看:

NALU_t *GenerateSeq_parameter_set_NALU (){  NALU_t *n = AllocNALU(64000);  int RBSPlen = 0;  int NALUlen;  byte rbsp[MAXRBSPSIZE];  RBSPlen = GenerateSeq_parameter_set_rbsp (active_sps, rbsp);  NALUlen = RBSPtoNALU (rbsp, n, RBSPlen, NALU_TYPE_SPS, NALU_PRIORITY_HIGHEST, 0, 1);  n->startcodeprefix_len = 4;  return n;}

     由RBSPlen = GenerateSeq_parameter_set_rbsp (active_sps, rbsp);可知,在生成RBSP的过程中,的确用到了active_sps(间接地从配置文件获得了数据). 随后RBSP又转换成了NALU,这样就生成了一个NALU(这样,NALU就间接地从配置文件获得了数据)

 

     于是start_sequence函数中的下面语句就生成了sps对应的NALU和pps对应的NALU:

nalu = GenerateSeq_parameter_set_NALU ();......nalu = GeneratePic_parameter_set_NALU ();

     于是,调用start_sequence函数中的下面语句后,就把SPS呵呵PPS写进码流了:

len += WriteNALU (nalu);......len += WriteNALU (nalu);

 

转载地址:http://ijzti.baihongyu.com/

你可能感兴趣的文章
Single Number II --出现一次的数(重)
查看>>
Palindrome Partitioning --回文切割 深搜(重重)
查看>>
对话周鸿袆:从程序员创业谈起
查看>>
Mysql中下划线问题
查看>>
Xcode 11 报错,提示libstdc++.6 缺失,解决方案
查看>>
idea的安装以及简单使用
查看>>
Windows mysql 安装
查看>>
python循环语句与C语言的区别
查看>>
vue 项目中图片选择路径位置static 或 assets区别
查看>>
vue项目打包后无法运行报错空白页面
查看>>
Vue 解决部署到服务器后或者build之后Element UI图标不显示问题(404错误)
查看>>
element-ui全局自定义主题
查看>>
facebook库runtime.js
查看>>
vue2.* 中 使用socket.io
查看>>
openlayers安装引用
查看>>
js报错显示subString/subStr is not a function
查看>>
高德地图js API实现鼠标悬浮于点标记时弹出信息窗体显示详情,点击点标记放大地图操作
查看>>
初始化VUE项目报错
查看>>
vue项目使用安装sass
查看>>
HTTP和HttpServletRequest 要点
查看>>