1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/* 2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project 3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License. 6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at 7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software 11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and 14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License. 15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */ 16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong//#define LOG_NDEBUG 0 18b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong#define LOG_TAG "CameraSource" 19b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong#include <utils/Log.h> 20e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 21e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <OMX_Component.h> 2271d714ccbf03948d67ab6cebad49703160e5895eJames Dong#include <binder/IPCThreadState.h> 23e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/CameraSource.h> 24b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber#include <media/stagefright/MediaDebug.h> 25155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber#include <media/stagefright/MediaDefs.h> 26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaErrors.h> 27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h> 28000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <camera/Camera.h> 29000479f9e325b4e426a67033abd92d47da412725Mathias Agopian#include <camera/CameraParameters.h> 300c128b67f066b2e691348d5375c2da47b84f69acJames Dong#include <surfaceflinger/Surface.h> 31155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber#include <utils/String8.h> 32dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong#include <cutils/properties.h> 33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android { 35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3696af14d9b013496accf40a85a66fefcba3ac0111James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL; 3796af14d9b013496accf40a85a66fefcba3ac0111James Dong 38155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huberstruct CameraSourceListener : public CameraListener { 39155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber CameraSourceListener(const sp<CameraSource> &source); 40155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 41155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 42bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr, 43bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li camera_frame_metadata_t *metadata); 44155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 45155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber virtual void postDataTimestamp( 46155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 47155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 48155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huberprotected: 49155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber virtual ~CameraSourceListener(); 50155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate: 52155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber wp<CameraSource> mSource; 53155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 54155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber CameraSourceListener(const CameraSourceListener &); 55155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber CameraSourceListener &operator=(const CameraSourceListener &); 56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}; 57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 58155e2ad04c9e15562149772fbbaa39004d4778a7Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source) 59155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber : mSource(source) { 60155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber} 61e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 62155e2ad04c9e15562149772fbbaa39004d4778a7Andreas HuberCameraSourceListener::~CameraSourceListener() { 63155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber} 64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 65155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { 66155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber LOGV("notify(%d, %d, %d)", msgType, ext1, ext2); 67155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber} 68e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 69bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr, 70bb1e275c0e684dd213f124da77110cdd9d6f090cWu-cheng Li camera_frame_metadata_t *metadata) { 71155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber LOGV("postData(%d, ptr:%p, size:%d)", 72155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber msgType, dataPtr->pointer(), dataPtr->size()); 73f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra 74f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra sp<CameraSource> source = mSource.promote(); 75f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra if (source.get() != NULL) { 76f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra source->dataCallback(msgType, dataPtr); 77f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra } 78155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber} 79155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 80155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Hubervoid CameraSourceListener::postDataTimestamp( 81155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 82b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong 83b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong sp<CameraSource> source = mSource.promote(); 84b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong if (source.get() != NULL) { 85b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); 86b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong } 87155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber} 88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 89c2f328d0d2821e402823d6e17589da2849b67d0dJames Dongstatic int32_t getColorFormat(const char* colorFormat) { 909b61dc564e673a116928838e42dae25bdf1e0796James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) { 919b61dc564e673a116928838e42dae25bdf1e0796James Dong return OMX_COLOR_FormatYUV420Planar; 929b61dc564e673a116928838e42dae25bdf1e0796James Dong } 939b61dc564e673a116928838e42dae25bdf1e0796James Dong 94c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) { 95c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong return OMX_COLOR_FormatYUV422SemiPlanar; 96c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong } 97c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 98c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) { 99c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong return OMX_COLOR_FormatYUV420SemiPlanar; 100c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong } 101c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 102c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) { 103c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong return OMX_COLOR_FormatYCbYCr; 104c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong } 105c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 106c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) { 107c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong return OMX_COLOR_Format16bitRGB565; 108c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong } 109c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 110e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) { 111e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar; 112e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket } 113e641dc502bb31d968856a022846414dd8e947e19Dandawate Saket 114b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong LOGE("Uknown color format (%s), please add it to " 115b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong "CameraSource::getColorFormat", colorFormat); 116b5024daa6c49daaf9839923e9665f3a8051cf5d1James Dong 117c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong CHECK_EQ(0, "Unknown color format"); 118c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong} 119c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 120e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberCameraSource *CameraSource::Create() { 1210c128b67f066b2e691348d5375c2da47b84f69acJames Dong Size size; 1220c128b67f066b2e691348d5375c2da47b84f69acJames Dong size.width = -1; 1230c128b67f066b2e691348d5375c2da47b84f69acJames Dong size.height = -1; 124e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1250c128b67f066b2e691348d5375c2da47b84f69acJames Dong sp<ICamera> camera; 12642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li return new CameraSource(camera, NULL, 0, size, -1, NULL, false); 127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 129ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber// static 1300c128b67f066b2e691348d5375c2da47b84f69acJames DongCameraSource *CameraSource::CreateFromCamera( 1310c128b67f066b2e691348d5375c2da47b84f69acJames Dong const sp<ICamera>& camera, 13242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 1330c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t cameraId, 1340c128b67f066b2e691348d5375c2da47b84f69acJames Dong Size videoSize, 1350c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameRate, 136ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong const sp<Surface>& surface, 137ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong bool storeMetaDataInVideoBuffers) { 1380c128b67f066b2e691348d5375c2da47b84f69acJames Dong 13942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li CameraSource *source = new CameraSource(camera, proxy, cameraId, 140ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong videoSize, frameRate, surface, 141ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong storeMetaDataInVideoBuffers); 1420c128b67f066b2e691348d5375c2da47b84f69acJames Dong return source; 143ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber} 144ea6a38c63b9e9aeb45aa22587c069bd3c5d83df8Andreas Huber 1450c128b67f066b2e691348d5375c2da47b84f69acJames DongCameraSource::CameraSource( 1460c128b67f066b2e691348d5375c2da47b84f69acJames Dong const sp<ICamera>& camera, 14742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 1480c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t cameraId, 1490c128b67f066b2e691348d5375c2da47b84f69acJames Dong Size videoSize, 1500c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameRate, 151ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong const sp<Surface>& surface, 152ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong bool storeMetaDataInVideoBuffers) 1530c128b67f066b2e691348d5375c2da47b84f69acJames Dong : mCameraFlags(0), 1540c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoFrameRate(-1), 1550c128b67f066b2e691348d5375c2da47b84f69acJames Dong mCamera(0), 1560c128b67f066b2e691348d5375c2da47b84f69acJames Dong mSurface(surface), 1573300e9667e3daa374659b4a8b97dd92c4d34e501James Dong mNumFramesReceived(0), 158f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra mLastFrameTimestampUs(0), 159f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra mStarted(false), 1603300e9667e3daa374659b4a8b97dd92c4d34e501James Dong mNumFramesEncoded(0), 16196af14d9b013496accf40a85a66fefcba3ac0111James Dong mTimeBetweenFrameCaptureUs(0), 1625f3ab06e90365ad6c4865e2cab358a20e12ce0ebJames Dong mFirstFrameTimeUs(0), 1633300e9667e3daa374659b4a8b97dd92c4d34e501James Dong mNumFramesDropped(0), 16436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mNumGlitches(0), 16536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mGlitchDurationThresholdUs(200000), 166f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra mCollectStats(false) { 1670c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoSize.width = -1; 1680c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoSize.height = -1; 1690c128b67f066b2e691348d5375c2da47b84f69acJames Dong 17042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mInitCheck = init(camera, proxy, cameraId, 171ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong videoSize, frameRate, 172ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong storeMetaDataInVideoBuffers); 173528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li if (mInitCheck != OK) releaseCamera(); 1740c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 1750c128b67f066b2e691348d5375c2da47b84f69acJames Dong 1760c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::initCheck() const { 1770c128b67f066b2e691348d5375c2da47b84f69acJames Dong return mInitCheck; 1780c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 1790c128b67f066b2e691348d5375c2da47b84f69acJames Dong 1800c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::isCameraAvailable( 18142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy, 18242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li int32_t cameraId) { 1830c128b67f066b2e691348d5375c2da47b84f69acJames Dong 1840c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (camera == 0) { 1850c128b67f066b2e691348d5375c2da47b84f69acJames Dong mCamera = Camera::connect(cameraId); 18642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li if (mCamera == 0) return -EBUSY; 1870c128b67f066b2e691348d5375c2da47b84f69acJames Dong mCameraFlags &= ~FLAGS_HOT_CAMERA; 1880c128b67f066b2e691348d5375c2da47b84f69acJames Dong } else { 18942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // We get the proxy from Camera, not ICamera. We need to get the proxy 19042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // to the remote Camera owned by the application. Here mCamera is a 19142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // local Camera object created by us. We cannot use the proxy from 19242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // mCamera here. 1930c128b67f066b2e691348d5375c2da47b84f69acJames Dong mCamera = Camera::create(camera); 19442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li if (mCamera == 0) return -EBUSY; 19542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mCameraRecordingProxy = proxy; 1960c128b67f066b2e691348d5375c2da47b84f69acJames Dong mCameraFlags |= FLAGS_HOT_CAMERA; 197e02802306d63d5209afed11cc609ed6f65d5de89James Dong mDeathNotifier = new DeathNotifier(); 198e02802306d63d5209afed11cc609ed6f65d5de89James Dong // isBinderAlive needs linkToDeath to work. 199e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier); 2000c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 2010c128b67f066b2e691348d5375c2da47b84f69acJames Dong 20242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mCamera->lock(); 20342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li 2040c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 2050c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 2060c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2070c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2080c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 2090c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check to see whether the requested video width and height is one 2100c128b67f066b2e691348d5375c2da47b84f69acJames Dong * of the supported sizes. 2110c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param width the video frame width in pixels 2120c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param height the video frame height in pixels 2130c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param suppportedSizes the vector of sizes that we check against 2140c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return true if the dimension (width and height) is supported. 2150c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 2160c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatic bool isVideoSizeSupported( 2170c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t width, int32_t height, 2180c128b67f066b2e691348d5375c2da47b84f69acJames Dong const Vector<Size>& supportedSizes) { 2190c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2200c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGV("isVideoSizeSupported"); 2210c128b67f066b2e691348d5375c2da47b84f69acJames Dong for (size_t i = 0; i < supportedSizes.size(); ++i) { 2220c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (width == supportedSizes[i].width && 2230c128b67f066b2e691348d5375c2da47b84f69acJames Dong height == supportedSizes[i].height) { 2240c128b67f066b2e691348d5375c2da47b84f69acJames Dong return true; 2250c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 2260c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 2270c128b67f066b2e691348d5375c2da47b84f69acJames Dong return false; 2280c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 2290c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2300c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 2310c128b67f066b2e691348d5375c2da47b84f69acJames Dong * If the preview and video output is separate, we only set the 2320c128b67f066b2e691348d5375c2da47b84f69acJames Dong * the video size, and applications should set the preview size 2330c128b67f066b2e691348d5375c2da47b84f69acJames Dong * to some proper value, and the recording framework will not 2340c128b67f066b2e691348d5375c2da47b84f69acJames Dong * change the preview size; otherwise, if the video and preview 2350c128b67f066b2e691348d5375c2da47b84f69acJames Dong * output is the same, we need to set the preview to be the same 2360c128b67f066b2e691348d5375c2da47b84f69acJames Dong * as the requested video size. 2370c128b67f066b2e691348d5375c2da47b84f69acJames Dong * 2380c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 2390c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 2400c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Query the camera to retrieve the supported video frame sizes 2410c128b67f066b2e691348d5375c2da47b84f69acJames Dong * and also to see whether CameraParameters::setVideoSize() 2420c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is supported or not. 2430c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information 2440c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @@param isSetVideoSizeSupported retunrs whether method 2450c128b67f066b2e691348d5375c2da47b84f69acJames Dong * CameraParameters::setVideoSize() is supported or not. 2460c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param sizes returns the vector of Size objects for the 2470c128b67f066b2e691348d5375c2da47b84f69acJames Dong * supported video frame sizes advertised by the camera. 2480c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 2490c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatic void getSupportedVideoSizes( 2500c128b67f066b2e691348d5375c2da47b84f69acJames Dong const CameraParameters& params, 2510c128b67f066b2e691348d5375c2da47b84f69acJames Dong bool *isSetVideoSizeSupported, 2520c128b67f066b2e691348d5375c2da47b84f69acJames Dong Vector<Size>& sizes) { 2530c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2540c128b67f066b2e691348d5375c2da47b84f69acJames Dong *isSetVideoSizeSupported = true; 2550c128b67f066b2e691348d5375c2da47b84f69acJames Dong params.getSupportedVideoSizes(sizes); 2560c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (sizes.size() == 0) { 2570c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGD("Camera does not support setVideoSize()"); 2580c128b67f066b2e691348d5375c2da47b84f69acJames Dong params.getSupportedPreviewSizes(sizes); 2590c128b67f066b2e691348d5375c2da47b84f69acJames Dong *isSetVideoSizeSupported = false; 2600c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 2610c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 2620c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2630c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 2640c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check whether the camera has the supported color format 2650c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information 2660c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error. 2670c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 2680c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::isCameraColorFormatSupported( 2690c128b67f066b2e691348d5375c2da47b84f69acJames Dong const CameraParameters& params) { 2700c128b67f066b2e691348d5375c2da47b84f69acJames Dong mColorFormat = getColorFormat(params.get( 2710c128b67f066b2e691348d5375c2da47b84f69acJames Dong CameraParameters::KEY_VIDEO_FRAME_FORMAT)); 2720c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (mColorFormat == -1) { 2730c128b67f066b2e691348d5375c2da47b84f69acJames Dong return BAD_VALUE; 2740c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 2750c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 2760c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 2770c128b67f066b2e691348d5375c2da47b84f69acJames Dong 2780c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 2790c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Configure the camera to use the requested video size 2800c128b67f066b2e691348d5375c2da47b84f69acJames Dong * (width and height) and/or frame rate. If both width and 2810c128b67f066b2e691348d5375c2da47b84f69acJames Dong * height are -1, configuration on the video size is skipped. 2820c128b67f066b2e691348d5375c2da47b84f69acJames Dong * if frameRate is -1, configuration on the frame rate 2830c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is skipped. Skipping the configuration allows one to 2840c128b67f066b2e691348d5375c2da47b84f69acJames Dong * use the current camera setting without the need to 2850c128b67f066b2e691348d5375c2da47b84f69acJames Dong * actually know the specific values (see Create() method). 2860c128b67f066b2e691348d5375c2da47b84f69acJames Dong * 2870c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params the CameraParameters to be configured 2880c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param width the target video frame width in pixels 2890c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param height the target video frame height in pixels 2900c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param frameRate the target frame rate in frames per second. 2910c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error. 2920c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 2930c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::configureCamera( 2940c128b67f066b2e691348d5375c2da47b84f69acJames Dong CameraParameters* params, 2950c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t width, int32_t height, 2960c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameRate) { 297e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("configureCamera"); 2980c128b67f066b2e691348d5375c2da47b84f69acJames Dong Vector<Size> sizes; 2990c128b67f066b2e691348d5375c2da47b84f69acJames Dong bool isSetVideoSizeSupportedByCamera = true; 3000c128b67f066b2e691348d5375c2da47b84f69acJames Dong getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes); 3010c128b67f066b2e691348d5375c2da47b84f69acJames Dong bool isCameraParamChanged = false; 3020c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (width != -1 && height != -1) { 3030c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (!isVideoSizeSupported(width, height, sizes)) { 3040c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Video dimension (%dx%d) is unsupported", width, height); 3050c128b67f066b2e691348d5375c2da47b84f69acJames Dong return BAD_VALUE; 3060c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3070c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (isSetVideoSizeSupportedByCamera) { 3080c128b67f066b2e691348d5375c2da47b84f69acJames Dong params->setVideoSize(width, height); 3090c128b67f066b2e691348d5375c2da47b84f69acJames Dong } else { 3100c128b67f066b2e691348d5375c2da47b84f69acJames Dong params->setPreviewSize(width, height); 3110c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3120c128b67f066b2e691348d5375c2da47b84f69acJames Dong isCameraParamChanged = true; 3130c128b67f066b2e691348d5375c2da47b84f69acJames Dong } else if ((width == -1 && height != -1) || 3140c128b67f066b2e691348d5375c2da47b84f69acJames Dong (width != -1 && height == -1)) { 3150c128b67f066b2e691348d5375c2da47b84f69acJames Dong // If one and only one of the width and height is -1 3160c128b67f066b2e691348d5375c2da47b84f69acJames Dong // we reject such a request. 3170c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Requested video size (%dx%d) is not supported", width, height); 3180c128b67f066b2e691348d5375c2da47b84f69acJames Dong return BAD_VALUE; 3190c128b67f066b2e691348d5375c2da47b84f69acJames Dong } else { // width == -1 && height == -1 3200c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Do not configure the camera. 3210c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Use the current width and height value setting from the camera. 3220c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3230c128b67f066b2e691348d5375c2da47b84f69acJames Dong 3240c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (frameRate != -1) { 325b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong CHECK(frameRate > 0 && frameRate <= 120); 326b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong const char* supportedFrameRates = 327b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES); 328b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong CHECK(supportedFrameRates != NULL); 329b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong LOGV("Supported frame rates: %s", supportedFrameRates); 330b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong char buf[4]; 331b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong snprintf(buf, 4, "%d", frameRate); 332b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong if (strstr(supportedFrameRates, buf) == NULL) { 333b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong LOGE("Requested frame rate (%d) is not supported: %s", 334b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong frameRate, supportedFrameRates); 335b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong return BAD_VALUE; 336b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong } 337b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong 338b15f2eaa92070cd4871892bd0db2292e5019b6cdJames Dong // The frame rate is supported, set the camera to the requested value. 3390c128b67f066b2e691348d5375c2da47b84f69acJames Dong params->setPreviewFrameRate(frameRate); 3400c128b67f066b2e691348d5375c2da47b84f69acJames Dong isCameraParamChanged = true; 3410c128b67f066b2e691348d5375c2da47b84f69acJames Dong } else { // frameRate == -1 3420c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Do not configure the camera. 3430c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Use the current frame rate value setting from the camera 3440c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3450c128b67f066b2e691348d5375c2da47b84f69acJames Dong 3460c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (isCameraParamChanged) { 3470c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Either frame rate or frame size needs to be changed. 3480c128b67f066b2e691348d5375c2da47b84f69acJames Dong String8 s = params->flatten(); 3490c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (OK != mCamera->setParameters(s)) { 3500c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Could not change settings." 3510c128b67f066b2e691348d5375c2da47b84f69acJames Dong " Someone else is using camera %p?", mCamera.get()); 3520c128b67f066b2e691348d5375c2da47b84f69acJames Dong return -EBUSY; 3530c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3540c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3550c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 3560c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 3570c128b67f066b2e691348d5375c2da47b84f69acJames Dong 3580c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 3590c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check whether the requested video frame size 3600c128b67f066b2e691348d5375c2da47b84f69acJames Dong * has been successfully configured or not. If both width and height 3610c128b67f066b2e691348d5375c2da47b84f69acJames Dong * are -1, check on the current width and height value setting 3620c128b67f066b2e691348d5375c2da47b84f69acJames Dong * is performed. 3630c128b67f066b2e691348d5375c2da47b84f69acJames Dong * 3640c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information 3650c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame width in pixels to check against 3660c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame height in pixels to check against 3670c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error 3680c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 3690c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::checkVideoSize( 3700c128b67f066b2e691348d5375c2da47b84f69acJames Dong const CameraParameters& params, 3710c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t width, int32_t height) { 3720c128b67f066b2e691348d5375c2da47b84f69acJames Dong 373e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("checkVideoSize"); 37426e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // The actual video size is the same as the preview size 37526e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // if the camera hal does not support separate video and 37626e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // preview output. In this case, we retrieve the video 37726e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // size from preview. 3780c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameWidthActual = -1; 3790c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameHeightActual = -1; 38026e54e258f0331e09c045c7af9b6b8cf11d19257James Dong Vector<Size> sizes; 38126e54e258f0331e09c045c7af9b6b8cf11d19257James Dong params.getSupportedVideoSizes(sizes); 38226e54e258f0331e09c045c7af9b6b8cf11d19257James Dong if (sizes.size() == 0) { 38326e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // video size is the same as preview size 38426e54e258f0331e09c045c7af9b6b8cf11d19257James Dong params.getPreviewSize(&frameWidthActual, &frameHeightActual); 38526e54e258f0331e09c045c7af9b6b8cf11d19257James Dong } else { 38626e54e258f0331e09c045c7af9b6b8cf11d19257James Dong // video size may not be the same as preview 38726e54e258f0331e09c045c7af9b6b8cf11d19257James Dong params.getVideoSize(&frameWidthActual, &frameHeightActual); 38826e54e258f0331e09c045c7af9b6b8cf11d19257James Dong } 3890c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (frameWidthActual < 0 || frameHeightActual < 0) { 3900c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Failed to retrieve video frame size (%dx%d)", 3910c128b67f066b2e691348d5375c2da47b84f69acJames Dong frameWidthActual, frameHeightActual); 3920c128b67f066b2e691348d5375c2da47b84f69acJames Dong return UNKNOWN_ERROR; 3930c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 3940c128b67f066b2e691348d5375c2da47b84f69acJames Dong 3950c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Check the actual video frame size against the target/requested 3960c128b67f066b2e691348d5375c2da47b84f69acJames Dong // video frame size. 3970c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (width != -1 && height != -1) { 3980c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (frameWidthActual != width || frameHeightActual != height) { 3990c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Failed to set video frame size to %dx%d. " 4000c128b67f066b2e691348d5375c2da47b84f69acJames Dong "The actual video size is %dx%d ", width, height, 4010c128b67f066b2e691348d5375c2da47b84f69acJames Dong frameWidthActual, frameHeightActual); 4020c128b67f066b2e691348d5375c2da47b84f69acJames Dong return UNKNOWN_ERROR; 4030c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 4040c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 4050c128b67f066b2e691348d5375c2da47b84f69acJames Dong 4060c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Good now. 4070c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoSize.width = frameWidthActual; 4080c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoSize.height = frameHeightActual; 4090c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 4100c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 4110c128b67f066b2e691348d5375c2da47b84f69acJames Dong 4120c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 4130c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Check the requested frame rate has been successfully configured or not. 4140c128b67f066b2e691348d5375c2da47b84f69acJames Dong * If the target frameRate is -1, check on the current frame rate value 4150c128b67f066b2e691348d5375c2da47b84f69acJames Dong * setting is performed. 4160c128b67f066b2e691348d5375c2da47b84f69acJames Dong * 4170c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param params CameraParameters to retrieve the information 4180c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param the target video frame rate to check against 4190c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error. 4200c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 4210c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::checkFrameRate( 4220c128b67f066b2e691348d5375c2da47b84f69acJames Dong const CameraParameters& params, 4230c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameRate) { 4240c128b67f066b2e691348d5375c2da47b84f69acJames Dong 425e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("checkFrameRate"); 4260c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t frameRateActual = params.getPreviewFrameRate(); 4270c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (frameRateActual < 0) { 4280c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual); 4290c128b67f066b2e691348d5375c2da47b84f69acJames Dong return UNKNOWN_ERROR; 4300c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 4310c128b67f066b2e691348d5375c2da47b84f69acJames Dong 4320c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Check the actual video frame rate against the target/requested 4330c128b67f066b2e691348d5375c2da47b84f69acJames Dong // video frame rate. 4340c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (frameRate != -1 && (frameRateActual - frameRate) != 0) { 4350c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("Failed to set preview frame rate to %d fps. The actual " 4360c128b67f066b2e691348d5375c2da47b84f69acJames Dong "frame rate is %d", frameRate, frameRateActual); 4370c128b67f066b2e691348d5375c2da47b84f69acJames Dong return UNKNOWN_ERROR; 4380c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 4390c128b67f066b2e691348d5375c2da47b84f69acJames Dong 4400c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Good now. 4410c128b67f066b2e691348d5375c2da47b84f69acJames Dong mVideoFrameRate = frameRateActual; 4420c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 4430c128b67f066b2e691348d5375c2da47b84f69acJames Dong} 4440c128b67f066b2e691348d5375c2da47b84f69acJames Dong 4450c128b67f066b2e691348d5375c2da47b84f69acJames Dong/* 4460c128b67f066b2e691348d5375c2da47b84f69acJames Dong * Initialize the CameraSource to so that it becomes 4470c128b67f066b2e691348d5375c2da47b84f69acJames Dong * ready for providing the video input streams as requested. 4480c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param camera the camera object used for the video source 4490c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param cameraId if camera == 0, use camera with this id 4500c128b67f066b2e691348d5375c2da47b84f69acJames Dong * as the video source 4510c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param videoSize the target video frame size. If both 4520c128b67f066b2e691348d5375c2da47b84f69acJames Dong * width and height in videoSize is -1, use the current 4530c128b67f066b2e691348d5375c2da47b84f69acJames Dong * width and heigth settings by the camera 4540c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @param frameRate the target frame rate in frames per second. 4550c128b67f066b2e691348d5375c2da47b84f69acJames Dong * if it is -1, use the current camera frame rate setting. 456ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * @param storeMetaDataInVideoBuffers request to store meta 457ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * data or real YUV data in video buffers. Request to 458ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * store meta data in video buffers may not be honored 459ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * if the source does not support this feature. 460ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong * 4610c128b67f066b2e691348d5375c2da47b84f69acJames Dong * @return OK if no error. 4620c128b67f066b2e691348d5375c2da47b84f69acJames Dong */ 4630c128b67f066b2e691348d5375c2da47b84f69acJames Dongstatus_t CameraSource::init( 4640c128b67f066b2e691348d5375c2da47b84f69acJames Dong const sp<ICamera>& camera, 46542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li const sp<ICameraRecordingProxy>& proxy, 4660c128b67f066b2e691348d5375c2da47b84f69acJames Dong int32_t cameraId, 4670c128b67f066b2e691348d5375c2da47b84f69acJames Dong Size videoSize, 468ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong int32_t frameRate, 469ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong bool storeMetaDataInVideoBuffers) { 4700c128b67f066b2e691348d5375c2da47b84f69acJames Dong 471e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("init"); 4720c128b67f066b2e691348d5375c2da47b84f69acJames Dong status_t err = OK; 4738d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 4748d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong err = initWithCameraAccess(camera, proxy, cameraId, 4758d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong videoSize, frameRate, 4768d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong storeMetaDataInVideoBuffers); 4778d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong IPCThreadState::self()->restoreCallingIdentity(token); 4788d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong return err; 4798d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong} 4808d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong 4818d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dongstatus_t CameraSource::initWithCameraAccess( 4828d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong const sp<ICamera>& camera, 4838d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong const sp<ICameraRecordingProxy>& proxy, 4848d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong int32_t cameraId, 4858d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong Size videoSize, 4868d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong int32_t frameRate, 4878d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong bool storeMetaDataInVideoBuffers) { 488e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("initWithCameraAccess"); 4898d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong status_t err = OK; 49071d714ccbf03948d67ab6cebad49703160e5895eJames Dong 49142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) { 49242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li LOGE("Camera connection could not be established."); 4930c128b67f066b2e691348d5375c2da47b84f69acJames Dong return err; 4940c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 4950c128b67f066b2e691348d5375c2da47b84f69acJames Dong CameraParameters params(mCamera->getParameters()); 4960c128b67f066b2e691348d5375c2da47b84f69acJames Dong if ((err = isCameraColorFormatSupported(params)) != OK) { 4970c128b67f066b2e691348d5375c2da47b84f69acJames Dong return err; 4980c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 499155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 5000c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Set the camera to use the requested video frame size 5010c128b67f066b2e691348d5375c2da47b84f69acJames Dong // and/or frame rate. 5020c128b67f066b2e691348d5375c2da47b84f69acJames Dong if ((err = configureCamera(¶ms, 5030c128b67f066b2e691348d5375c2da47b84f69acJames Dong videoSize.width, videoSize.height, 5040c128b67f066b2e691348d5375c2da47b84f69acJames Dong frameRate))) { 5050c128b67f066b2e691348d5375c2da47b84f69acJames Dong return err; 5060c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 507c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong 5080c128b67f066b2e691348d5375c2da47b84f69acJames Dong // Check on video frame size and frame rate. 5090c128b67f066b2e691348d5375c2da47b84f69acJames Dong CameraParameters newCameraParams(mCamera->getParameters()); 5100c128b67f066b2e691348d5375c2da47b84f69acJames Dong if ((err = checkVideoSize(newCameraParams, 5110c128b67f066b2e691348d5375c2da47b84f69acJames Dong videoSize.width, videoSize.height)) != OK) { 5120c128b67f066b2e691348d5375c2da47b84f69acJames Dong return err; 5130c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 5140c128b67f066b2e691348d5375c2da47b84f69acJames Dong if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) { 5150c128b67f066b2e691348d5375c2da47b84f69acJames Dong return err; 5160c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 5170c128b67f066b2e691348d5375c2da47b84f69acJames Dong 5180c128b67f066b2e691348d5375c2da47b84f69acJames Dong // This CHECK is good, since we just passed the lock/unlock 5190c128b67f066b2e691348d5375c2da47b84f69acJames Dong // check earlier by calling mCamera->setParameters(). 5200c128b67f066b2e691348d5375c2da47b84f69acJames Dong CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface)); 521997eaa2c7c6f7c59d145dab3e93431ea2e2a7dc7James Dong 522845584e7172406224071ebeb04838dc757761bcbJames Dong // By default, do not store metadata in video buffers 523ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong mIsMetaDataStoredInVideoBuffers = false; 524845584e7172406224071ebeb04838dc757761bcbJames Dong mCamera->storeMetaDataInBuffers(false); 525845584e7172406224071ebeb04838dc757761bcbJames Dong if (storeMetaDataInVideoBuffers) { 526845584e7172406224071ebeb04838dc757761bcbJames Dong if (OK == mCamera->storeMetaDataInBuffers(true)) { 527845584e7172406224071ebeb04838dc757761bcbJames Dong mIsMetaDataStoredInVideoBuffers = true; 528845584e7172406224071ebeb04838dc757761bcbJames Dong } 529ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong } 530ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong 5310c128b67f066b2e691348d5375c2da47b84f69acJames Dong int64_t glitchDurationUs = (1000000LL / mVideoFrameRate); 53236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong if (glitchDurationUs > mGlitchDurationThresholdUs) { 53336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mGlitchDurationThresholdUs = glitchDurationUs; 53436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 53536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong 5361244eab2cea41df1db4eeb930fddbb9e67ff7691James Dong // XXX: query camera for the stride and slice height 5371244eab2cea41df1db4eeb930fddbb9e67ff7691James Dong // when the capability becomes available. 538c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong mMeta = new MetaData; 5390c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 5400c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setInt32(kKeyColorFormat, mColorFormat); 5410c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setInt32(kKeyWidth, mVideoSize.width); 5420c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setInt32(kKeyHeight, mVideoSize.height); 5430c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setInt32(kKeyStride, mVideoSize.width); 5440c128b67f066b2e691348d5375c2da47b84f69acJames Dong mMeta->setInt32(kKeySliceHeight, mVideoSize.height); 545aac193cf38ac084eea0f6367b98f6304d1ec38f2James Dong mMeta->setInt32(kKeyFrameRate, mVideoFrameRate); 5460c128b67f066b2e691348d5375c2da47b84f69acJames Dong return OK; 547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 548e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 549e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberCameraSource::~CameraSource() { 550e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 5528d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong } else if (mInitCheck == OK) { 5538d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong // Camera is initialized but because start() is never called, 5548d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong // the lock on Camera is never released(). This makes sure 5558d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong // Camera's lock is released in this case. 5568d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong releaseCamera(); 557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 560f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::startCameraRecording() { 561e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("startCameraRecording"); 56242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // Reset the identity to the current thread because media server owns the 56342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // camera and recording is started by the applications. The applications 56442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li // will connect to the camera in ICameraRecordingProxy::startRecording. 56542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li int64_t token = IPCThreadState::self()->clearCallingIdentity(); 566e02802306d63d5209afed11cc609ed6f65d5de89James Dong if (mCameraFlags & FLAGS_HOT_CAMERA) { 567e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->unlock(); 568e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera.clear(); 569e02802306d63d5209afed11cc609ed6f65d5de89James Dong CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this))); 570e02802306d63d5209afed11cc609ed6f65d5de89James Dong } else { 571e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->setListener(new CameraSourceListener(this)); 572e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->startRecording(); 573e02802306d63d5209afed11cc609ed6f65d5de89James Dong CHECK(mCamera->recordingEnabled()); 574e02802306d63d5209afed11cc609ed6f65d5de89James Dong } 57542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li IPCThreadState::self()->restoreCallingIdentity(token); 576f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra} 577f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra 57836e573bf7db5888f92c52eda26e0771aaa2406e4James Dongstatus_t CameraSource::start(MetaData *meta) { 579e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("start"); 580b5ceb9ee21f37ae0817c16490c1fc148dd3eb5e2Andreas Huber CHECK(!mStarted); 5810c128b67f066b2e691348d5375c2da47b84f69acJames Dong if (mInitCheck != OK) { 5820c128b67f066b2e691348d5375c2da47b84f69acJames Dong LOGE("CameraSource is not initialized yet"); 5830c128b67f066b2e691348d5375c2da47b84f69acJames Dong return mInitCheck; 5840c128b67f066b2e691348d5375c2da47b84f69acJames Dong } 585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 586dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong char value[PROPERTY_VALUE_MAX]; 587dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong if (property_get("media.stagefright.record-stats", value, NULL) 588dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 589dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong mCollectStats = true; 590dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong } 59171d714ccbf03948d67ab6cebad49703160e5895eJames Dong 59236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mStartTimeUs = 0; 59336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong int64_t startTimeUs; 59436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong if (meta && meta->findInt64(kKeyTime, &startTimeUs)) { 59536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mStartTimeUs = startTimeUs; 59636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 59736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong 598df7a856d3d7a62049e3d1091cf07e95019da4609James Dong startCameraRecording(); 599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 604f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::stopCameraRecording() { 605e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("stopCameraRecording"); 606e02802306d63d5209afed11cc609ed6f65d5de89James Dong if (mCameraFlags & FLAGS_HOT_CAMERA) { 607e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCameraRecordingProxy->stopRecording(); 608e02802306d63d5209afed11cc609ed6f65d5de89James Dong } else { 609e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->setListener(NULL); 610e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->stopRecording(); 611e02802306d63d5209afed11cc609ed6f65d5de89James Dong } 612f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra} 613f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra 6145df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dongvoid CameraSource::releaseCamera() { 6155df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong LOGV("releaseCamera"); 616528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li if (mCamera != 0) { 6178d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 618528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { 619528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li LOGV("Camera was cold when we started, stopping preview"); 620528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li mCamera->stopPreview(); 621528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li mCamera->disconnect(); 622528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li } 623e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->unlock(); 624528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li mCamera.clear(); 625e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera = 0; 6268d19d3ae1e828e9189e2174e8ea88374af93f18eJames Dong IPCThreadState::self()->restoreCallingIdentity(token); 627528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li } 628528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li if (mCameraRecordingProxy != 0) { 629528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier); 630528b084be26ff6f5b5d8cf42007bf964857be8daWu-cheng Li mCameraRecordingProxy.clear(); 6315df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong } 6325df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong mCameraFlags = 0; 6335df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong} 6345df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t CameraSource::stop() { 6367455630fff59ac1b68d67077aba360056ca88eceJames Dong LOGD("stop: E"); 637b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong Mutex::Autolock autoLock(mLock); 638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 639b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong mFrameAvailableCondition.signal(); 640dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong 641831227816bdcb360148615393e3e93ac379bf3eaJames Dong int64_t token; 642831227816bdcb360148615393e3e93ac379bf3eaJames Dong bool isTokenValid = false; 643831227816bdcb360148615393e3e93ac379bf3eaJames Dong if (mCamera != 0) { 644831227816bdcb360148615393e3e93ac379bf3eaJames Dong token = IPCThreadState::self()->clearCallingIdentity(); 645831227816bdcb360148615393e3e93ac379bf3eaJames Dong isTokenValid = true; 646831227816bdcb360148615393e3e93ac379bf3eaJames Dong } 647b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong releaseQueuedFrames(); 648dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong while (!mFramesBeingEncoded.empty()) { 6497455630fff59ac1b68d67077aba360056ca88eceJames Dong if (NO_ERROR != 65096af14d9b013496accf40a85a66fefcba3ac0111James Dong mFrameCompleteCondition.waitRelative(mLock, 65196af14d9b013496accf40a85a66fefcba3ac0111James Dong mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { 6527455630fff59ac1b68d67077aba360056ca88eceJames Dong LOGW("Timed out waiting for outstanding frames being encoded: %d", 653dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong mFramesBeingEncoded.size()); 6547455630fff59ac1b68d67077aba360056ca88eceJames Dong } 655dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong } 65663703876801b569caf3737ea6932ea3fc444c245James Dong stopCameraRecording(); 6575df53fe2f038bc23f2e3c452dc8398c8bdd08d30James Dong releaseCamera(); 658831227816bdcb360148615393e3e93ac379bf3eaJames Dong if (isTokenValid) { 659831227816bdcb360148615393e3e93ac379bf3eaJames Dong IPCThreadState::self()->restoreCallingIdentity(token); 660831227816bdcb360148615393e3e93ac379bf3eaJames Dong } 661dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong 662dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong if (mCollectStats) { 663dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us", 664dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 665dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong mLastFrameTimestampUs - mFirstFrameTimeUs); 666dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong } 6673300e9667e3daa374659b4a8b97dd92c4d34e501James Dong 66808800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong if (mNumGlitches > 0) { 669cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong LOGW("%d long delays between neighboring video frames", mNumGlitches); 67008800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong } 67108800f3fdc607e1e8f8d0554eff4a9dc9a6c53d3James Dong 6723300e9667e3daa374659b4a8b97dd92c4d34e501James Dong CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 6737455630fff59ac1b68d67077aba360056ca88eceJames Dong LOGD("stop: X"); 674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 677f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { 678e02802306d63d5209afed11cc609ed6f65d5de89James Dong LOGV("releaseRecordingFrame"); 67942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li if (mCameraRecordingProxy != NULL) { 68042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mCameraRecordingProxy->releaseRecordingFrame(frame); 6810a5825edf5490588d730cae7d9bb7461ad0b29a5James Dong } else if (mCamera != NULL) { 682e02802306d63d5209afed11cc609ed6f65d5de89James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 683e02802306d63d5209afed11cc609ed6f65d5de89James Dong mCamera->releaseRecordingFrame(frame); 684e02802306d63d5209afed11cc609ed6f65d5de89James Dong IPCThreadState::self()->restoreCallingIdentity(token); 68563703876801b569caf3737ea6932ea3fc444c245James Dong } 686f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra} 687f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra 688b00e246669a1da84b1dd7e3f014eedc21747562fJames Dongvoid CameraSource::releaseQueuedFrames() { 689b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong List<sp<IMemory> >::iterator it; 690dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong while (!mFramesReceived.empty()) { 691dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong it = mFramesReceived.begin(); 692f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra releaseRecordingFrame(*it); 693dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong mFramesReceived.erase(it); 6943300e9667e3daa374659b4a8b97dd92c4d34e501James Dong ++mNumFramesDropped; 695b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong } 696b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong} 697b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong 698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> CameraSource::getFormat() { 699c2f328d0d2821e402823d6e17589da2849b67d0dJames Dong return mMeta; 700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 70236e573bf7db5888f92c52eda26e0771aaa2406e4James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) { 703f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra releaseRecordingFrame(frame); 70436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong} 70536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong 706dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) { 707dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong LOGV("signalBufferReturned: %p", buffer->data()); 70822bd242478fa9c9531cf0b750023db5a513eaa8cAndreas Huber Mutex::Autolock autoLock(mLock); 709dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin(); 710dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong it != mFramesBeingEncoded.end(); ++it) { 711dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong if ((*it)->pointer() == buffer->data()) { 71236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong releaseOneRecordingFrame((*it)); 713dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong mFramesBeingEncoded.erase(it); 714dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong ++mNumFramesEncoded; 715dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong buffer->setObserver(0); 716dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong buffer->release(); 717dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong mFrameCompleteCondition.signal(); 718dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong return; 719dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong } 720dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong } 721dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 722dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong} 723dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t CameraSource::read( 725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **buffer, const ReadOptions *options) { 726b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong LOGV("read"); 727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *buffer = NULL; 729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 7316624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 7326624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_UNSUPPORTED; 734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sp<IMemory> frame; 737155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber int64_t frameTime; 738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Mutex::Autolock autoLock(mLock); 7412144f6316d9c993ba20c7de2a6cac35265291cc5James Dong while (mStarted && mFramesReceived.empty()) { 7427455630fff59ac1b68d67077aba360056ca88eceJames Dong if (NO_ERROR != 74396af14d9b013496accf40a85a66fefcba3ac0111James Dong mFrameAvailableCondition.waitRelative(mLock, 74496af14d9b013496accf40a85a66fefcba3ac0111James Dong mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { 745e02802306d63d5209afed11cc609ed6f65d5de89James Dong if (mCameraRecordingProxy != 0 && 746e02802306d63d5209afed11cc609ed6f65d5de89James Dong !mCameraRecordingProxy->asBinder()->isBinderAlive()) { 74742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li LOGW("camera recording proxy is gone"); 74842419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li return ERROR_END_OF_STREAM; 74942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li } 7507455630fff59ac1b68d67077aba360056ca88eceJames Dong LOGW("Timed out waiting for incoming camera video frames: %lld us", 7517455630fff59ac1b68d67077aba360056ca88eceJames Dong mLastFrameTimestampUs); 7527455630fff59ac1b68d67077aba360056ca88eceJames Dong } 753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7542144f6316d9c993ba20c7de2a6cac35265291cc5James Dong if (!mStarted) { 7552144f6316d9c993ba20c7de2a6cac35265291cc5James Dong return OK; 7562144f6316d9c993ba20c7de2a6cac35265291cc5James Dong } 7572144f6316d9c993ba20c7de2a6cac35265291cc5James Dong frame = *mFramesReceived.begin(); 7582144f6316d9c993ba20c7de2a6cac35265291cc5James Dong mFramesReceived.erase(mFramesReceived.begin()); 7592144f6316d9c993ba20c7de2a6cac35265291cc5James Dong 7602144f6316d9c993ba20c7de2a6cac35265291cc5James Dong frameTime = *mFrameTimes.begin(); 7612144f6316d9c993ba20c7de2a6cac35265291cc5James Dong mFrameTimes.erase(mFrameTimes.begin()); 7622144f6316d9c993ba20c7de2a6cac35265291cc5James Dong mFramesBeingEncoded.push_back(frame); 7632144f6316d9c993ba20c7de2a6cac35265291cc5James Dong *buffer = new MediaBuffer(frame->pointer(), frame->size()); 7642144f6316d9c993ba20c7de2a6cac35265291cc5James Dong (*buffer)->setObserver(this); 7652144f6316d9c993ba20c7de2a6cac35265291cc5James Dong (*buffer)->add_ref(); 7662144f6316d9c993ba20c7de2a6cac35265291cc5James Dong (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 767dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong } 768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 771b00e246669a1da84b1dd7e3f014eedc21747562fJames Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs, 772b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong int32_t msgType, const sp<IMemory> &data) { 773b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Mutex::Autolock autoLock(mLock); 775cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) { 776cbeebb194b374a5eea2f1c6ed6298c09a937c4cbJames Dong LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs); 77736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong releaseOneRecordingFrame(data); 778b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong return; 779b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong } 780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 78186f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong if (mNumFramesReceived > 0) { 78286f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong CHECK(timestampUs > mLastFrameTimestampUs); 78386f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) { 78486f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong ++mNumGlitches; 78536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 78636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 78736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong 788f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra // May need to skip frame or modify timestamp. Currently implemented 789f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra // by the subclass CameraSourceTimeLapse. 7902144f6316d9c993ba20c7de2a6cac35265291cc5James Dong if (skipCurrentFrame(timestampUs)) { 791f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra releaseOneRecordingFrame(data); 792f9b80182bcd32d563c23c12b4ac06517fd6da531Nipun Kwatra return; 793d26920ada05843e736d78709812e03797eedee55Nipun Kwatra } 794d26920ada05843e736d78709812e03797eedee55Nipun Kwatra 795dae9fd31907c62712f7a96bb2a8e288b0cca57c2James Dong mLastFrameTimestampUs = timestampUs; 7963300e9667e3daa374659b4a8b97dd92c4d34e501James Dong if (mNumFramesReceived == 0) { 797b00e246669a1da84b1dd7e3f014eedc21747562fJames Dong mFirstFrameTimeUs = timestampUs; 79836e573bf7db5888f92c52eda26e0771aaa2406e4James Dong // Initial delay 79936e573bf7db5888f92c52eda26e0771aaa2406e4James Dong if (mStartTimeUs > 0) { 80036e573bf7db5888f92c52eda26e0771aaa2406e4James Dong if (timestampUs < mStartTimeUs) { 80136e573bf7db5888f92c52eda26e0771aaa2406e4James Dong // Frame was captured before recording was started 80236e573bf7db5888f92c52eda26e0771aaa2406e4James Dong // Drop it without updating the statistical data. 80336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong releaseOneRecordingFrame(data); 80436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong return; 80536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 80636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mStartTimeUs = timestampUs - mStartTimeUs; 80736e573bf7db5888f92c52eda26e0771aaa2406e4James Dong } 808155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber } 8093300e9667e3daa374659b4a8b97dd92c4d34e501James Dong ++mNumFramesReceived; 810155e2ad04c9e15562149772fbbaa39004d4778a7Andreas Huber 81186f8b98e763b34e6a74e81bc9faa3a875c16e18cJames Dong CHECK(data != NULL && data->size() > 0); 812dfb1dd6a8c0c0b0ecde302fae266d9a37617dfdaJames Dong mFramesReceived.push_back(data); 81336e573bf7db5888f92c52eda26e0771aaa2406e4James Dong int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); 81436e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mFrameTimes.push_back(timeUs); 81536e573bf7db5888f92c52eda26e0771aaa2406e4James Dong LOGV("initial delay: %lld, current time stamp: %lld", 81636e573bf7db5888f92c52eda26e0771aaa2406e4James Dong mStartTimeUs, timeUs); 817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFrameAvailableCondition.signal(); 818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 820ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const { 821ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong LOGV("isMetaDataStoredInVideoBuffers"); 822ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong return mIsMetaDataStoredInVideoBuffers; 823ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong} 824ab79d1febcb6d0bfaaf5e8bfb75f4c641c00a2fbJames Dong 82542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) { 82642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mSource = source; 82742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li} 82842419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li 82942419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp( 83042419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 83142419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr); 83242419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li} 83342419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li 83442419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) { 83542419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li LOGI("Camera recording proxy died"); 83642419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li} 83742419ce28a09eb63e29a8fef87e6f5534f41902fWu-cheng Li 838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 839