基于Android4.2系统的H264视频数据的获取

本文详细介绍了如何在Android 4.2.2系统中,通过修改StagefrightRecorder类和构建H264Writer类,实现从HAL层面获取H264原始压缩数据,解决了MediaRecorder获取数据的效率和稳定性问题,实现了H264数据的文件保存和传输功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于Android4.2系统的H264视频数据的获取


0引言

Andriod系统本身不支持H264视频原始压缩数据(即符合H264压缩标准,具有NAL头的裸数据)的实时获取,基本上都是利用MediaRecorder类的setOutputFile()函数中可以接收文件描述符的特点,使用LocalSocket从MPEG4文件流中获得H264裸数据,实现数据存储或传输。在作者的测试中,该方法存在两个问题:(1)MPEG4文件流中的H264压缩数据因为去掉了NAL头,全靠4字节的帧数据长度来获得一帧数据;当因为某些原因造成长度数据错误,而没有NAL同步头则造成一段时间内不能获得正确的H264原始数据;(2)H264数据的SPS和PPS帧不能简单确定,需要人工填写,容易造成不能解码。本文正是针对该缺点,从Android4.2.2的HAL层面上解决了该问题,并且实现了H264原始数据的文件保存,同时兼容MPEG4的所有处理方式,提高了获取数据的效率和稳定性。

1 Android MediaRecorder介绍

Android的MediaRecorder类从功能的角度包含音频,视频记录,视频预览的功能,从上到下的类调用顺序如下:

MediaRecorder.java

+- android_media_MediaRecorder.cpp

+-MediaRecorder.cpp

+-MediaPlayerService.cpp

+-MediaRecorderClient.cpp

+-StagefrightRecorder.cpp

+- MPEG4Writer.cpp,AACWriter.cpp等

本文利用系统缺省的文件输出格式,即在MediaRecorder类调用时,设置输出方式为MediaRecorder.OutputFormat.DEFAULT即可,通过在StagefrightRecorder类中对缺省编码方式实现特殊处理,并且参照MPEG4Writer类实现了自定义的H264Writer类,从而实现了H264原始数据的文件存储和数据传输功能。

2 StagefrightRecorder类修改

StagefrightRecorder的构造函数中调用reset函数进行了初始化设置。默认OutputFormat为3GPP, AudioEncoder为AMR NB,VideoEncoder为H264。图1为StagefrightRecorder支持输出的文件格式。

图1

本文就是将default选项提取出来,进行单独的处理,如图2所示。


图2

该类源代码所在目录路径如下:

./frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp,代码修改如下:

(1)   添加头文件

#include <media/stagefright/H264Writer.h>

(2)   修改setOutputFormat()函数

屏蔽对OUTPUT_FORMAT_DEFAULT的处理,直接将参数of赋值给mOutputFormat;

(3)   修改start函数

屏蔽系统对OUTPUT_FORMAT_DEFAULT的默认处理,添加单独处理代码:

case OUTPUT_FORMAT_DEFAULT:

startH264Recording();

break;

(4)   仿照setupMPEG4Recording()函数,创建setupH264Recording()函数,将newMPEG4Writer(outputFd)替换为new H264Writer(outputFd);

(5)   仿照startMPEG4Recording()函数,创建startH264Recording()函数;

3 MPEG4Writer类介绍

MPEG4Writer类主要实现将以H264压缩编码获得的H264原始数据,以MPEG4文件格式进行一系列的处理,如填写MPEG4文件头块ftpy等。MPEG4Writer封装好的视频的格式如图3所示:


图3

在该封装格式中,首先填写fypy块,然后填写mdat。H264的原始数据就存放在mdat块中,以4个字节表示一帧数据的长度,一帧数据一帧数据存储的。当停止保存(录像等)动作后,再回填moov等box数据,包含该段视频总帧数,时长等信息。

4构建H264Writer类

H264Writer类主要实现H264编码原始数据的读取,然后不做任何处理,直接存储到Java层传递来的文件描述符的句柄中。

(1) 仿照MPEG4Writer.cpp,MPEG4Writer.h生成相应的H2644Writer.cpp,H2644Writer.h,并且将头文件拷贝到相应的include目录;

(2) 修改start()函数

屏蔽写FtypBox的过程,屏蔽代码从writeFtypBox(param)开始到status_t err =startWriterThread()之前结束;

(3) 修改reset()函数,该函数主要实现moov等各种box块的填写,屏蔽代码从if (mUse32BitOffset)开始到CHECK(mBoxes.empty())之前结束;

(4) 修改Track::threadEntry()函数

A)  屏蔽if(buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)的整个处理过程;

B)   屏蔽代码从mOwner->trackProgressStatus(mTrackId,-1, err)开始到sendTrackSummary(hasMultipleTracks)结束;

(5) 修改addLengthPrefixedSample()函数,将代码:

uint8_t  x = length>> 24;

::write(mFd, &x, 1);

x = (length >> 16) & 0xff;

::write(mFd, &x, 1);

x = (length >> 8) & 0xff;

::write(mFd, &x, 1);

x = length & 0xff;

::write(mFd, &x, 1);

修改为:

       uint8_t  x = 0x00;

       ::write(mFd, &x, 1);

       ::write(mFd, &x, 1);

::write(mFd,&x, 1);

       x = 0x01;

::write(mFd,&x, 1);

(6) 修改MPEG4Writer.cpp文件所在目录的Android.mk文件,添加H264Writer.cpp

5编译

编译整个安卓系统,生成新的system.img镜像,更新系统重启后即可在Java层通过设置DEFAULT输出方式,实现H264原始数据的获取(文件保存或数据传输)。

6总结

通过以上的实现方法,作者实现了H264原始数据的文件存储,并且在移植了live555的源代码后,利用管道文件的方式,实现了手机端作为RTSP服务器的功能,从而在其他设备上实现了实时视频流播放功能。

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值