ffmpeg学习-从不完整的MP4文件提取H264裸流

需求

视频录制设备,在没有内置电池的情况下,突然断电,导致视频文件不完整,使用播放器播放失败;录制视频文件格式是MP4,需要提取里面的H264裸流进行播放。

实现

使用开源工具ffmpeg和ffplay进行转换和播放,windows环境下;

思想:首先使用工具ffmpeg转换正常的MP4文件,然后对比查看差异,再结合H264帧格式数据,最后手动写代码提取H264裸流;

正常的MP4转换后对比:

根据查询H264帧头格式信息看出,H264帧头是以00 00 01 61开头的,当然,还有其他的常用的NAL头:

0x67: SPS 
0x68: PPS 
0x65: IDR   
0x61: non-IDR Slice
0x01: B Slice
0x06: SEI
0x09: AU Delimiter

前面4个字节是后面数据长度,所有需要把后面的数据取出然后加上固定的头格式00 00 00 01就形成了一帧数据;

但是在实验过程中,发现不同厂商的摄像头输出的帧头格式有细微的差异,需要做特殊处理;

代码

思想:

 -- LEN -- NAL-固定值
|		  |
00 00 01 1D 61 E0 08	->	00 00 00 01 61 E0 08
				  ..
00 00 00 E7 61 E0 E8	->	00 00 00 01 61 E0 08

00 00 00 0E 67 4D 00	->	00 00 00 01 67 4D 00
00 00 00 04 68 EE 3C	->	00 00 00 01 68 EE 3C
00 00 00 05 06 E5 01	->	00 00 00 01 06 E5 01
00 00 A1 15 65 B8 XX XX	->	00 00 00 01 65 B8 XX XX

黄色金属摄像头h264头数据:
00 00 xx xx 41 E1/E0

实现:

	for(i=0; i<size-3; i++){
		if((0x00 == buffer[i] && 0x00 == buffer[i+1]) && 
			((0x61 == buffer[i+4] && 0xE0 == buffer[i+5]) ||
			 (0x67 == buffer[i+4] && 0x4D == buffer[i+5] && 0x00 == buffer[i+6]) ||
			 (0x68 == buffer[i+4] && 0xEE == buffer[i+5] && 0x3C == buffer[i+6]) ||
			 (0x06 == buffer[i+4] && 0xE5 == buffer[i+5] && 0x01 == buffer[i+6]) ||
			 (0x65 == buffer[i+4] && 0xB8 == buffer[i+5])))
		{
			date_len = ((buffer[i+2]<<8) | buffer[i+3]) + 4;
			buffer[i+2] = 0x00;
			buffer[i+3] = 0x01;
			
			ret = fwrite(p_buffer+i, 1, date_len, pFile_out);
			//printf("ret=%02X\n",ret);
			if(ret != date_len)
			{
				printf("Fail to fwrite size=%d\n",date_len);
				break;
			}
		}
		else if(0x00 == buffer[i+2] && 0x18 == buffer[i+3] && 0x66 == buffer[i+4])
		{
			printf("over index=%x, flag: 00 00 00 18 66\n",i);
			break;
		}	
	}

由于对MP4和H264格式没有深入的了解,所以上面的内容根据自己经验得出,有不足之处请多多指教;

播放

提出的H264裸流保存成一个文件,使用ffplay工具进行播放,可以播放不完整的MP4文件,还能测试出视频丢失多少秒;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值