| /* |
| ** |
| ** Copyright 2008, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "IMediaRecorder" |
| #include <utils/Log.h> |
| #include <binder/Parcel.h> |
| #include <surfaceflinger/Surface.h> |
| #include <camera/ICamera.h> |
| #include <media/IMediaRecorderClient.h> |
| #include <media/IMediaRecorder.h> |
| #include <gui/ISurfaceTexture.h> |
| #include <unistd.h> |
| |
| |
| namespace android { |
| |
| enum { |
| RELEASE = IBinder::FIRST_CALL_TRANSACTION, |
| INIT, |
| CLOSE, |
| QUERY_SURFACE_MEDIASOURCE, |
| RESET, |
| STOP, |
| START, |
| PREPARE, |
| GET_MAX_AMPLITUDE, |
| SET_VIDEO_SOURCE, |
| SET_AUDIO_SOURCE, |
| SET_OUTPUT_FORMAT, |
| SET_VIDEO_ENCODER, |
| SET_AUDIO_ENCODER, |
| SET_OUTPUT_FILE_PATH, |
| SET_OUTPUT_FILE_FD, |
| SET_VIDEO_SIZE, |
| SET_VIDEO_FRAMERATE, |
| SET_PARAMETERS, |
| SET_PREVIEW_SURFACE, |
| SET_CAMERA, |
| SET_LISTENER |
| }; |
| |
| class BpMediaRecorder: public BpInterface<IMediaRecorder> |
| { |
| public: |
| BpMediaRecorder(const sp<IBinder>& impl) |
| : BpInterface<IMediaRecorder>(impl) |
| { |
| } |
| |
| status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy) |
| { |
| LOGV("setCamera(%p,%p)", camera.get(), proxy.get()); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeStrongBinder(camera->asBinder()); |
| data.writeStrongBinder(proxy->asBinder()); |
| remote()->transact(SET_CAMERA, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| sp<ISurfaceTexture> querySurfaceMediaSource() |
| { |
| LOGV("Query SurfaceMediaSource"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply); |
| int returnedNull = reply.readInt32(); |
| if (returnedNull) { |
| return NULL; |
| } |
| return interface_cast<ISurfaceTexture>(reply.readStrongBinder()); |
| } |
| |
| status_t setPreviewSurface(const sp<Surface>& surface) |
| { |
| LOGV("setPreviewSurface(%p)", surface.get()); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| Surface::writeToParcel(surface, &data); |
| remote()->transact(SET_PREVIEW_SURFACE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t init() |
| { |
| LOGV("init"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(INIT, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setVideoSource(int vs) |
| { |
| LOGV("setVideoSource(%d)", vs); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(vs); |
| remote()->transact(SET_VIDEO_SOURCE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setAudioSource(int as) |
| { |
| LOGV("setAudioSource(%d)", as); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(as); |
| remote()->transact(SET_AUDIO_SOURCE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setOutputFormat(int of) |
| { |
| LOGV("setOutputFormat(%d)", of); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(of); |
| remote()->transact(SET_OUTPUT_FORMAT, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setVideoEncoder(int ve) |
| { |
| LOGV("setVideoEncoder(%d)", ve); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(ve); |
| remote()->transact(SET_VIDEO_ENCODER, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setAudioEncoder(int ae) |
| { |
| LOGV("setAudioEncoder(%d)", ae); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(ae); |
| remote()->transact(SET_AUDIO_ENCODER, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setOutputFile(const char* path) |
| { |
| LOGV("setOutputFile(%s)", path); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeCString(path); |
| remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setOutputFile(int fd, int64_t offset, int64_t length) { |
| LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeFileDescriptor(fd); |
| data.writeInt64(offset); |
| data.writeInt64(length); |
| remote()->transact(SET_OUTPUT_FILE_FD, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setVideoSize(int width, int height) |
| { |
| LOGV("setVideoSize(%dx%d)", width, height); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(width); |
| data.writeInt32(height); |
| remote()->transact(SET_VIDEO_SIZE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setVideoFrameRate(int frames_per_second) |
| { |
| LOGV("setVideoFrameRate(%d)", frames_per_second); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeInt32(frames_per_second); |
| remote()->transact(SET_VIDEO_FRAMERATE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setParameters(const String8& params) |
| { |
| LOGV("setParameter(%s)", params.string()); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeString8(params); |
| remote()->transact(SET_PARAMETERS, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t setListener(const sp<IMediaRecorderClient>& listener) |
| { |
| LOGV("setListener(%p)", listener.get()); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| data.writeStrongBinder(listener->asBinder()); |
| remote()->transact(SET_LISTENER, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t prepare() |
| { |
| LOGV("prepare"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(PREPARE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t getMaxAmplitude(int* max) |
| { |
| LOGV("getMaxAmplitude"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(GET_MAX_AMPLITUDE, data, &reply); |
| *max = reply.readInt32(); |
| return reply.readInt32(); |
| } |
| |
| status_t start() |
| { |
| LOGV("start"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(START, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t stop() |
| { |
| LOGV("stop"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(STOP, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t reset() |
| { |
| LOGV("reset"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(RESET, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t close() |
| { |
| LOGV("close"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(CLOSE, data, &reply); |
| return reply.readInt32(); |
| } |
| |
| status_t release() |
| { |
| LOGV("release"); |
| Parcel data, reply; |
| data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); |
| remote()->transact(RELEASE, data, &reply); |
| return reply.readInt32(); |
| } |
| }; |
| |
| IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder"); |
| |
| // ---------------------------------------------------------------------- |
| |
| status_t BnMediaRecorder::onTransact( |
| uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) |
| { |
| switch(code) { |
| case RELEASE: { |
| LOGV("RELEASE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(release()); |
| return NO_ERROR; |
| } break; |
| case INIT: { |
| LOGV("INIT"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(init()); |
| return NO_ERROR; |
| } break; |
| case CLOSE: { |
| LOGV("CLOSE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(close()); |
| return NO_ERROR; |
| } break; |
| case RESET: { |
| LOGV("RESET"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(reset()); |
| return NO_ERROR; |
| } break; |
| case STOP: { |
| LOGV("STOP"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(stop()); |
| return NO_ERROR; |
| } break; |
| case START: { |
| LOGV("START"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(start()); |
| return NO_ERROR; |
| } break; |
| case PREPARE: { |
| LOGV("PREPARE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(prepare()); |
| return NO_ERROR; |
| } break; |
| case GET_MAX_AMPLITUDE: { |
| LOGV("GET_MAX_AMPLITUDE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int max = 0; |
| status_t ret = getMaxAmplitude(&max); |
| reply->writeInt32(max); |
| reply->writeInt32(ret); |
| return NO_ERROR; |
| } break; |
| case SET_VIDEO_SOURCE: { |
| LOGV("SET_VIDEO_SOURCE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int vs = data.readInt32(); |
| reply->writeInt32(setVideoSource(vs)); |
| return NO_ERROR; |
| } break; |
| case SET_AUDIO_SOURCE: { |
| LOGV("SET_AUDIO_SOURCE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int as = data.readInt32(); |
| reply->writeInt32(setAudioSource(as)); |
| return NO_ERROR; |
| } break; |
| case SET_OUTPUT_FORMAT: { |
| LOGV("SET_OUTPUT_FORMAT"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int of = data.readInt32(); |
| reply->writeInt32(setOutputFormat(of)); |
| return NO_ERROR; |
| } break; |
| case SET_VIDEO_ENCODER: { |
| LOGV("SET_VIDEO_ENCODER"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int ve = data.readInt32(); |
| reply->writeInt32(setVideoEncoder(ve)); |
| return NO_ERROR; |
| } break; |
| case SET_AUDIO_ENCODER: { |
| LOGV("SET_AUDIO_ENCODER"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int ae = data.readInt32(); |
| reply->writeInt32(setAudioEncoder(ae)); |
| return NO_ERROR; |
| |
| } break; |
| case SET_OUTPUT_FILE_PATH: { |
| LOGV("SET_OUTPUT_FILE_PATH"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| const char* path = data.readCString(); |
| reply->writeInt32(setOutputFile(path)); |
| return NO_ERROR; |
| } break; |
| case SET_OUTPUT_FILE_FD: { |
| LOGV("SET_OUTPUT_FILE_FD"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int fd = dup(data.readFileDescriptor()); |
| int64_t offset = data.readInt64(); |
| int64_t length = data.readInt64(); |
| reply->writeInt32(setOutputFile(fd, offset, length)); |
| ::close(fd); |
| return NO_ERROR; |
| } break; |
| case SET_VIDEO_SIZE: { |
| LOGV("SET_VIDEO_SIZE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int width = data.readInt32(); |
| int height = data.readInt32(); |
| reply->writeInt32(setVideoSize(width, height)); |
| return NO_ERROR; |
| } break; |
| case SET_VIDEO_FRAMERATE: { |
| LOGV("SET_VIDEO_FRAMERATE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| int frames_per_second = data.readInt32(); |
| reply->writeInt32(setVideoFrameRate(frames_per_second)); |
| return NO_ERROR; |
| } break; |
| case SET_PARAMETERS: { |
| LOGV("SET_PARAMETER"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| reply->writeInt32(setParameters(data.readString8())); |
| return NO_ERROR; |
| } break; |
| case SET_LISTENER: { |
| LOGV("SET_LISTENER"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| sp<IMediaRecorderClient> listener = |
| interface_cast<IMediaRecorderClient>(data.readStrongBinder()); |
| reply->writeInt32(setListener(listener)); |
| return NO_ERROR; |
| } break; |
| case SET_PREVIEW_SURFACE: { |
| LOGV("SET_PREVIEW_SURFACE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| sp<Surface> surface = Surface::readFromParcel(data); |
| reply->writeInt32(setPreviewSurface(surface)); |
| return NO_ERROR; |
| } break; |
| case SET_CAMERA: { |
| LOGV("SET_CAMERA"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder()); |
| sp<ICameraRecordingProxy> proxy = |
| interface_cast<ICameraRecordingProxy>(data.readStrongBinder()); |
| reply->writeInt32(setCamera(camera, proxy)); |
| return NO_ERROR; |
| } break; |
| case QUERY_SURFACE_MEDIASOURCE: { |
| LOGV("QUERY_SURFACE_MEDIASOURCE"); |
| CHECK_INTERFACE(IMediaRecorder, data, reply); |
| // call the mediaserver side to create |
| // a surfacemediasource |
| sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource(); |
| // The mediaserver might have failed to create a source |
| int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ; |
| reply->writeInt32(returnedNull); |
| if (!returnedNull) { |
| reply->writeStrongBinder(surfaceMediaSource->asBinder()); |
| } |
| return NO_ERROR; |
| } break; |
| default: |
| return BBinder::onTransact(code, data, reply, flags); |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| }; // namespace android |