最近使用h264码流数据进行录像,但是录出来的第一帧有马赛克,究其原因是录像的第一帧不是关键帧,所以需要录像是需要判断第一帧是否是关键帧,方法有两种,第一种是原码流的基础上查找,第二种是将原码流传递给ffmpeg让ffmpeg判断
key_frame
,第二种相对简单,但是由于这样一来录像和解码视频切合的太紧密,之后修改比较麻烦,所以选择第一种方案,查看注释1可以明白如何检测h264码流的关键帧,下面是我截取原码流的关键帧和p帧
0000000
:是sps
0000000 : 是pps
0000000 : 是帧类型
关键帧类型:
<span style=
"color:#FF0000;"
><span style=
"font-size:24px;"
>0000000: <span style=
"color:#CCCCCC;"
>0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......
0000010: a</span><span style=
"color:#3366FF;"
>000 0000 0168 ce38 80</span>00 0000 01<span style=
"color:#000000;"
>65</span> 8880 .....h.8.....e..
0000020: 4001 8231 2000 4f11 d84d 5fff fb3b c28a @..1 .O..M_..;..
0000030: 00bc fc83 03db b3e3 8603 9c59 fa0f a82c ...........Y...,
0000040: df55 fdf6 8414 032a e766 bd4b fbea 05af .U.....*.f.K....</span>
</span>
0000000: <span style=
"color:#C0C0C0;"
>0000 0001 6742 401f 9654 0501 ed00 f39e ....gB@..T......
0000010: a</span><span style=
"color:#3366FF;"
>000 0000 0168 ce38 80</span>00 0000 01<span style=
"color:#000000;"
>41</span> 9a02 .....h.8.....A..
0000020: 0586 7cb9 9125 5788 8f90 7f1f 1930 7eef ..|..%W......0~.
0000030: 6383 bebd 2cc5 3627 92c3 390b 46dc d4a5 c...,.6'..9.F...
0000040: 774b 3484 57f8 9840 fba3 1dd6 800f 2242 wK4.W..@......"B
0000050: 8816 080f 8f8d 84c6 09aa cda6 363d 00da ............6=..
0000060: b563 4392 bc65 93e2 63bb 6d30 472e 3ef1 .cC..e..c.m0G.>.
0000070: 545d 6a3f 36c3 2f7d 6b1e 3c91 d15d d687 T]j?6./}k.<..]..
public static String byteToHexString(byte src){
StringBuilder stringBuilder = new StringBuilder("");
int v = src &
0xFF
;
String hv = Integer.toHexString(v);
if
(hv.length() <
2
) {
stringBuilder.append(
0
);
stringBuilder.append(hv);
return
stringBuilder.toString();
private boolean isFirstIFrame = true;
private String IFrame =
"65"
;//关键帧是
0x65
//<span style=
"font-size:16px"
></span>bArrayImage是存放h264原码流字节数组
if
(是在录像) {
if
(isFirstIFrame) {
String type = byteToHexString(bArrayImage[
29
]);
if
(type.equals(IFrame)) { //第
29
个字符是判断帧的类型
isFirstIFrame = false;
ShootingVideoData(bArrayImage, Video_Data_iVideoLen);//录制第一帧:关键帧
}
else
{
ShootingVideoData(bArrayImage, Video_Data_iVideoLen);
注释1:检测h264中I帧,P帧
原文链接:
http://blog.csdn.net/zgyulongfei/article/details/7558031
今天在网上找了一些资料,知道了如何检测h264中的帧类型,在这里记录下来。
首先,贴出nal单元类型定义(图从《新一代视频压缩编码标准H.264》摘录):
假设一段h264的码流为:00 00 00 01
41
E6 60……
其中的00 00 00 01为起始码,而起始码之后的下一个字节就可以检测出这一帧的类型。
在上面的码流中起始码之后的字节位 0x41,换算成二进制为 0100 0001。
注:我解读顺序为
从左往右
算。
(1)第1位禁止位,值为1表示语法出错
(2)第2~3位为参考级别
(3)第4~8为是nal单元类型,在此处为 0 0001换算成十进制为1。根据上图可知道这段码流是【不分区、非IDR图像的片】,在baseline的档次中就是P帧,因为baseline没有B帧。
如果是另一段码流:00 00 00 01
65
E8……
那么根据0x65字节(011
0 0101
)根据后5位换算十进制为5,也就是【IDR图像中的片】,即I帧。
用代码的方式可以这样写,int type = 0x65 & 0x1f,然后根据type在表中查找即可获得需要的结果。
使用AprilTag标记进行相机校准
AprilTags被广泛用作物体检测、定位应用的视觉标记,并作为相机校准的目标。AprilTags类似于QR码,但旨在编码更少的数据,因此可以更快地解码,这对于实时机器人应用程序非常有用。使用 AprilTags 作为校准模式的优点包括更好的特征点检测以及一致、可重复的检测。
MMFlow :帧与帧之间的追光者
光流(Optical Flow),字面理解为“光的流动”,更准确的说法为:时变图像上的二维运动场,是视频数据的重要视觉线索,在动作识别、视频理解、视频分割、目标跟踪以及全景拼接等领域,都有广泛应用。
【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )(一)
【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )(一)
【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )(二)
【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )(二)