Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 493|回复: 0

开发交流:视频电话中camera部分数据流分析

[复制链接]

该用户从未签到

发表于 2011-10-24 09:17:28 | 显示全部楼层 |阅读模式
最近在研究如何移植Android的camera系统,对camera的应用场景做了一些分析。Camera一般用于图像浏览、拍照和视频录制。图像浏览和拍照的数据流是比较清晰的,这里就不做赘述了。视频录制应用于视频电话中。拨打视频电话时,既可以看见对方的图像,又可以看见自己的图像;当然,对方也是如此。从camera获取的图像数据,既需要在本地浏览,还需要video encoder编码后传输到对方手机。这样的场景中,图像数据要同时做preview和record两种操作。
一、        回调函数传递
首先需要将客户端的回调函数传递到底层,当底层获取完图像数据后,回调该函数,通知上层,做相应的处理。
类AndroidCameraInput作为客户端,它有两个成员,分别为:
sp<android::Camera> mCamera;
sp<AndroidCameraInputListener> mListener;
类AndroidCameraInput就可以通过mCamera访问camera系统的对外接口。
类AndroidCameraInputListener继承于类CameraListener,它有三个成员函数,分别为:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2){}
virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
这里需要说明的是postDataTimestamp(),它是客户端实现的回调函数,其定义为:
void AndroidCameraInputListener:: postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr){}
当camera HAL层捕获到一帧数据后,就会调用该回调函数,告诉客户端。客户端在这个回调函数里先判断参数msgType是不是CAMERA_MSG_VIDEO_FRAME,如果是,即表示要对该帧数据进行编码处理,编码结束后会调用mCamera的函数releaseRecordingFrame(),其对应的HAL层的定义为:
void QualcommCameraHardware::releaseRecordingFrame(const sp<IMemory>& mem_attibute_((unused))){}
在这个函数里,会调用函数LINK_camera_release_frame()告诉camera硬件,存放当前帧的buffer可以被释放,用于下一帧使用。
回调函数postDataTimestamp()如何注册到HAL层,这里需要详细说明。
在客户端中,是通过mCamera的setListener()函数将mListener注册到mCamera中的,既将几个回调函数注册给mCamera:
mCamera->setListener(mListener);
mCamera继承于类BnCameraClient,而BnCameraClient继承于类ICameraClient。类ICameraClient有纯虚函数:
virtual void dataCallbackTimstamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
类Camera中定义了虚函数dataCallbackTimstamp()并做了实现:
virtual void dataCallbackTimstamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data);
dataCallbackTimstamp()实现中,调用了类Camera的成员mListener的成员函数postDataTimestamp()。
类CameraService有成员类Client,类Client有成员:
sp<ICameraClient> mCameraClient;
sp<CameraHardwareInterface> mHardware;
在类CameraService的成员类Client构造函数中:
CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, pid_t clientPid){}
其中调用了mHardware的函数setCallbacks():
mHardware->setCallbacks(notifyCallback,
                                        dataCallback,
                                        dataCallbackTimestamp,
                                        mCameraService.get());
如下函数:
bool QualcommCameraHardware::setCallbacks(preview_callback pcb, void *puser,
                                                        recording_callback rcb, void *ruser){}
将recording_callback赋给了mHardware的成员mRecordingCallback,至此,已将类AndroidCameraInput中的回调函数postDataTimestamp()传递给了camera的HAL层的成员mRecordingCallback。

二、        数据buffer分配
在提供的Android代码中,有一个camera HAL层的实例,即QualcommCameraHardware。在类QualcommCameraHardware中,默认分配了6个buffer,其中4个preview buffer,1个raw buffer,1个JPEG buffer。在视频电话中,只用了preview buffer。
类QualcommCameraHardware在函数initPreview()中对preview buffer做了初始化。
bool QualcommCameraHardware::initPreview(){}
其中有code为:
mPreviewHeap = new PreviewPmemPool(kRawFrameHeaderSize +
                        mPreviewWidth * mPreviewHeight * 2, //worst
                        kPreviewBufferCount,
                        mPreviewFrameSize,
                        kRawFrameHeaderSize,
                        “preview”);
QualcommCameraHardwares使用PMEM驱动对preview buffer进行了分配。Android PMEM是其专用的驱动,称为物理内存驱动。
视频电话中,当camera捕获一帧数据后,存储该数据的buffer会被同时用于preview和record。只用当客户端调用了函数releaseRecordingFrame()之后才能将对应的buffer释放掉,用于其它帧使用。

三、        视频录制调用
客户端类AndroidCameraInput启动record,通过下面的调用:
mCamera->startRecording();
其会调到函数:
status_t CameraService::Client::startRecording(){}
此处为mHardware设置了message CAMERA_MSG_VIDEO_FRAME,并调用函数 startCameraMode()。其定义为:
status_t CameraService::Client::startCameraMode(camera_mode mode){}
参数camera_mode为CAMERA_RECORDING_MODE,于是调了startRecordingMode。其定义为:
status_t CameraService::Client::startRecordingMode(){}
其中会先启动preview,如果它没有启动的话,调用了startPreviewMode,即:
status_t CameraService::Client::startPreviewMode(){}
这里会处理preview的显示介质,如果使用Overlay显示,会设置相应的Overlay,同时调用mHardware->startPreview()以启动preview;否则先调用mHardware->startPreview()启动preview,然后设置buffer:调用函数registerPreviewBuffers(),其定义为:
status_t CameraService::Client::registerPreviewBuffers(){}
这里会调用mHardware->getPreviewHeap(),从HAL层获得preview的buffer,将其设置给Surface去显示preview的结果。
类QualcommCameraHardware对startPreview的定义如下:
status_t QualcommCameraHardware::startPreview(preview_callback pcb, void *puser){}
它调用了startPreviewInternal(),其定义为:
status_t QualcommCameraHardware:startPreviewInternal(preview_callback pcb, void (puser, recording_callback rcb, void *ruser){}
函数里调用了setCallbacks(pcb, puser, rcb, ruser),更新了preview和record的回调函数。另外调用函数LINK_camera_start_preview(camera_cb, this),向driver层传递函数camera_cb。其定义为:
void QualcommCameraHardware::camera_cb(camera_cb_type cb, const void *client_data, camera_func_type func, int32_t parm4){}
函数里,当mCameraState为QCS_PREVIEW_IN_PROGRESS时,preview成功,同时调用函数receivePreviewFrame,其定义为:
void QualcommCameraHardware::receivePreviewFrame(camera_frame_type *frame){}
它调用了回调函数mPreviewCallback和mRecordingCallback,这就回调了函数postDataTimstamp(),告诉客户端一帧数据已经获取成功,其可以开始编码了。
前面已经讲过,当客户端对该帧数据的处理结束后,会告诉底层硬件释放该帧所占用的buffer空间,以备其他帧使用。
如此,preview和record同时进行,即可实现视频电话功能。
上述文中有不少问题,还望各位高手指点,谢谢。
视频电话中camera部分数据流分析 (1).rar (9.33 KB)

115网盘下载地址:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

该用户从未签到

发表于 2011-10-24 09:17:33 | 显示全部楼层

Re:开发交

不错的资料,学习了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 19:14 , Processed in 0.336526 second(s), 34 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表