//
// NALUnit.cpp
//
// Implementation of Basic parsing of H.264 NAL Units
//
// Geraint Davies, March 2004
//
// Copyright (c) GDCL 2004-2008 http://www.gdcl.co.uk/license.htm
#include "NALUnit.h"
// --- core NAL Unit implementation ------------------------------
NALUnit::NALUnit()
: m_pStart(NULL),
m_cBytes(0)
{
}
bool
NALUnit::GetStartCode(const BYTE*& pBegin, const BYTE*& pStart, int& cRemain)
{
// start code is any number of 00 followed by 00 00 01
// We need to record the first 00 in pBegin and the first byte
// following the startcode in pStart.
// if no start code is found, pStart and cRemain should be unchanged.
const BYTE* pThis = pStart;
int cBytes = cRemain;
pBegin = NULL;
while (cBytes>= 4)
{
if (pThis[0] == 0)
{
// remember first 00
if (pBegin == NULL)
{
pBegin = pThis;
}
if ((pThis[1] == 0) &&
(pThis[2] == 1))
{
// point to type byte of NAL unit
pStart = pThis + 3;
cRemain = cBytes - 3;
return true;
}
} else {
pBegin = NULL;
}
cBytes--;
pThis++;
}
return false;
}
bool
NALUnit::Parse(const BYTE* pBuffer, int cSpace, int LengthSize, bool bEnd)
{
// if we get the start code but not the whole
// NALU, we can return false but still have the length property valid
m_cBytes = 0;
ResetBitstream();
if (LengthSize > 0)
{
m_pStartCodeStart = pBuffer;
if (LengthSize > cSpace)
{
return false;
}
m_cBytes = 0;
for (int i = 0; i < LengthSize; i++)
{
m_cBytes <<= 8;
m_cBytes += *pBuffer++;
}
if ((m_cBytes+LengthSize) <= cSpace)
{
m_pStart = pBuffer;
return true;
}
} else {
// this is not length-delimited: we must look for start codes
const BYTE* pBegin;
if (GetStartCode(pBegin, pBuffer, cSpace))
{
m_pStart = pBuffer;
m_pStartCodeStart = pBegin;
// either we find another startcode, or we continue to the
// buffer end (if this is the last block of data)
if (GetStartCode(pBegin, pBuffer, cSpace))
{
m_cBytes = int(pBegin - m_pStart);
return true;
} else if (bEnd)
{
// current element extends to end of buffer
m_cBytes = cSpace;
return true;
}
}
}
return false;
}
// bitwise access to data
void
NALUnit::ResetBitstream()
{
m_idx = 0;
m_nBits = 0;
m_cZeros = 0;
}
void
NALUnit::Skip(int nBits)
{
if (nBits < m_nBits)
{
m_nBits -= nBits;
} else {
nBits -= m_nBits;
while (nBits >= 8)
{
GetBYTE();
nBits -= 8;
}
if (nBits)
{
m_byte = GetBYTE();
m_nBits = 8;
m_nBits -= nBits;
}
}
}
// get the next byte, removing emulation prevention bytes
BYTE
NALUnit::GetBYTE()
{
if (m_idx >= m_cBytes)
{
return 0;
}
BYTE b = m_pStart[m_idx++];
// to avoid start-code emulation, a byte 0x03 is inserted
// after any 00 00 pair. Discard that here.
if (b == 0)
{
m_cZeros++;
if ((m_idx < m_cBytes) && (m_cZeros == 2) && (m_pStart[m_idx] == 0x03))
{
m_idx++;
m_cZeros=0;
}
} else {
m_cZeros = 0;
}
return b;
}
unsigned long
NALUnit::GetBit()
{
if (m_nBits == 0)
{
m_byte = GetBYTE();
m_nBits = 8;
}
m_nBits--;
return (m_byte >> m_nBits) & 0x1;
}
unsigned long
NALUnit::GetWord(int nBits)
{
unsigned long u = 0;
while (nBits > 0)
{
u <<= 1;
u |= GetBit();
nBits--;
}
return u;
}
unsigned long
NALUnit::GetUE()
{
// Exp-Golomb entropy coding: leading zeros, then a one, then
// the data bits. The number of leading zeros is the number of
// data bits, counting up from that number of 1s as the base.
// That is, if you see
// 0001010
// You have three leading zeros, so there are three data bits (010)
// counting up from a base of 111: thus 111 + 010 = 1001 = 9
int cZeros = 0;
while (GetBit() == 0)
{
cZeros++;
}
return GetWord(cZeros) + ((1 << cZeros)-1);
}
long
NALUnit::GetSE()
{
// same as UE but signed.
// basically the unsigned numbers are used as codes to indicate signed numbers in pairs
// in increasing value. Thus the encoded values
// 0, 1, 2, 3, 4
// mean
// 0, 1, -1, 2, -2 etc
unsigned long UE = GetUE();
bool bPositive = UE & 1;
long SE = (UE + 1) >> 1;
if (!bPositive)
{
SE = -SE;
}
return SE;
}
// --- sequence params parsing ---------------
SeqParamSet::SeqParamSet()
: m_cx(0),
m_cy(0),
m_FrameBits(0)
{
// SetRect(&m_rcFrame, 0, 0, 0, 0);
}
void
ScalingList(int size, NALUnit* pnalu)
{
long lastScale = 8;
long nextScale = 8;
for (int j = 0 ; j < size; j++)
{
if (nextScale != 0)
{
long delta = pnalu->GetSE();
nextScale = (lastScale + delta + 256) %256;
}
int scaling_list_j = (nextScale == 0) ? lastScale : nextScale;
lastScale = scaling_list_j;
}
}
bool
SeqParamSet::Parse(NALUnit* pnalu)
{
if (pnalu->Type() != NALUnit::NAL_Sequence_Params)
{
return false;
}
// with the UE/SE type encoding, we must decode all the values
// to get through to the ones we want
pnalu->ResetBitstream();
pnalu->Skip(8); // type
m_Profile = pnalu->GetWord(8);
m_Compatibility = (BYTE) pnalu->GetWord(8);
m_Level = pnalu->GetWord(8);
/*int seq_param_id =*/ pnalu->GetUE();
if ((m_Profile == 100) || (m_Profile == 110) || (m_Profile == 122) || (m_Profile == 144))
{
int chroma_fmt = pnalu->GetUE();
if (chroma_fmt == 3)
{
pnalu->Skip(1);
}
/* int bit_depth_luma_minus8 = */ pnalu->GetUE();
/* int bit_depth_chroma_minus8 = */ pnalu->GetUE();
pnalu->Skip(1);
int seq_scaling_matrix_present = pnalu->GetBit();
if (seq_scaling_matrix_present)
{
for (int i = 0; i < 8; i++)
{
if (pnalu->GetBit())
{
if (i < 6)
{
ScalingList(16, pnalu);
}
else
{
ScalingList(64, pnalu);
}
}
}
}
}
int log2_frame_minus4 = pnalu->GetUE();
m_FrameBits = log2_frame_minus4 + 4;
int POCtype = pnalu->GetUE();
if (POCtype == 0)
{
/*int log2_poc_minus4 =*/ pnalu->GetUE();
} else if (POCtype == 1)
{
pnalu->Skip(1); // delta always zero
/*int nsp_offset =*/ pnalu->GetSE();
/*int nsp_top_to_bottom = */ pnalu->GetSE();
int num_ref_in_cycle = pnalu->GetUE();
for (int i = 0; i < num_ref_in_cycle; i++)
{
/*int sf_offset =*/ pnalu->GetSE();
}
}
else if (POCtype != 2)
{
return false;
}
// else for POCtype == 2, no additional data in stream
/*int num_ref_frames =*/ pnalu->GetUE();
/*int gaps_allowed =*/ pnalu->GetBit();
int mbs_width = pnalu->GetUE();
int mbs_height = pnalu->GetUE();
m_cx = (mbs_width+1) * 16;
m_cy = (mbs_height+1) * 16;
// smoke test validation of sps
if ((m_cx > 2000) || (m_cy > 2000))
{
return false;
}
// if this is false, then sizes are field sizes and need adjusting
m_bFrameOnly = pnalu->GetBit() ? true : false;
if (!m_bFrameOnly)
{
pnalu->Skip(1); // adaptive frame/field
}
pnalu->Skip(1); // direct 8x8
#if 0
SetRect(&m_rcFrame, 0, 0, 0, 0);
bool bCrop = pnalu->GetBit() ? true : false;
if (bCrop) {
// get cropping rect
// store as exclusive, pixel parameters relative to frame
m_rcFrame.left = pnalu->GetU
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
ios_hardware_encoder_h264.zip (32个子文件)
LICENSE.markdown 2KB
Encoder Demo
CameraServer.h 619B
EncoderDemoAppDelegate.h 315B
en.lproj
MainStoryboard_iPhone.storyboard 4KB
InfoPlist.strings 45B
MainStoryboard_iPad.storyboard 4KB
main.m 372B
RTSPServer.m 4KB
RTSPMessage.h 446B
Encoder Demo-Info.plist 2KB
RTSPMessage.m 2KB
CameraServer.m 3KB
RTSPClientConnection.mm 18KB
RTSPServer.h 591B
AVEncoder.mm 14KB
EncoderDemoViewController.m 1KB
MP4Atom.m 2KB
Default-568h@2x.png 18KB
EncoderDemoViewController.h 399B
NALUnit.h 4KB
NALUnit.cpp 10KB
VideoEncoder.h 798B
RTSPClientConnection.h 443B
Encoder Demo-Prefix.pch 327B
Default.png 6KB
Default@2x.png 16KB
AVEncoder.h 876B
MP4Atom.h 779B
EncoderDemoAppDelegate.m 2KB
VideoEncoder.m 2KB
.gitignore 351B
Encoder Demo.xcodeproj
project.pbxproj 21KB
共 32 条
- 1
资源评论
王安东
- 粉丝: 3
- 资源: 13
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 服务器概述服务器概述服务器概述服务器概述.txt
- 华中农业大学python实验题.txt
- 海康威视相机采图交叉编译示例程序,c++
- DETR-基于Tensorflow实现DETR目标检测算法-附流程教程+项目源码-优质项目实战.zip
- 3d激光slam地图发布程序,3d地图点云处理,c++程序
- 送给妈妈的一束鲜花.zip(母亲节祝福HTML源码)
- 稀疏化DETR-基于Pytorch实现稀疏化DETR-SparseDETR-附流程教程+项目源码-优质项目实战.zip
- 人工分类:SLTM的微博评论二分类数据集
- (自适应手机端)响应式房产合同知识产权网站pbootcms模板 企业管理类网站源码下载.zip
- (自适应手机端)响应式动力刀座pbootcms网站模板 五金机械设备类网站源码下载.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功