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

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

       在lencod.c的main函数中调用了encode_one_slice函数,在encode_one_slice函数中调用了frame_picture函数,调用了frame_picture函数后(frame_picture还会继续调用其他重要函数) 就实现了对第一帧的编码,这样全局变量frame_pic就发生了变化,得到了它想得到的码流,现在要写码流,怎么写呢?

      在encode_one_frame中接着就调用到了writeout_picture函数,调用形式是:

writeout_picture (frame_pic);

      可见,把代码码流信息的frame_pic穿进去了,进入writeout_picture函数看看:

static int writeout_picture(Picture *pic){  Bitstream *currStream;  int partition, slice;  Slice *currSlice;  img->currentPicture=pic;  // 遍历slice,通常,一个frame对应一个slice  for (slice=0; slice
no_slices; slice++) { currSlice = pic->slices[slice]; // 目前都发现currSlice->max_part_nr为1 for (partition=0; partition
max_part_nr; partition++) { currStream = (currSlice->partArr[partition]).bitstream; // currStream->bits_to_go相当于标记,必须为8 assert (currStream->bits_to_go == 8); //! should always be the case, the //! byte alignment is done in terminate_slice // writeUnit函数的第一参数类型是Bitstream* writeUnit (currSlice->partArr[partition].bitstream,partition); } // partition loop } // slice loop return 0; }

      可以看到,把一个picture对应的码流分成slice和数据分块来传给writeUnit的形参(一般认为:一个slice对应一个数据分块),进入到writeUnit函数看看:

static void writeUnit(Bitstream* currStream,int partition){  NALU_t *nalu;  // 实际上currStream->bits_to_go就是一个标记  // 如果不为8, 则表明往下继续执行会有错误  assert (currStream->bits_to_go == 8);  // 分配堆空间, *4是为了安全起见  nalu = AllocNALU(img->width*img->height*4);  nalu->startcodeprefix_len = 2+(img->current_mb_nr == 0?ZEROBYTES_SHORTSTARTCODE+1:ZEROBYTES_SHORTSTARTCODE);//printf ("nalu->startcodeprefix_len %d\n", nalu->startcodeprefix_len);    nalu->len = currStream->byte_pos +1;            // add one for the first byte of the NALU//printf ("nalu->len %d\n", nalu->len);  // 内存数据复制,这个是最重要的.  memcpy (&nalu->buf[1], currStream->streamBuffer, nalu->len-1);    // 下面对nalu的一些参数进行赋值  // 其实就是对nalu header的8个比特赋值  if (img->currentPicture->idr_flag)  {    nalu->nal_unit_type = NALU_TYPE_IDR;    nalu->nal_reference_idc = NALU_PRIORITY_HIGHEST;  }  else if (img->type == B_SLICE)  {		//different nal header for different partitions    if(input->partition_mode == 0)	{      nalu->nal_unit_type = NALU_TYPE_SLICE;	}	else	{      nalu->nal_unit_type = NALU_TYPE_DPA +  partition;	}        if (img->nal_reference_idc !=0)	{		nalu->nal_reference_idc = NALU_PRIORITY_HIGH;	}    else    {      nalu->nal_reference_idc = NALU_PRIORITY_DISPOSABLE;    }  }  else   // non-b frame, non IDR slice  {		//different nal header for different partitions    if(input->partition_mode == 0)    {       nalu->nal_unit_type = NALU_TYPE_SLICE;	}	else	{       nalu->nal_unit_type = NALU_TYPE_DPA +  partition;	}    if (img->nal_reference_idc !=0)    {       nalu->nal_reference_idc = NALU_PRIORITY_HIGH;    }    else    {       nalu->nal_reference_idc = NALU_PRIORITY_DISPOSABLE;    }  }  nalu->forbidden_bit = 0; // 必须为0  // WriteNALU是指向函数的全局指针(提前赋值了),  // 所以要想用鼠标进入WriteNALU“函数”是不可能的  // 真正调用到的函数是:WriteAnnexbNALU  // 而WriteAnnexbNALU函数就是写码流函数  stat->bit_ctr += WriteNALU (nalu); // 写码流    FreeNALU(nalu);}

       不用再进入WriteAnnexbNALU函数了,因为,对这个函数太熟悉了.

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

你可能感兴趣的文章
985硕士:非科班自学编程感觉还不如培训班出来的,硕士白读了?
查看>>
你准备写代码到多少岁?程序员们是这么回答的!
查看>>
码农:和产品对一天需求,产品经理的需求是对完了,可我代码呢?
查看>>
程序员过年回家该怎么给亲戚朋友解释自己的职业?
查看>>
技术架构师的日常工作是什么?网友:搭框架,写公共方法?
查看>>
第四章 微信飞机大战
查看>>
九度:题目1008:最短路径问题
查看>>
九度Online Judge
查看>>
九度:题目1027:欧拉回路
查看>>
九度:题目1012:畅通工程
查看>>
九度:题目1017:还是畅通工程
查看>>
九度:题目1034:寻找大富翁
查看>>
第六章 背包问题——01背包
查看>>
51nod 分类
查看>>
1136 . 欧拉函数
查看>>
面试题:强制类型转换
查看>>
Decorator模式
查看>>
Template模式
查看>>
Observer模式
查看>>
高性能服务器设计
查看>>