120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong//#define LOG_NDEBUG 0 18c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#define LOG_TAG "CameraSource" 19c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <utils/Log.h> 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <OMX_Component.h> 229d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong#include <binder/IPCThreadState.h> 23f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h> 25be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <media/stagefright/MediaDefs.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaErrors.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 283cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/Camera.h> 293cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/CameraParameters.h> 30df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/Surface.h> 31be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h> 32365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL; 37e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong 38be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener { 39be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener(const sp<CameraSource> &source); 40be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 41be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 4257c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr, 4357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li camera_frame_metadata_t *metadata); 44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual void postDataTimestamp( 46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 48be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected: 49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual ~CameraSourceListener(); 50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber wp<CameraSource> mSource; 53be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 54be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener(const CameraSourceListener &); 55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener &operator=(const CameraSourceListener &); 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source) 59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber : mSource(source) { 60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() { 63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { 663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2); 67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr, 7057c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li camera_frame_metadata_t *metadata) { 713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("postData(%d, ptr:%p, size:%d)", 72be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber msgType, dataPtr->pointer(), dataPtr->size()); 7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<CameraSource> source = mSource.promote(); 7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra if (source.get() != NULL) { 7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra source->dataCallback(msgType, dataPtr); 7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 78be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 79be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 80be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp( 81be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 82c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 83c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong sp<CameraSource> source = mSource.promote(); 84c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (source.get() != NULL) { 85c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); 86c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 87be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) { 90e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) { 91e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong return OMX_COLOR_FormatYUV420Planar; 92e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong } 93e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong 94653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) { 95653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYUV422SemiPlanar; 96653252be963c07c99109d20f942d1f30c52a9360James Dong } 97653252be963c07c99109d20f942d1f30c52a9360James Dong 98653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) { 99653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYUV420SemiPlanar; 100653252be963c07c99109d20f942d1f30c52a9360James Dong } 101653252be963c07c99109d20f942d1f30c52a9360James Dong 102653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) { 103653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYCbYCr; 104653252be963c07c99109d20f942d1f30c52a9360James Dong } 105653252be963c07c99109d20f942d1f30c52a9360James Dong 106653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) { 107653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_Format16bitRGB565; 108653252be963c07c99109d20f942d1f30c52a9360James Dong } 109653252be963c07c99109d20f942d1f30c52a9360James Dong 1101374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) { 1111374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar; 1121374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket } 1131374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket 114bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) { 115bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala return OMX_COLOR_FormatAndroidOpaque; 116bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala } 117bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala 11829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Uknown color format (%s), please add it to " 119a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong "CameraSource::getColorFormat", colorFormat); 120a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong 121f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong CHECK(!"Unknown color format"); 122653252be963c07c99109d20f942d1f30c52a9360James Dong} 123653252be963c07c99109d20f942d1f30c52a9360James Dong 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() { 12554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size size; 12654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong size.width = -1; 12754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong size.height = -1; 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong sp<ICamera> camera; 1304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li return new CameraSource(camera, NULL, 0, size, -1, NULL, false); 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13330ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static 13454ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera( 13554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const sp<ICamera>& camera, 1364ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 13754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t cameraId, 13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size videoSize, 13954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameRate, 1405c9523154d106b555db6c41f85ab205a4f189b02James Dong const sp<Surface>& surface, 1415c9523154d106b555db6c41f85ab205a4f189b02James Dong bool storeMetaDataInVideoBuffers) { 14254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 1434ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li CameraSource *source = new CameraSource(camera, proxy, cameraId, 1445c9523154d106b555db6c41f85ab205a4f189b02James Dong videoSize, frameRate, surface, 1455c9523154d106b555db6c41f85ab205a4f189b02James Dong storeMetaDataInVideoBuffers); 14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return source; 14730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 14830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 14954ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource( 15054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const sp<ICamera>& camera, 1514ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 15254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t cameraId, 15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size videoSize, 15454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameRate, 1555c9523154d106b555db6c41f85ab205a4f189b02James Dong const sp<Surface>& surface, 1565c9523154d106b555db6c41f85ab205a4f189b02James Dong bool storeMetaDataInVideoBuffers) 15754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong : mCameraFlags(0), 158983cf231ab2d176a14595cdae46ff1b0c239af47James Dong mNumInputBuffers(0), 15954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoFrameRate(-1), 16054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mCamera(0), 16154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mSurface(surface), 16213aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesReceived(0), 16365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mLastFrameTimestampUs(0), 16465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mStarted(false), 16513aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesEncoded(0), 166e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong mTimeBetweenFrameCaptureUs(0), 1677757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong mFirstFrameTimeUs(0), 16813aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesDropped(0), 169f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mNumGlitches(0), 170f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mGlitchDurationThresholdUs(200000), 17165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCollectStats(false) { 17254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoSize.width = -1; 17354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoSize.height = -1; 17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 1754ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mInitCheck = init(camera, proxy, cameraId, 1765c9523154d106b555db6c41f85ab205a4f189b02James Dong videoSize, frameRate, 1775c9523154d106b555db6c41f85ab205a4f189b02James Dong storeMetaDataInVideoBuffers); 17895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li if (mInitCheck != OK) releaseCamera(); 17954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 18054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const { 18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return mInitCheck; 18354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 18454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 18554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable( 1864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, 1874ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li int32_t cameraId) { 18854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 18954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (camera == 0) { 19008ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li mCamera = Camera::connect(cameraId); 1914ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li if (mCamera == 0) return -EBUSY; 19254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mCameraFlags &= ~FLAGS_HOT_CAMERA; 19354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } else { 1944ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // We get the proxy from Camera, not ICamera. We need to get the proxy 1954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // to the remote Camera owned by the application. Here mCamera is a 1964ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // local Camera object created by us. We cannot use the proxy from 1974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // mCamera here. 19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mCamera = Camera::create(camera); 1994ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li if (mCamera == 0) return -EBUSY; 2004ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mCameraRecordingProxy = proxy; 20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mCameraFlags |= FLAGS_HOT_CAMERA; 2023bd3020c00ec8264ac1fe3870800f326487f9221James Dong mDeathNotifier = new DeathNotifier(); 2033bd3020c00ec8264ac1fe3870800f326487f9221James Dong // isBinderAlive needs linkToDeath to work. 2043bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier); 20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 2074ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mCamera->lock(); 2084ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li 20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one 21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes. 21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels 21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels 21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against 21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported. 22054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported( 22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t width, int32_t height, 22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const Vector<Size>& supportedSizes) { 22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 2253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("isVideoSizeSupported"); 22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong for (size_t i = 0; i < supportedSizes.size(); ++i) { 22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (width == supportedSizes[i].width && 22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong height == supportedSizes[i].height) { 22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return true; 23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return false; 23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the 23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size 23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not 23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview 24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same 24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size. 24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * 24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes 24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize() 24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not. 24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information 24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method 25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * CameraParameters::setVideoSize() is supported or not. 25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the 25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * supported video frame sizes advertised by the camera. 25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes( 25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const CameraParameters& params, 25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong bool *isSetVideoSizeSupported, 25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Vector<Size>& sizes) { 25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *isSetVideoSizeSupported = true; 26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong params.getSupportedVideoSizes(sizes); 26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (sizes.size() == 0) { 262b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Camera does not support setVideoSize()"); 26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong params.getSupportedPreviewSizes(sizes); 26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *isSetVideoSizeSupported = false; 26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format 27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information 27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error. 27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported( 27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const CameraParameters& params) { 27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mColorFormat = getColorFormat(params.get( 27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong CameraParameters::KEY_VIDEO_FRAME_FORMAT)); 27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (mColorFormat == -1) { 27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return BAD_VALUE; 27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size 28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and 28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped. 28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate 28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to 28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to 29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method). 29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * 29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured 29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels 29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels 29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second. 29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error. 29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera( 29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong CameraParameters* params, 30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t width, int32_t height, 30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameRate) { 3023856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("configureCamera"); 30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Vector<Size> sizes; 30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong bool isSetVideoSizeSupportedByCamera = true; 30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes); 30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong bool isCameraParamChanged = false; 30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (width != -1 && height != -1) { 30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (!isVideoSizeSupported(width, height, sizes)) { 30929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Video dimension (%dx%d) is unsupported", width, height); 31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return BAD_VALUE; 31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (isSetVideoSizeSupportedByCamera) { 31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong params->setVideoSize(width, height); 31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } else { 31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong params->setPreviewSize(width, height); 31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong isCameraParamChanged = true; 31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } else if ((width == -1 && height != -1) || 31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong (width != -1 && height == -1)) { 32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // If one and only one of the width and height is -1 32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // we reject such a request. 32229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Requested video size (%dx%d) is not supported", width, height); 32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return BAD_VALUE; 32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } else { // width == -1 && height == -1 32554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Do not configure the camera. 32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Use the current width and height value setting from the camera. 32754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (frameRate != -1) { 330635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong CHECK(frameRate > 0 && frameRate <= 120); 331635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong const char* supportedFrameRates = 332635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES); 333635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong CHECK(supportedFrameRates != NULL); 3343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Supported frame rates: %s", supportedFrameRates); 335635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong char buf[4]; 336635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong snprintf(buf, 4, "%d", frameRate); 337635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong if (strstr(supportedFrameRates, buf) == NULL) { 33829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Requested frame rate (%d) is not supported: %s", 339635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong frameRate, supportedFrameRates); 340635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong return BAD_VALUE; 341635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong } 342635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong 343635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong // The frame rate is supported, set the camera to the requested value. 34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong params->setPreviewFrameRate(frameRate); 34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong isCameraParamChanged = true; 34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } else { // frameRate == -1 34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Do not configure the camera. 34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Use the current frame rate value setting from the camera 34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (isCameraParamChanged) { 35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Either frame rate or frame size needs to be changed. 35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong String8 s = params->flatten(); 35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (OK != mCamera->setParameters(s)) { 35529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Could not change settings." 35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong " Someone else is using camera %p?", mCamera.get()); 35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return -EBUSY; 35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size 36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height 36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting 36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed. 36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * 36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information 37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against 37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against 37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error 37354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 37454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize( 37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const CameraParameters& params, 37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t width, int32_t height) { 37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 3783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("checkVideoSize"); 379f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // The actual video size is the same as the preview size 380f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // if the camera hal does not support separate video and 381f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // preview output. In this case, we retrieve the video 382f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // size from preview. 38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameWidthActual = -1; 38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameHeightActual = -1; 385f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong Vector<Size> sizes; 386f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong params.getSupportedVideoSizes(sizes); 387f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong if (sizes.size() == 0) { 388f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // video size is the same as preview size 389f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong params.getPreviewSize(&frameWidthActual, &frameHeightActual); 390f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong } else { 391f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong // video size may not be the same as preview 392f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong params.getVideoSize(&frameWidthActual, &frameHeightActual); 393f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong } 39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (frameWidthActual < 0 || frameHeightActual < 0) { 39529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to retrieve video frame size (%dx%d)", 39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong frameWidthActual, frameHeightActual); 39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return UNKNOWN_ERROR; 39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Check the actual video frame size against the target/requested 40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // video frame size. 40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (width != -1 && height != -1) { 40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (frameWidthActual != width || frameHeightActual != height) { 40429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to set video frame size to %dx%d. " 40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong "The actual video size is %dx%d ", width, height, 40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong frameWidthActual, frameHeightActual); 40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return UNKNOWN_ERROR; 40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Good now. 41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoSize.width = frameWidthActual; 41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoSize.height = frameHeightActual; 41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not. 41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value 42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed. 42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * 42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information 42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against 42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error. 42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate( 42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const CameraParameters& params, 42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameRate) { 42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 4303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("checkFrameRate"); 43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t frameRateActual = params.getPreviewFrameRate(); 43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (frameRateActual < 0) { 43329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); 43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return UNKNOWN_ERROR; 43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Check the actual video frame rate against the target/requested 43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // video frame rate. 43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (frameRate != -1 && (frameRateActual - frameRate) != 0) { 44029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to set preview frame rate to %d fps. The actual " 44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong "frame rate is %d", frameRate, frameRateActual); 44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return UNKNOWN_ERROR; 44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Good now. 44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mVideoFrameRate = frameRateActual; 44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong} 44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/* 45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes 45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested. 45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source 45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id 45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the video source 45654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both 45754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * width and height in videoSize is -1, use the current 45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * width and heigth settings by the camera 45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second. 46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if it is -1, use the current camera frame rate setting. 4615c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta 4625c9523154d106b555db6c41f85ab205a4f189b02James Dong * data or real YUV data in video buffers. Request to 4635c9523154d106b555db6c41f85ab205a4f189b02James Dong * store meta data in video buffers may not be honored 4645c9523154d106b555db6c41f85ab205a4f189b02James Dong * if the source does not support this feature. 4655c9523154d106b555db6c41f85ab205a4f189b02James Dong * 46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error. 46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */ 46854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init( 46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong const sp<ICamera>& camera, 4704ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 47154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int32_t cameraId, 47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong Size videoSize, 4735c9523154d106b555db6c41f85ab205a4f189b02James Dong int32_t frameRate, 4745c9523154d106b555db6c41f85ab205a4f189b02James Dong bool storeMetaDataInVideoBuffers) { 47554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 4763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("init"); 47754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong status_t err = OK; 478ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 479ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong err = initWithCameraAccess(camera, proxy, cameraId, 480ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong videoSize, frameRate, 481ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong storeMetaDataInVideoBuffers); 482ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong IPCThreadState::self()->restoreCallingIdentity(token); 483ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong return err; 484ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong} 485ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong 486ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess( 487ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong const sp<ICamera>& camera, 488ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong const sp<ICameraRecordingProxy>& proxy, 489ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong int32_t cameraId, 490ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong Size videoSize, 491ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong int32_t frameRate, 492ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong bool storeMetaDataInVideoBuffers) { 4933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initWithCameraAccess"); 494ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong status_t err = OK; 4959d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong 4964ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) { 49729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Camera connection could not be established."); 49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return err; 49954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 50054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong CameraParameters params(mCamera->getParameters()); 50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if ((err = isCameraColorFormatSupported(params)) != OK) { 50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return err; 50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 504be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Set the camera to use the requested video frame size 50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // and/or frame rate. 50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if ((err = configureCamera(¶ms, 50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong videoSize.width, videoSize.height, 50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong frameRate))) { 51054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return err; 51154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 512653252be963c07c99109d20f942d1f30c52a9360James Dong 51354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong // Check on video frame size and frame rate. 51454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong CameraParameters newCameraParams(mCamera->getParameters()); 51554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if ((err = checkVideoSize(newCameraParams, 51654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong videoSize.width, videoSize.height)) != OK) { 51754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return err; 51854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 51954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) { 52054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return err; 52154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 52254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong 5238e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li // Set the preview display. Skip this if mSurface is null because 5248e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li // applications may already set a surface to the camera. 5258e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li if (mSurface != NULL) { 5268e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li // This CHECK is good, since we just passed the lock/unlock 5278e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li // check earlier by calling mCamera->setParameters(). 5288e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li CHECK_EQ((status_t)OK, mCamera->setPreviewDisplay(mSurface)); 5298e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li } 5302b37ced30f89437c804c3945b901019b86d210aeJames Dong 531abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong // By default, do not store metadata in video buffers 5325c9523154d106b555db6c41f85ab205a4f189b02James Dong mIsMetaDataStoredInVideoBuffers = false; 533abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong mCamera->storeMetaDataInBuffers(false); 534abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong if (storeMetaDataInVideoBuffers) { 535abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong if (OK == mCamera->storeMetaDataInBuffers(true)) { 536abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong mIsMetaDataStoredInVideoBuffers = true; 537abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong } 5385c9523154d106b555db6c41f85ab205a4f189b02James Dong } 5395c9523154d106b555db6c41f85ab205a4f189b02James Dong 54054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong int64_t glitchDurationUs = (1000000LL / mVideoFrameRate); 541f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (glitchDurationUs > mGlitchDurationThresholdUs) { 542f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mGlitchDurationThresholdUs = glitchDurationUs; 543f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 544f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 545ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // XXX: query camera for the stride and slice height 546ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // when the capability becomes available. 547653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta = new MetaData; 54854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 54954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setInt32(kKeyColorFormat, mColorFormat); 55054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setInt32(kKeyWidth, mVideoSize.width); 55154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setInt32(kKeyHeight, mVideoSize.height); 55254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setInt32(kKeyStride, mVideoSize.width); 55354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong mMeta->setInt32(kKeySliceHeight, mVideoSize.height); 554393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong mMeta->setInt32(kKeyFrameRate, mVideoFrameRate); 55554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return OK; 55620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 55820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() { 55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 560b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong reset(); 561ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong } else if (mInitCheck == OK) { 562ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong // Camera is initialized but because start() is never called, 563ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong // the lock on Camera is never released(). This makes sure 564ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong // Camera's lock is released in this case. 565ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong releaseCamera(); 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() { 5703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("startCameraRecording"); 5714ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // Reset the identity to the current thread because media server owns the 5724ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // camera and recording is started by the applications. The applications 5734ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li // will connect to the camera in ICameraRecordingProxy::startRecording. 5744ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li int64_t token = IPCThreadState::self()->clearCallingIdentity(); 575983cf231ab2d176a14595cdae46ff1b0c239af47James Dong if (mNumInputBuffers > 0) { 576983cf231ab2d176a14595cdae46ff1b0c239af47James Dong status_t err = mCamera->sendCommand( 577983cf231ab2d176a14595cdae46ff1b0c239af47James Dong CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0); 578983cf231ab2d176a14595cdae46ff1b0c239af47James Dong 579983cf231ab2d176a14595cdae46ff1b0c239af47James Dong // This could happen for CameraHAL1 clients; thus the failure is 580983cf231ab2d176a14595cdae46ff1b0c239af47James Dong // not a fatal error 581983cf231ab2d176a14595cdae46ff1b0c239af47James Dong if (err != OK) { 582983cf231ab2d176a14595cdae46ff1b0c239af47James Dong ALOGW("Failed to set video buffer count to %d due to %d", 583983cf231ab2d176a14595cdae46ff1b0c239af47James Dong mNumInputBuffers, err); 584983cf231ab2d176a14595cdae46ff1b0c239af47James Dong } 585983cf231ab2d176a14595cdae46ff1b0c239af47James Dong } 586983cf231ab2d176a14595cdae46ff1b0c239af47James Dong 5873bd3020c00ec8264ac1fe3870800f326487f9221James Dong if (mCameraFlags & FLAGS_HOT_CAMERA) { 5883bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->unlock(); 5893bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera.clear(); 590f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong CHECK_EQ((status_t)OK, 591f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong mCameraRecordingProxy->startRecording(new ProxyListener(this))); 5923bd3020c00ec8264ac1fe3870800f326487f9221James Dong } else { 5933bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->setListener(new CameraSourceListener(this)); 5943bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->startRecording(); 5953bd3020c00ec8264ac1fe3870800f326487f9221James Dong CHECK(mCamera->recordingEnabled()); 5963bd3020c00ec8264ac1fe3870800f326487f9221James Dong } 5974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li IPCThreadState::self()->restoreCallingIdentity(token); 59865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 59965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 600f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) { 6013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("start"); 6020c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mStarted); 60354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong if (mInitCheck != OK) { 60429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("CameraSource is not initialized yet"); 60554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong return mInitCheck; 60654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong } 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 608365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 609365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 610365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 611365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats = true; 612365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 6139d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong 614f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = 0; 615983cf231ab2d176a14595cdae46ff1b0c239af47James Dong mNumInputBuffers = 0; 616983cf231ab2d176a14595cdae46ff1b0c239af47James Dong if (meta) { 617983cf231ab2d176a14595cdae46ff1b0c239af47James Dong int64_t startTimeUs; 618983cf231ab2d176a14595cdae46ff1b0c239af47James Dong if (meta->findInt64(kKeyTime, &startTimeUs)) { 619983cf231ab2d176a14595cdae46ff1b0c239af47James Dong mStartTimeUs = startTimeUs; 620983cf231ab2d176a14595cdae46ff1b0c239af47James Dong } 621983cf231ab2d176a14595cdae46ff1b0c239af47James Dong 622983cf231ab2d176a14595cdae46ff1b0c239af47James Dong int32_t nBuffers; 623983cf231ab2d176a14595cdae46ff1b0c239af47James Dong if (meta->findInt32(kKeyNumBuffers, &nBuffers)) { 624983cf231ab2d176a14595cdae46ff1b0c239af47James Dong CHECK_GT(nBuffers, 0); 625983cf231ab2d176a14595cdae46ff1b0c239af47James Dong mNumInputBuffers = nBuffers; 626983cf231ab2d176a14595cdae46ff1b0c239af47James Dong } 627f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 628f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 629c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong startCameraRecording(); 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 63220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() { 6363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("stopCameraRecording"); 6373bd3020c00ec8264ac1fe3870800f326487f9221James Dong if (mCameraFlags & FLAGS_HOT_CAMERA) { 6383bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCameraRecordingProxy->stopRecording(); 6393bd3020c00ec8264ac1fe3870800f326487f9221James Dong } else { 6403bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->setListener(NULL); 6413bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->stopRecording(); 6423bd3020c00ec8264ac1fe3870800f326487f9221James Dong } 64365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 64465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 645ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() { 6463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("releaseCamera"); 64795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li if (mCamera != 0) { 648ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 64995068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { 6503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Camera was cold when we started, stopping preview"); 65195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li mCamera->stopPreview(); 65295068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li mCamera->disconnect(); 65395068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li } 6543bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->unlock(); 65595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li mCamera.clear(); 6563bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera = 0; 657ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong IPCThreadState::self()->restoreCallingIdentity(token); 65895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li } 65995068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li if (mCameraRecordingProxy != 0) { 66095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier); 66195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li mCameraRecordingProxy.clear(); 662ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong } 663ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong mCameraFlags = 0; 664ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong} 665ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong 666b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t CameraSource::reset() { 667b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong ALOGD("reset: E"); 668c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong Mutex::Autolock autoLock(mLock); 66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 670c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFrameAvailableCondition.signal(); 671365a963142093a1cd8efdcea76b5f65096a5b115James Dong 6729197441e59be323e2f6f0c6506f7248eb6a944b2James Dong int64_t token; 6739197441e59be323e2f6f0c6506f7248eb6a944b2James Dong bool isTokenValid = false; 6749197441e59be323e2f6f0c6506f7248eb6a944b2James Dong if (mCamera != 0) { 6759197441e59be323e2f6f0c6506f7248eb6a944b2James Dong token = IPCThreadState::self()->clearCallingIdentity(); 6769197441e59be323e2f6f0c6506f7248eb6a944b2James Dong isTokenValid = true; 6779197441e59be323e2f6f0c6506f7248eb6a944b2James Dong } 678c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong releaseQueuedFrames(); 6797278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong while (!mFramesBeingEncoded.empty()) { 68041152efd144ccf70c380d5c9a32105c02a039f43James Dong if (NO_ERROR != 681e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong mFrameCompleteCondition.waitRelative(mLock, 682e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { 6835ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Timed out waiting for outstanding frames being encoded: %d", 684365a963142093a1cd8efdcea76b5f65096a5b115James Dong mFramesBeingEncoded.size()); 68541152efd144ccf70c380d5c9a32105c02a039f43James Dong } 6867278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 687d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong stopCameraRecording(); 688ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong releaseCamera(); 6899197441e59be323e2f6f0c6506f7248eb6a944b2James Dong if (isTokenValid) { 6909197441e59be323e2f6f0c6506f7248eb6a944b2James Dong IPCThreadState::self()->restoreCallingIdentity(token); 6919197441e59be323e2f6f0c6506f7248eb6a944b2James Dong } 6927278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong 693365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mCollectStats) { 694df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us", 695365a963142093a1cd8efdcea76b5f65096a5b115James Dong mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 696365a963142093a1cd8efdcea76b5f65096a5b115James Dong mLastFrameTimestampUs - mFirstFrameTimeUs); 697365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 69813aec890216948b0c364f8f92792129d0335f506James Dong 699ba29002c7aee13c068049037cd14bba6a244da6bJames Dong if (mNumGlitches > 0) { 7005ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("%d long delays between neighboring video frames", mNumGlitches); 701ba29002c7aee13c068049037cd14bba6a244da6bJames Dong } 702ba29002c7aee13c068049037cd14bba6a244da6bJames Dong 70313aec890216948b0c364f8f92792129d0335f506James Dong CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 704b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong ALOGD("reset: X"); 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { 7093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("releaseRecordingFrame"); 7104ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li if (mCameraRecordingProxy != NULL) { 7114ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mCameraRecordingProxy->releaseRecordingFrame(frame); 712334d097870eefeb45137b6df026f7db861d47663James Dong } else if (mCamera != NULL) { 7133bd3020c00ec8264ac1fe3870800f326487f9221James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 7143bd3020c00ec8264ac1fe3870800f326487f9221James Dong mCamera->releaseRecordingFrame(frame); 7153bd3020c00ec8264ac1fe3870800f326487f9221James Dong IPCThreadState::self()->restoreCallingIdentity(token); 716d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong } 71765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 71865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 719c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() { 720c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong List<sp<IMemory> >::iterator it; 7217278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong while (!mFramesReceived.empty()) { 7227278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong it = mFramesReceived.begin(); 72365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseRecordingFrame(*it); 7247278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesReceived.erase(it); 72513aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesDropped; 726c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 727c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong} 728c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() { 730653252be963c07c99109d20f942d1f30c52a9360James Dong return mMeta; 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 733f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) { 73465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseRecordingFrame(frame); 735f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong} 736f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 7377278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) { 7383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("signalBufferReturned: %p", buffer->data()); 73956223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber Mutex::Autolock autoLock(mLock); 7407278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin(); 7417278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong it != mFramesBeingEncoded.end(); ++it) { 7427278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong if ((*it)->pointer() == buffer->data()) { 743f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame((*it)); 7447278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesBeingEncoded.erase(it); 7457278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong ++mNumFramesEncoded; 7467278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong buffer->setObserver(0); 7477278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong buffer->release(); 7487278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFrameCompleteCondition.signal(); 7497278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong return; 7507278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 7517278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 752f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong CHECK(!"signalBufferReturned: bogus buffer"); 7537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong} 7547278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong 75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read( 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **buffer, const ReadOptions *options) { 7573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("read"); 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *buffer = NULL; 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 762abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 763abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_UNSUPPORTED; 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<IMemory> frame; 768be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber int64_t frameTime; 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 77279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong while (mStarted && mFramesReceived.empty()) { 77341152efd144ccf70c380d5c9a32105c02a039f43James Dong if (NO_ERROR != 774e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong mFrameAvailableCondition.waitRelative(mLock, 775e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { 7763bd3020c00ec8264ac1fe3870800f326487f9221James Dong if (mCameraRecordingProxy != 0 && 7773bd3020c00ec8264ac1fe3870800f326487f9221James Dong !mCameraRecordingProxy->asBinder()->isBinderAlive()) { 7785ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("camera recording proxy is gone"); 7794ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li return ERROR_END_OF_STREAM; 7804ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li } 7815ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Timed out waiting for incoming camera video frames: %lld us", 78241152efd144ccf70c380d5c9a32105c02a039f43James Dong mLastFrameTimestampUs); 78341152efd144ccf70c380d5c9a32105c02a039f43James Dong } 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 78579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong if (!mStarted) { 78679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong return OK; 78779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong } 78879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong frame = *mFramesReceived.begin(); 78979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong mFramesReceived.erase(mFramesReceived.begin()); 79079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong 79179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong frameTime = *mFrameTimes.begin(); 79279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong mFrameTimes.erase(mFrameTimes.begin()); 79379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong mFramesBeingEncoded.push_back(frame); 79479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong *buffer = new MediaBuffer(frame->pointer(), frame->size()); 79579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong (*buffer)->setObserver(this); 79679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong (*buffer)->add_ref(); 79779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 7987278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 802c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs, 803c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong int32_t msgType, const sp<IMemory> &data) { 8043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 806a472613aec322e25891abf5c77bf3f7e3c244920James Dong if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) { 8073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs); 808f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame(data); 809c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong return; 810c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81298cfde007490a5903b729a4718c0dada755ae8f8James Dong if (mNumFramesReceived > 0) { 81398cfde007490a5903b729a4718c0dada755ae8f8James Dong CHECK(timestampUs > mLastFrameTimestampUs); 81498cfde007490a5903b729a4718c0dada755ae8f8James Dong if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) { 81598cfde007490a5903b729a4718c0dada755ae8f8James Dong ++mNumGlitches; 816f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 817f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 818f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 81965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // May need to skip frame or modify timestamp. Currently implemented 82065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // by the subclass CameraSourceTimeLapse. 82179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong if (skipCurrentFrame(timestampUs)) { 82265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseOneRecordingFrame(data); 82365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return; 824fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra } 825fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra 826365a963142093a1cd8efdcea76b5f65096a5b115James Dong mLastFrameTimestampUs = timestampUs; 82713aec890216948b0c364f8f92792129d0335f506James Dong if (mNumFramesReceived == 0) { 828c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFirstFrameTimeUs = timestampUs; 829f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Initial delay 830f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimeUs > 0) { 831f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (timestampUs < mStartTimeUs) { 832f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Frame was captured before recording was started 833f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Drop it without updating the statistical data. 834f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame(data); 835f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong return; 836f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 837f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = timestampUs - mStartTimeUs; 838f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 839be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber } 84013aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesReceived; 841be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 84298cfde007490a5903b729a4718c0dada755ae8f8James Dong CHECK(data != NULL && data->size() > 0); 8437278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesReceived.push_back(data); 844f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); 845f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mFrameTimes.push_back(timeUs); 8463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("initial delay: %lld, current time stamp: %lld", 847f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs, timeUs); 84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFrameAvailableCondition.signal(); 84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8515c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const { 8523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("isMetaDataStoredInVideoBuffers"); 8535c9523154d106b555db6c41f85ab205a4f189b02James Dong return mIsMetaDataStoredInVideoBuffers; 8545c9523154d106b555db6c41f85ab205a4f189b02James Dong} 8555c9523154d106b555db6c41f85ab205a4f189b02James Dong 8564ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) { 8574ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mSource = source; 8584ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li} 8594ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li 8604ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp( 8614ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 8624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr); 8634ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li} 8644ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li 8654ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) { 866df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Camera recording proxy died"); 8674ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li} 8684ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li 86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 870