CameraSource.cpp revision e2d8ba8c36fd39eb98f604b11654aa5466673260
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> 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h> 240c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/stagefright/MediaDebug.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> 30be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h> 31365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h> 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener { 36be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener(const sp<CameraSource> &source); 37be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 38be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); 39be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr); 40be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 41be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual void postDataTimestamp( 42be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); 43be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected: 45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber virtual ~CameraSourceListener(); 46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 48be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber wp<CameraSource> mSource; 49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener(const CameraSourceListener &); 51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraSourceListener &operator=(const CameraSourceListener &); 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 54be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source) 55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber : mSource(source) { 56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() { 59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) { 62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber LOGV("notify(%d, %d, %d)", msgType, ext1, ext2); 63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) { 66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber LOGV("postData(%d, ptr:%p, size:%d)", 67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber msgType, dataPtr->pointer(), dataPtr->size()); 6865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<CameraSource> source = mSource.promote(); 7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra if (source.get() != NULL) { 7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra source->dataCallback(msgType, dataPtr); 7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra } 73be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 74be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 75be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp( 76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { 77c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 78c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong sp<CameraSource> source = mSource.promote(); 79c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (source.get() != NULL) { 80c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); 81c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 82be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber} 8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) { 85e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) { 86e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong return OMX_COLOR_FormatYUV420Planar; 87e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong } 88e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong 89653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) { 90653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYUV422SemiPlanar; 91653252be963c07c99109d20f942d1f30c52a9360James Dong } 92653252be963c07c99109d20f942d1f30c52a9360James Dong 93653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) { 94653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYUV420SemiPlanar; 95653252be963c07c99109d20f942d1f30c52a9360James Dong } 96653252be963c07c99109d20f942d1f30c52a9360James Dong 97653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) { 98653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_FormatYCbYCr; 99653252be963c07c99109d20f942d1f30c52a9360James Dong } 100653252be963c07c99109d20f942d1f30c52a9360James Dong 101653252be963c07c99109d20f942d1f30c52a9360James Dong if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) { 102653252be963c07c99109d20f942d1f30c52a9360James Dong return OMX_COLOR_Format16bitRGB565; 103653252be963c07c99109d20f942d1f30c52a9360James Dong } 104653252be963c07c99109d20f942d1f30c52a9360James Dong 105a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong LOGE("Uknown color format (%s), please add it to " 106a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong "CameraSource::getColorFormat", colorFormat); 107a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong 108653252be963c07c99109d20f942d1f30c52a9360James Dong CHECK_EQ(0, "Unknown color format"); 109653252be963c07c99109d20f942d1f30c52a9360James Dong} 110653252be963c07c99109d20f942d1f30c52a9360James Dong 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() { 11335a055b8bfc6f3cbea409b2897caf936654519cbChih-Chung Chang sp<Camera> camera = Camera::connect(0); 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber if (camera.get() == NULL) { 116be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber return NULL; 117be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber } 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber return new CameraSource(camera); 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12230ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static 123c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James DongCameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) { 12430ab66297501757d745b9ae10da61adcd891f497Andreas Huber if (camera.get() == NULL) { 12530ab66297501757d745b9ae10da61adcd891f497Andreas Huber return NULL; 12630ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 12730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 12830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return new CameraSource(camera); 12930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 13030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 131be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSource::CameraSource(const sp<Camera> &camera) 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mCamera(camera), 13313aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesReceived(0), 13465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mLastFrameTimestampUs(0), 13565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mStarted(false), 13665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mFirstFrameTimeUs(0), 13713aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesEncoded(0), 13813aec890216948b0c364f8f92792129d0335f506James Dong mNumFramesDropped(0), 139f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mNumGlitches(0), 140f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mGlitchDurationThresholdUs(200000), 14165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCollectStats(false) { 1429d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong 1439d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 144be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber String8 s = mCamera->getParameters(); 1459d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 1469d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong 147be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber printf("params: \"%s\"\n", s.string()); 148be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 149ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong int32_t width, height, stride, sliceHeight; 150be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber CameraParameters params(s); 151653252be963c07c99109d20f942d1f30c52a9360James Dong params.getPreviewSize(&width, &height); 152653252be963c07c99109d20f942d1f30c52a9360James Dong 153f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Calculate glitch duraton threshold based on frame rate 154f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int32_t frameRate = params.getPreviewFrameRate(); 155f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t glitchDurationUs = (1000000LL / frameRate); 156f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (glitchDurationUs > mGlitchDurationThresholdUs) { 157f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mGlitchDurationThresholdUs = glitchDurationUs; 158f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 159f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 160653252be963c07c99109d20f942d1f30c52a9360James Dong const char *colorFormatStr = params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT); 161653252be963c07c99109d20f942d1f30c52a9360James Dong CHECK(colorFormatStr != NULL); 162653252be963c07c99109d20f942d1f30c52a9360James Dong int32_t colorFormat = getColorFormat(colorFormatStr); 163653252be963c07c99109d20f942d1f30c52a9360James Dong 164ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // XXX: query camera for the stride and slice height 165ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // when the capability becomes available. 166ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong stride = width; 167ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong sliceHeight = height; 168ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong 169653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta = new MetaData; 170653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 171653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta->setInt32(kKeyColorFormat, colorFormat); 172653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta->setInt32(kKeyWidth, width); 173653252be963c07c99109d20f942d1f30c52a9360James Dong mMeta->setInt32(kKeyHeight, height); 174ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong mMeta->setInt32(kKeyStride, stride); 175ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong mMeta->setInt32(kKeySliceHeight, sliceHeight); 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() { 17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() { 18565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CHECK_EQ(OK, mCamera->startRecording()); 18665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 18765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 188f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) { 1890c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber CHECK(!mStarted); 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 191365a963142093a1cd8efdcea76b5f65096a5b115James Dong char value[PROPERTY_VALUE_MAX]; 192365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (property_get("media.stagefright.record-stats", value, NULL) 193365a963142093a1cd8efdcea76b5f65096a5b115James Dong && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { 194365a963142093a1cd8efdcea76b5f65096a5b115James Dong mCollectStats = true; 195365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 1969d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong 197f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = 0; 198f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t startTimeUs; 199f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (meta && meta->findInt64(kKeyTime, &startTimeUs)) { 200f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = startTimeUs; 201f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 202f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 2039d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 204be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber mCamera->setListener(new CameraSourceListener(this)); 20565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra startCameraRecording(); 2069d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() { 21365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCamera->stopRecording(); 21465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 21565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() { 217c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("stop"); 218c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong Mutex::Autolock autoLock(mLock); 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 220c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFrameAvailableCondition.signal(); 221365a963142093a1cd8efdcea76b5f65096a5b115James Dong 2229d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 223c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mCamera->setListener(NULL); 22465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra stopCameraRecording(); 225c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong releaseQueuedFrames(); 2267278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong while (!mFramesBeingEncoded.empty()) { 227365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("Waiting for outstanding frames being encoded: %d", 228365a963142093a1cd8efdcea76b5f65096a5b115James Dong mFramesBeingEncoded.size()); 2297278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFrameCompleteCondition.wait(mLock); 2307278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 2319d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong mCamera = NULL; 2329d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 2337278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong 234365a963142093a1cd8efdcea76b5f65096a5b115James Dong if (mCollectStats) { 235365a963142093a1cd8efdcea76b5f65096a5b115James Dong LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us", 236365a963142093a1cd8efdcea76b5f65096a5b115James Dong mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, 237365a963142093a1cd8efdcea76b5f65096a5b115James Dong mLastFrameTimestampUs - mFirstFrameTimeUs); 238365a963142093a1cd8efdcea76b5f65096a5b115James Dong } 23913aec890216948b0c364f8f92792129d0335f506James Dong 24013aec890216948b0c364f8f92792129d0335f506James Dong CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); 24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) { 24565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra mCamera->releaseRecordingFrame(frame); 24665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra} 24765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra 248c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() { 249c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong List<sp<IMemory> >::iterator it; 2507278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong while (!mFramesReceived.empty()) { 2517278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong it = mFramesReceived.begin(); 25265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseRecordingFrame(*it); 2537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesReceived.erase(it); 25413aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesDropped; 255c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 256c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong} 257c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() { 259653252be963c07c99109d20f942d1f30c52a9360James Dong return mMeta; 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 262f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) { 263f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 26465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseRecordingFrame(frame); 265f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong IPCThreadState::self()->restoreCallingIdentity(token); 266f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong} 267f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 2687278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) { 2697278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong LOGV("signalBufferReturned: %p", buffer->data()); 27056223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber Mutex::Autolock autoLock(mLock); 2717278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin(); 2727278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong it != mFramesBeingEncoded.end(); ++it) { 2737278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong if ((*it)->pointer() == buffer->data()) { 274f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame((*it)); 2757278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesBeingEncoded.erase(it); 2767278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong ++mNumFramesEncoded; 2777278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong buffer->setObserver(0); 2787278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong buffer->release(); 2797278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFrameCompleteCondition.signal(); 2807278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong return; 2817278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 2827278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 2837278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong CHECK_EQ(0, "signalBufferReturned: bogus buffer"); 2847278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong} 2857278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read( 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **buffer, const ReadOptions *options) { 288c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("read"); 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *buffer = NULL; 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 293abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 294abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_UNSUPPORTED; 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<IMemory> frame; 299be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber int64_t frameTime; 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 303542db5d438988360d491a5add1040a2df9aa90c9James Dong while (mStarted) { 304542db5d438988360d491a5add1040a2df9aa90c9James Dong while(mFramesReceived.empty()) { 305542db5d438988360d491a5add1040a2df9aa90c9James Dong mFrameAvailableCondition.wait(mLock); 306542db5d438988360d491a5add1040a2df9aa90c9James Dong } 307542db5d438988360d491a5add1040a2df9aa90c9James Dong 308542db5d438988360d491a5add1040a2df9aa90c9James Dong if (!mStarted) { 309542db5d438988360d491a5add1040a2df9aa90c9James Dong return OK; 310542db5d438988360d491a5add1040a2df9aa90c9James Dong } 311542db5d438988360d491a5add1040a2df9aa90c9James Dong 312542db5d438988360d491a5add1040a2df9aa90c9James Dong frame = *mFramesReceived.begin(); 313542db5d438988360d491a5add1040a2df9aa90c9James Dong mFramesReceived.erase(mFramesReceived.begin()); 314542db5d438988360d491a5add1040a2df9aa90c9James Dong 315542db5d438988360d491a5add1040a2df9aa90c9James Dong frameTime = *mFrameTimes.begin(); 316542db5d438988360d491a5add1040a2df9aa90c9James Dong mFrameTimes.erase(mFrameTimes.begin()); 317542db5d438988360d491a5add1040a2df9aa90c9James Dong int64_t skipTimeUs; 318542db5d438988360d491a5add1040a2df9aa90c9James Dong if (!options || !options->getSkipFrame(&skipTimeUs)) { 319542db5d438988360d491a5add1040a2df9aa90c9James Dong skipTimeUs = frameTime; 320542db5d438988360d491a5add1040a2df9aa90c9James Dong } 321542db5d438988360d491a5add1040a2df9aa90c9James Dong if (skipTimeUs > frameTime) { 322542db5d438988360d491a5add1040a2df9aa90c9James Dong LOGV("skipTimeUs: %lld us > frameTime: %lld us", 323542db5d438988360d491a5add1040a2df9aa90c9James Dong skipTimeUs, frameTime); 324542db5d438988360d491a5add1040a2df9aa90c9James Dong releaseOneRecordingFrame(frame); 325542db5d438988360d491a5add1040a2df9aa90c9James Dong ++mNumFramesDropped; 326542db5d438988360d491a5add1040a2df9aa90c9James Dong // Safeguard against the abuse of the kSkipFrame_Option. 327542db5d438988360d491a5add1040a2df9aa90c9James Dong if (skipTimeUs - frameTime >= 1E6) { 328542db5d438988360d491a5add1040a2df9aa90c9James Dong LOGE("Frame skipping requested is way too long: %lld us", 329542db5d438988360d491a5add1040a2df9aa90c9James Dong skipTimeUs - frameTime); 330542db5d438988360d491a5add1040a2df9aa90c9James Dong return UNKNOWN_ERROR; 331542db5d438988360d491a5add1040a2df9aa90c9James Dong } 332542db5d438988360d491a5add1040a2df9aa90c9James Dong } else { 333542db5d438988360d491a5add1040a2df9aa90c9James Dong mFramesBeingEncoded.push_back(frame); 334542db5d438988360d491a5add1040a2df9aa90c9James Dong *buffer = new MediaBuffer(frame->pointer(), frame->size()); 335542db5d438988360d491a5add1040a2df9aa90c9James Dong (*buffer)->setObserver(this); 336542db5d438988360d491a5add1040a2df9aa90c9James Dong (*buffer)->add_ref(); 337542db5d438988360d491a5add1040a2df9aa90c9James Dong (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 33856223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber 339542db5d438988360d491a5add1040a2df9aa90c9James Dong return OK; 340542db5d438988360d491a5add1040a2df9aa90c9James Dong } 34120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 3427278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong } 34320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 346c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs, 347c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong int32_t msgType, const sp<IMemory> &data) { 348c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs); 34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Mutex::Autolock autoLock(mLock); 350c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (!mStarted) { 351f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame(data); 35213aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesReceived; 35313aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesDropped; 354c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong return; 355c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 357f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mNumFramesReceived > 0 && 358f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) { 359f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mNumGlitches % 10 == 0) { // Don't spam the log 360f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGW("Long delay detected in video recording"); 361f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 362f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong ++mNumGlitches; 363f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 364f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong 36565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // May need to skip frame or modify timestamp. Currently implemented 36665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra // by the subclass CameraSourceTimeLapse. 36765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra if(skipCurrentFrame(timestampUs)) { 36865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra releaseOneRecordingFrame(data); 36965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra return; 370fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra } 371fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra 372365a963142093a1cd8efdcea76b5f65096a5b115James Dong mLastFrameTimestampUs = timestampUs; 37313aec890216948b0c364f8f92792129d0335f506James Dong if (mNumFramesReceived == 0) { 374c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFirstFrameTimeUs = timestampUs; 375f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Initial delay 376f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (mStartTimeUs > 0) { 377f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong if (timestampUs < mStartTimeUs) { 378f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Frame was captured before recording was started 379f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong // Drop it without updating the statistical data. 380f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong releaseOneRecordingFrame(data); 381f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong return; 382f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 383f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs = timestampUs - mStartTimeUs; 384f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong } 385be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber } 38613aec890216948b0c364f8f92792129d0335f506James Dong ++mNumFramesReceived; 387be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber 3887278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong mFramesReceived.push_back(data); 389f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); 390f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mFrameTimes.push_back(timeUs); 391f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong LOGV("initial delay: %lld, current time stamp: %lld", 392f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong mStartTimeUs, timeUs); 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFrameAvailableCondition.signal(); 39420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 397