环境:我们的项目T082所使用的平台是samsung C110, android系统为4.0.3版本。 在android系统Framework层,有Mediarecorder.h文件,其中有定义:
enum video_source {
VIDEO_SOURCE_DEFAULT = 0,
VIDEO_SOURCE_CAMERA = 1,
VIDEO_SOURCE_GRALLOC_BUFFER = 2,

VIDEO_SOURCE_LIST_END // must be last - used to validate audio source type
};

//Please update media/java/android/media/MediaRecorder.java if the following is updated.
enum output_format {
OUTPUT_FORMAT_DEFAULT = 0,
OUTPUT_FORMAT_THREE_GPP = 1,
OUTPUT_FORMAT_MPEG_4 = 2,


OUTPUT_FORMAT_AUDIO_ONLY_START = 3, // Used in validating the output format. Should be the
// at the start of the audio only output formats.

/* These are audio only file formats */
OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible
OUTPUT_FORMAT_AMR_NB = 3,
OUTPUT_FORMAT_AMR_WB = 4,
OUTPUT_FORMAT_AAC_ADIF = 5,
OUTPUT_FORMAT_AAC_ADTS = 6,

/* Stream over a socket, limited to a single stream */
OUTPUT_FORMAT_RTP_AVP = 7,

/* H.264/AAC data encapsulated in MPEG2/TS */
OUTPUT_FORMAT_MPEG2TS = 8,

OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
};

enum audio_encoder {
AUDIO_ENCODER_DEFAULT = 0,
AUDIO_ENCODER_AMR_NB = 1,
AUDIO_ENCODER_AMR_WB = 2,
AUDIO_ENCODER_AAC = 3,
AUDIO_ENCODER_AAC_PLUS = 4,
AUDIO_ENCODER_EAAC_PLUS = 5,

AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
};

enum video_encoder {
VIDEO_ENCODER_DEFAULT = 0,
VIDEO_ENCODER_H263 = 1,
VIDEO_ENCODER_H264 = 2,
VIDEO_ENCODER_MPEG_4_SP = 3,

VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
}; 上面分别定义了支持的视频源、输出格式和编码格式,其中视频源主要分三种模式:第一种是默认源,在本项目中,设定为camara源作为默认源 另外一种就是VIDEO_SOURCE_CAMERA支持camara录制视频,还有一种就是VIDEO_SOURCE_GRALLOC_BUFFER,这一种是用户自己分配空间,然后填充自己的数据进行编码输出,也是我这次学习的重点。
class MediaRecorder : public BnMediaRecorderClient{}这是一个recorder应用实体对应的类对象,它从BnMediaRecorderClient派生过来,跟踪代码可发现,继承这个类主要是为了给远程提供notify机制,以便在录制过程中接收其它端的消息。
类中有 sp<IMediaRecorder> mMediaRecorder; sp<MediaRecorderListener> mListener; // Reference toISurfaceTexture
// for encoding GL Frames. That is useful only when the
// video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
sp<ISurfaceTexture> mSurfaceMediaSource; 几个成员变量,其中mMediaRecorder是为了通过IMediaRecorder与MediaPlayerService进行控制操作;mListener是为了在接收到其它进程通知时作出相应的处理;mSurfaceMediaSource只有在VIDEO_SOURCE_GRALLOC_BUFFER模式下才分配,是为了实际填充待编码数据的。

一,初始化 一个简单的recorder客户端的初始化过程如下: LOGE("Starting setupMediasource...");
sp<MediaRecorder> mr = new MediaRecorder(); //创建一个实例化对象
mr->setVideoSource(VIDEO_SOURCE_GRALLOC_BUFFER); //设定录制机的模式
mr->setOutputFormat(OUTPUT_FORMAT_MPEG_4); // 设置输出的文件格式为MPEG4
// mr->setOutputFormat(OUTPUT_FORMAT_MPEG2TS); // 设置输出的文件格式为MPEG2TS mr->setVideoEncoder(VIDEO_ENCODER_H264); //设置输出的文件的编码格式为H264
mr->setOutputFile(fd, 0, 0); // 设置输出的文件所要写的fd
mr->setVideoSize(mYuvTexWidth, mYuvTexHeight); // 设置输出视频的尺寸
mr->setVideoFrameRate(fps); //设置输出视频的帧率
mr->prepare(); // 开始准备
mr->start(); // 正式开始录制
LOGE("Starting MediaRecorder...");

sp<MediaRecorder> mr = new MediaRecorder();--->IMediaPlayerService.createMediaRecorder(getpid())(通过binder通知MediaPlayerService创建一个实例对象)--->MediaPlayerService::createMediaRecorder()---->new MediaRecorderClient(this, pid);--->mRecorder = new StagefrightRecorder;到这里也就是创建一个StagefrightRecorder对象,供mr操控,同时进行了一系列的初始化;
mr中间的一系列操作只是设置一些标志位,mr->start(); ---->MediaRecorder::start()---->IMediaRecorder.start()--->MediaRecorderClient::start()----->StagefrightRecorder::start()---->startMPEG4Recording()(前面设置的输出格式是OUTPUT_FORMAT_MPEG_4)------>setupMPEG4Recording()---> 1,setupMPEG4Recording()--->writer = new MPEG4Writer(outputFd)+setupMediaSource()---->setupSurfaceMediaSource()(当前面选择VIDEO_SOURCE_CAMERA时,setupCameraSource())---->new SurfaceMediaSource()--->mGraphicBufferAlloc = composer->createGraphicBufferAlloc()(创建一个alloc对象,用于后面申请memory空间) 2,mWriter->start()---->MPEG4Writer::start()---->startWriterThread();
二,填充数据
sp<SurfaceTextureClient> mSTC;
sp<ANativeWindow> mANW; sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
mSTC = new SurfaceTextureClient(iST); mANW = mSTC;
ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(), HAL_PIXEL_FORMAT_YV12));

int32_t nFramesCount = 0;
while (nFramesCount <= 30)
{
ANativeWindowBuffer* anb;

ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
ASSERT_TRUE(anb != NULL)

sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));

// Fill the buffer with the a checkerboard pattern
uint8_t* img = NULL;
buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
if (img)
fillYV12Buffer(img, mYuvTexWidth, mYuvTexHeight, buf->getStride());
else
LOGE("buf->lock FAILED...");

buf->unlock();

//ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));

usleep(33*1000);
nFramesCount++;

}

ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU));
LOGE("Stopping MediaRecorder...");
if (mr->stop()!=OK)
{
LOGE("mr->stop()...");
return;
}


native_window_api_connect() 和native_window_api_disconnect()是一对,现版本的代码是不做任何处理; native_window_set_buffers_format()是对将要申请的buffer的数据类型标志进行设定,这里设定为HAL_PIXEL_FORMAT_YV12,还可以设置RGBA_8888等类型;
mANW->dequeueBuffer()--->ANativeWindow::dequeueBuffer()--->SurfaceTextureClient::hook_dequeueBuffer()--->SurfaceTextureClient::dequeueBuffer()---->mSurfaceTexture.dequeueBuffer()----->ISurfaceTexture::dequeueBuffer()----->SurfaceTexture::dequeueBuffer()---->(当已存在申请的buffer,返回buffer序号)mGraphicBufferAlloc->createGraphicBuffer()(在初始化SurfaceTexture对象时,mGraphicBufferAlloc=ISurfaceComposer::createGraphicBufferAlloc())---->IGraphicBufferAlloc::createGraphicBuffer()---->(Bn对象是在surfaceFlinger::createGraphicBufferAlloc()创建的)GraphicBufferAlloc::createGraphicBuffer()---->new GraphicBuffer()--->initSize()---->(surfaceFlinger中的都用同一个GraphicBufferAllocator实例)GraphicBufferAllocator::alloc()--->mAllocDev::alloc()(这里用到HAL层的gralloc.so库了)
中间的几个过程就是锁定buffer,提取出实际的 buffer指针,然后往地址中填数据; mANW->queueBuffer()----> ANativeWindow::()--->SurfaceTextureClient::hook_queueBuffer()--->SurfaceTextureClient::queueBuffer()---->mSurfaceTexture.queueBuffer()----->ISurfaceTexture::queueBuffer()----->SurfaceTexture::queueBuffer()将相应的slot状态修改,并通过listener通知相应的处理模块;

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. android XML 解析代码
  6. Android遍历获取指定目录的文件
  7. 使用ActivityGroup类显示多个Activity
  8. android得到清单文件里meta标签的属性值
  9. android AppWidgetProvider 使用方法

随机推荐

  1. Android中对Log日志文件的分析
  2. 想抢先体验Android操作系统的魅力吗?那就
  3. Android通过Socket(TCP/IP)与PC通讯
  4. 环境装好后,创建手机的模拟器
  5. 新手学习linux需了解的内容
  6. Android(安卓)2.3系统令人为之兴奋的十大
  7. Android开发实践:在任意目录执行NDK编译
  8. Android(安卓)开发艺术探索读书笔记 11 -
  9. 转!Android(安卓)onTouchEvent,onClick和o
  10. Android之Glide(非常好用的图片加载框架)