https://blog.csdn.net/haiping1224746757/article/details/107506453
继续之前的Video数据流进一步分析Surface的原理解析
private void startRecordingVideo() {
if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
return;
}
try {
// 关闭之前的会话,新的会话会添加录像的Target
closePreviewSession();
// 配置MediaRecorder,音频、视频来源,编码格式等
setUpMediaRecorder();
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
// 创建一个适合视频录制的请求
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
List<Surface> surfaces = new ArrayList<>();
// Set up Surface for the camera preview
Surface previewSurface = new Surface(texture);
surfaces.add(previewSurface);
mPreviewBuilder.addTarget(previewSurface);
// Set up Surface for the MediaRecorder 重要的一步,视频信息会交给mMediaRecorder处理
Surface recorderSurface = mMediaRecorder.getSurface();
surfaces.add(recorderSurface);
mPreviewBuilder.addTarget(recorderSurface);
// Start a capture session
// Once the session starts, we can update the UI and start recording
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
mPreviewSession = cameraCaptureSession;
updatePreview();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// UI
mButtonVideo.setText(R.string.stop);
mIsRecordingVideo = true;
// 开始录制
mMediaRecorder.start();
}
});
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
}
}
}, mBackgroundHandler);
} catch (CameraAccessException | IOException e) {
e.printStackTrace();
}
}
在上面的代码中有一个地方,不知道有没有注意到:
Surface recorderSurface = mMediaRecorder.getSurface();
surfaces.add(recorderSurface);
mPreviewBuilder.addTarget(recorderSurface);
这里的Surface是哪里来的,怎么MediaRecorder会get出Surface来,带着疑问往下看:
先进入MediaRecorder.java,主要讲述构造函数MediaRecorder()和prepare()函数
//frameworks\base\media\java\android\media\MediaRecorder.java
public MediaRecorder() {
....
String packageName = ActivityThread.currentPackageName();
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaRecorder>(this), packageName,
ActivityThread.currentOpPackageName());
}
public void prepare() throws IllegalStateException, IOException
{
...
_prepare();
}
_prepare是native 方法,定义如下:
//frameworks\base\media\java\android\media\MediaRecorder.java
private native final void native_setup(Object mediarecorder_this,
String clientName, String opPackageName) throws IllegalStateException;
private native void _prepare() throws IllegalStateException, IOException;
咱们进入JNI 层具体看看实现
//frameworks\base\media\jni\android_media_MediaRecorder.cpp
static void android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring packageName, jstring opPackageName)
{
...
// 创建MediaRecorder
sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str()));
// create new listener and give it to MediaRecorder
sp<JNIMediaRecorderListener> listener = new JNIMediaRecorderListener(env, thiz, weak_this);
mr->setListener(listener);
// pass client package name for permissions tracking
mr->setClientName(clientName);
}
static void android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
{
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
//该处获取的surface为null
jobject surface = env->GetObjectField(thiz, fields.surface);
if (surface != NULL) {
....
}
//调用mr->prepare(),mediarecoder的surface是在该方法中完成创建的。
process_media_recorder_call(env, mr->prepare(), "java/io/IOException", "prepare failed.");
}
进到mediarecorder.cpp类
//frameworks\av\media\libmedia\mediarecorder.cpp
//构造函数
MediaRecorder::MediaRecorder(const String16& opPackageName) : mSurfaceMediaSource(NULL)
{
ALOGV("constructor");
//获取IMediaPlayerService服务代理对象(实际是BpMediaPlayerService类对象)
const sp<IMediaPlayerService> service(getMediaPlayerService());
if (service != NULL) {
//通过IMediaPlayerService服务创建IMediaRecorder(实际是BpMediaRecorder类)对象mMediaRecorder
mMediaRecorder = service->createMediaRecorder(opPackageName);
}
if (mMediaRecorder != NULL) {
mCurrentState = MEDIA_RECORDER_IDLE;
}
doCleanUp();
}
prepare 方法
//frameworks\av\media\libmedia\mediarecorder.cpp
status_t MediaRecorder::prepare()
{
ALOGV("prepare");
...
status_t ret = mMediaRecorder->prepare();
...
return ret;
}
获取IMediaPlayerService服务代理的实现 代码:
// establish binder interface to MediaPlayerService
/*static*/const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
IMediaPlayerService服务实现代码:
//rc 文件
//frameworks\av\media\mediaserver\mediaserver.rc
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
至此,可见mMediaRecorder.getSurface()获取的surface实际上获取的是MediaCodecSource.cpp类成员变量mGraphicBufferProducer封装成 的surface对象。
//frameworks\av\media\libstagefright\MediaCodec.cpp
status_t MediaCodec::createInputSurface(
sp<IGraphicBufferProducer>* bufferProducer) {
sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
sp<AMessage> response;
//是通过发消息kWhatCreateInputSurface来创建的surface的
//靠,还需要研究下AMessage的发送接收!!!哥已晕
status_t err = PostAndAwaitResponse(msg, &response);
if (err == NO_ERROR) {
// unwrap the sp<IGraphicBufferProducer>
sp<RefBase> obj;
bool found = response->findObject("input-surface", &obj);
CHECK(found);
sp<BufferProducerWrapper> wrapper(
static_cast<BufferProducerWrapper*>(obj.get()));
*bufferProducer = wrapper->getBufferProducer();
} else {
ALOGW("createInputSurface failed, err=%d", err);
}
return err;
}
进如创建surface的流程
//frameworks\av\media\libstagefright\ACodec.cpp
void ACodec::LoadedState::onCreateInputSurface(
const sp<AMessage> & /* msg */) {
ALOGV("onCreateInputSurface");
//创建surface
sp<IGraphicBufferProducer> bufferProducer;
//mOMX类型是sp<IOMX> mOMX,接下来分析下其创建过程
status_t err = mCodec->mOMX->createInputSurface(
&bufferProducer, &mCodec->mGraphicBufferSource);
...
}
继续分析surface 创建,现在进入OMX createInputSurface创建surface
//frameworks\av\media\libstagefright\omx\OMX.cpp
status_t OMX::createInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferSource> *bufferSource) {
if (bufferProducer == NULL || bufferSource == NULL) {
ALOGE("b/25884056");
return BAD_VALUE;
}
//创建GraphicBufferSource对象,surface就是在该方法创建出来的
sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
status_t err = graphicBufferSource->initCheck();
if (err != OK) {
ALOGE("Failed to create persistent input surface: %s (%d)",
strerror(-err), err);
return err;
}
*bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
*bufferSource = new BWGraphicBufferSource(graphicBufferSource);
return OK;
}
//frameworks\av\media\libstagefright\omx\GraphicBufferSource.cpp
GraphicBufferSource::GraphicBufferSource() {
ALOGV("GraphicBufferSource");
String8 name("GraphicBufferSource");
//创建surface,千辛万苦,终于看到了surface的创建的地方了
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mConsumer->setConsumerName(name);
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
wp<BufferQueue::ConsumerListener> listener =
static_cast<BufferQueue::ConsumerListener*>(this);
sp<IConsumerListener> proxy =
new BufferQueue::ProxyConsumerListener(listener);
mInitCheck = mConsumer->consumerConnect(proxy, false);
}
至此分析完成,mediarecorder创建其内部的surface流程