From 983cf231ab2d176a14595cdae46ff1b0c239af47 Mon Sep 17 00:00:00 2001 From: James Dong Date: Wed, 1 Aug 2012 16:39:55 -0700 Subject: Dynamically configure the number of video buffers used by camera source, if supported o related-to-bug: 6920805 Change-Id: I413bb50954cc84e32ed40bcb713842dc7b58e2b6 --- include/media/stagefright/CameraSource.h | 1 + media/libstagefright/CameraSource.cpp | 28 ++++++++++++++-- services/camera/libcameraservice/Camera2Client.cpp | 39 ++++++++++++++++++---- services/camera/libcameraservice/Camera2Client.h | 3 +- services/camera/libcameraservice/CameraClient.cpp | 3 ++ 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index 5a35358..6d6b8a9 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -137,6 +137,7 @@ protected: int32_t mCameraFlags; Size mVideoSize; + int32_t mNumInputBuffers; int32_t mVideoFrameRate; int32_t mColorFormat; status_t mInitCheck; diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index a604c8f..efd7af7 100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -155,6 +155,7 @@ CameraSource::CameraSource( const sp& surface, bool storeMetaDataInVideoBuffers) : mCameraFlags(0), + mNumInputBuffers(0), mVideoFrameRate(-1), mCamera(0), mSurface(surface), @@ -571,6 +572,18 @@ void CameraSource::startCameraRecording() { // camera and recording is started by the applications. The applications // will connect to the camera in ICameraRecordingProxy::startRecording. int64_t token = IPCThreadState::self()->clearCallingIdentity(); + if (mNumInputBuffers > 0) { + status_t err = mCamera->sendCommand( + CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0); + + // This could happen for CameraHAL1 clients; thus the failure is + // not a fatal error + if (err != OK) { + ALOGW("Failed to set video buffer count to %d due to %d", + mNumInputBuffers, err); + } + } + if (mCameraFlags & FLAGS_HOT_CAMERA) { mCamera->unlock(); mCamera.clear(); @@ -599,9 +612,18 @@ status_t CameraSource::start(MetaData *meta) { } mStartTimeUs = 0; - int64_t startTimeUs; - if (meta && meta->findInt64(kKeyTime, &startTimeUs)) { - mStartTimeUs = startTimeUs; + mNumInputBuffers = 0; + if (meta) { + int64_t startTimeUs; + if (meta->findInt64(kKeyTime, &startTimeUs)) { + mStartTimeUs = startTimeUs; + } + + int32_t nBuffers; + if (meta->findInt32(kKeyNumBuffers, &nBuffers)) { + CHECK_GT(nBuffers, 0); + mNumInputBuffers = nBuffers; + } } startCameraRecording(); diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 3f1a677..6e26b5f 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -58,7 +58,8 @@ Camera2Client::Camera2Client(const sp& cameraService, mCaptureStreamId(NO_STREAM), mCaptureRequest(NULL), mRecordingStreamId(NO_STREAM), - mRecordingRequest(NULL) + mRecordingRequest(NULL), + mRecordingHeapCount(kDefaultRecordingHeapCount) { ATRACE_CALL(); @@ -1544,6 +1545,30 @@ status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { } else { return NO_INIT; } + } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) { + if (recordingEnabled()) { + ALOGE("%s: Camera %d: Error setting video buffer count after " + "recording was started", __FUNCTION__, mCameraId); + return INVALID_OPERATION; + } + + // 32 is the current upper limit on the video buffer count for BufferQueue + if (arg1 <= 0 || arg1 > 32) { + ALOGE("%s: Camera %d: Error setting %d as video buffer count value", + __FUNCTION__, mCameraId, arg1); + return BAD_VALUE; + } + + // Need to reallocate memory for heap + if (mRecordingHeapCount != arg1) { + if (mRecordingHeap != 0) { + mRecordingHeap.clear(); + mRecordingHeap = NULL; + } + mRecordingHeapCount = arg1; + } + + return OK; } ALOGE("%s: Camera %d: Unimplemented command %d (%d, %d)", __FUNCTION__, @@ -1649,17 +1674,17 @@ void Camera2Client::onRecordingFrameAvailable() { const size_t bufferSize = 4 + sizeof(buffer_handle_t); ALOGV("%s: Camera %d: Creating recording heap with %d buffers of " "size %d bytes", __FUNCTION__, mCameraId, - kRecordingHeapCount, bufferSize); + mRecordingHeapCount, bufferSize); if (mRecordingHeap != 0) { ALOGV("%s: Camera %d: Previous heap has size %d " "(new will be %d) bytes", __FUNCTION__, mCameraId, mRecordingHeap->mHeap->getSize(), - bufferSize * kRecordingHeapCount); + bufferSize * mRecordingHeapCount); } // Need to allocate memory for heap mRecordingHeap.clear(); - mRecordingHeap = new Camera2Heap(bufferSize, kRecordingHeapCount, + mRecordingHeap = new Camera2Heap(bufferSize, mRecordingHeapCount, "Camera2Client::RecordingHeap"); if (mRecordingHeap->mHeap->getSize() == 0) { ALOGE("%s: Camera %d: Unable to allocate memory for recording", @@ -1668,7 +1693,7 @@ void Camera2Client::onRecordingFrameAvailable() { return; } mRecordingHeapHead = 0; - mRecordingHeapFree = kRecordingHeapCount; + mRecordingHeapFree = mRecordingHeapCount; } if ( mRecordingHeapFree == 0) { @@ -1678,7 +1703,7 @@ void Camera2Client::onRecordingFrameAvailable() { return; } heapIdx = mRecordingHeapHead; - mRecordingHeapHead = (mRecordingHeapHead + 1) % kRecordingHeapCount; + mRecordingHeapHead = (mRecordingHeapHead + 1) % mRecordingHeapCount; mRecordingHeapFree--; ALOGV("%s: Camera %d: Timestamp %lld", @@ -2688,7 +2713,7 @@ status_t Camera2Client::updateRecordingStream(const Parameters ¶ms) { if (mRecordingConsumer == 0) { // Create CPU buffer queue endpoint - mRecordingConsumer = new MediaConsumer(kRecordingHeapCount); + mRecordingConsumer = new MediaConsumer(mRecordingHeapCount); mRecordingConsumer->setFrameAvailableListener(new RecordingWaiter(this)); mRecordingConsumer->setName(String8("Camera2Client::RecordingConsumer")); mRecordingWindow = new SurfaceTextureClient( diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index 8ae16a4..9bea8f1 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -288,7 +288,8 @@ private: // TODO: This needs to be queried from somewhere, or the BufferQueue needs // to be passed all the way to stagefright. Right now, set to a large number // to avoid starvation of the video encoders. - static const size_t kRecordingHeapCount = 8; + static const size_t kDefaultRecordingHeapCount = 8; + size_t mRecordingHeapCount; size_t mRecordingHeapHead, mRecordingHeapFree; // Handle new recording image buffers void onRecordingFrameAvailable(); diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index 54829ef..562384d 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -619,6 +619,9 @@ status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { return OK; } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) { mCameraService->playSound(CameraService::SOUND_RECORDING); + } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) { + // Silently ignore this command + return INVALID_OPERATION; } else if (cmd == CAMERA_CMD_PING) { // If mHardware is 0, checkPidAndHardware will return error. return OK; -- cgit v1.1