h264帧边界识别
2015-10-14 17:02
274 查看
帧边界识别简介
H.264 将构成一帧图像所有nalu 的集合称为一个AU,帧边界识别实际上就是识别AU。因为H.264 取消帧级语法,所以无法简单地从码流中获取AU。解码器只有在解码的过
程中,通过某些语法元素的组合才能判断一帧图像是否结束。一般来说,解码器必须在完成一帧新图像的第一个slice_header 语法解码之后,才能知道前一帧图像已经结束。
因此,最严谨的AU 识别步骤如下:
步骤 1 对码流实施“去03 处理”。
步骤 2 解析nalu 语法。
步骤 3 解析slice_header 语法。
步骤 4 综合判断前后两个nalu 以及对应的slice_header 中的若干个语法元素,看是否发生变化。
如果发生变化,则说明这两个nalu 属于不同的帧,否则说明这两个nalu 属于同一帧。
----结束
显然,在解码前完成上述的AU 识别消耗许多CPU 资源,因此不推荐使用AU 方式解码
为了提供一种简单的AU
识别方案,H.264
规定一种类型为09 的nalu,即编码器在每次完成一个AU
编码后,在码流中插入一个类型为09
的nalu,在这个前提下,解码器只需要从码流中搜索类型为09
的nalu 即可获得一个AU。
H.264 并不强制要求编码器插入类型为09
的nalu,因此并非所有的码流都具备这种特征。对于编码器和解码器协同工作的应用场景,建议让编码器插入类型为09
的nalu,这样可以降低解码器识别AU
的代价。
为了降低解码器在解码前识别AU 的代价,本文提出一种高效的AU 识别方法,其主要思路是利用一帧图像的第一个slice_header 中的语法元素first_mb_in_slice 一般等于0 这
个特征(对于包含ASO 或者FMO 特性的码流,这个条件不一定成立)。
typedef struct ParseContext{
unsigned int FrameStartFound;
unsigned int iFrameLength;
} ParseContext;
signed int DecLoadAU(unsigned char* pStream, unsigned int iStreamLen, ParseContext *pc)
{
unsigned int i;
unsigned int state = 0xffffffff;
if( NULL == pStream )
{
return -1;
}
for( i = 0; i < iStreamLen; i++)
{
/* 查找nal类型为1和5的nal头 */
if( (state & 0xFFFFFF1F) == 0x101 || (state & 0xFFFFFF1F) == 0x105 )
{
if (i >= iStreamLen) /* 到达Buffer尾部,退出查找循环 */
{
break;
}if( pStream[i] & 0x80) /* 查找first_mb_in_slice为0的slice头确定一幅图像的开始 */
{
if(pc->FrameStartFound) /* 查找到下一幅图像的开始就可以确定图像的起始和结束 */
{
pc->iFrameLength = i - 4;
pc->FrameStartFound = 0;
state = 0xffffffff;
return 0; /* 找到一幅图像的边界返回0 */
}
else
{
pc->FrameStartFound = 1;
}
}
}
if (i < iStreamLen)
{
state = (state << 8) | pStream[i]; /* 从码流Buffer中读入1个字节 */
}
}
pc->FrameStartFound = 0;
return -1; /* 没有找到AU边界返回-1 */
}
H.264 将构成一帧图像所有nalu 的集合称为一个AU,帧边界识别实际上就是识别AU。因为H.264 取消帧级语法,所以无法简单地从码流中获取AU。解码器只有在解码的过
程中,通过某些语法元素的组合才能判断一帧图像是否结束。一般来说,解码器必须在完成一帧新图像的第一个slice_header 语法解码之后,才能知道前一帧图像已经结束。
因此,最严谨的AU 识别步骤如下:
步骤 1 对码流实施“去03 处理”。
步骤 2 解析nalu 语法。
步骤 3 解析slice_header 语法。
步骤 4 综合判断前后两个nalu 以及对应的slice_header 中的若干个语法元素,看是否发生变化。
如果发生变化,则说明这两个nalu 属于不同的帧,否则说明这两个nalu 属于同一帧。
----结束
显然,在解码前完成上述的AU 识别消耗许多CPU 资源,因此不推荐使用AU 方式解码
为了提供一种简单的AU
识别方案,H.264
规定一种类型为09 的nalu,即编码器在每次完成一个AU
编码后,在码流中插入一个类型为09
的nalu,在这个前提下,解码器只需要从码流中搜索类型为09
的nalu 即可获得一个AU。
H.264 并不强制要求编码器插入类型为09
的nalu,因此并非所有的码流都具备这种特征。对于编码器和解码器协同工作的应用场景,建议让编码器插入类型为09
的nalu,这样可以降低解码器识别AU
的代价。
为了降低解码器在解码前识别AU 的代价,本文提出一种高效的AU 识别方法,其主要思路是利用一帧图像的第一个slice_header 中的语法元素first_mb_in_slice 一般等于0 这
个特征(对于包含ASO 或者FMO 特性的码流,这个条件不一定成立)。
typedef struct ParseContext{
unsigned int FrameStartFound;
unsigned int iFrameLength;
} ParseContext;
signed int DecLoadAU(unsigned char* pStream, unsigned int iStreamLen, ParseContext *pc)
{
unsigned int i;
unsigned int state = 0xffffffff;
if( NULL == pStream )
{
return -1;
}
for( i = 0; i < iStreamLen; i++)
{
/* 查找nal类型为1和5的nal头 */
if( (state & 0xFFFFFF1F) == 0x101 || (state & 0xFFFFFF1F) == 0x105 )
{
if (i >= iStreamLen) /* 到达Buffer尾部,退出查找循环 */
{
break;
}if( pStream[i] & 0x80) /* 查找first_mb_in_slice为0的slice头确定一幅图像的开始 */
{
if(pc->FrameStartFound) /* 查找到下一幅图像的开始就可以确定图像的起始和结束 */
{
pc->iFrameLength = i - 4;
pc->FrameStartFound = 0;
state = 0xffffffff;
return 0; /* 找到一幅图像的边界返回0 */
}
else
{
pc->FrameStartFound = 1;
}
}
}
if (i < iStreamLen)
{
state = (state << 8) | pStream[i]; /* 从码流Buffer中读入1个字节 */
}
}
pc->FrameStartFound = 0;
return -1; /* 没有找到AU边界返回-1 */
}
相关文章推荐
- 04-Windows Server 2012 R2 会话远程桌面-标准部署-CA证书(RemoteApp)
- 什么是arc?(arc是为了解决什么问题诞生的?)
- IOS-14-IOS支付宝集成与成功掌握
- 如何将四大名著和地图相结合?
- Data Base oracle简单使用及管理工具使用
- 桌面oracle 11g导入多年库的dump备忘
- 第二章 rsync实现本地磁盘数据备份
- select option便利循环
- 如何设计一个 iOS 控件?(iOS 控件完全解析)
- 使用IDEA远程服务器调试DEBUG
- xcode 左边导航栏中,类文件后面的标记“A”,"M","? "...的意思
- SQL 中GO的作用
- Outlook 2016 连接Exchange服务器的一些已知问题
- 《需求工程——软件建模与分析》——阅读笔记一
- 【iOS】Your account already has a valid ios
- String类和StringBuffer类的区别
- [java]运算工具(提供精确的浮点数运算,包括加减乘除和四舍五入)
- SQL Server数据库表的六大约束
- win8系统应用商店搜索功能在哪里?win8系统应用商店搜索功能使用教程
- 图像特征提取