CameraSource.cpp revision df64d15042bbd5e0e4933ac49bf3c177dd94752c
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>
3054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong#include <surfaceflinger/Surface.h>
31be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h>
32365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
37e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong
38be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
39be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
40be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
41be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
4257c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
4357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                          camera_frame_metadata_t *metadata);
44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
48be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
53be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
54be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
7057c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                                    camera_frame_metadata_t *metadata) {
713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("postData(%d, ptr:%p, size:%d)",
72be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
7465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
7565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
7665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
7765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
78be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
79be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
80be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
81be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
82c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
83c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
84c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
85c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
86c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
87be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
89653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
90e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
91e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
92e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
93e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
94653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
95653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
96653252be963c07c99109d20f942d1f30c52a9360James Dong    }
97653252be963c07c99109d20f942d1f30c52a9360James Dong
98653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
99653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
100653252be963c07c99109d20f942d1f30c52a9360James Dong    }
101653252be963c07c99109d20f942d1f30c52a9360James Dong
102653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
103653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
104653252be963c07c99109d20f942d1f30c52a9360James Dong    }
105653252be963c07c99109d20f942d1f30c52a9360James Dong
106653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
107653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
108653252be963c07c99109d20f942d1f30c52a9360James Dong    }
109653252be963c07c99109d20f942d1f30c52a9360James Dong
1101374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
1111374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
1121374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    }
1131374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket
114a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    LOGE("Uknown color format (%s), please add it to "
115a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
116a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
117653252be963c07c99109d20f942d1f30c52a9360James Dong    CHECK_EQ(0, "Unknown color format");
118653252be963c07c99109d20f942d1f30c52a9360James Dong}
119653252be963c07c99109d20f942d1f30c52a9360James Dong
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() {
12154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
12254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
1264ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12930ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
13054ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
13154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1324ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
13354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
13454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
13554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1365c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1375c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1394ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
1405c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate, surface,
1415c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
14254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
14330ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
14430ab66297501757d745b9ae10da61adcd891f497Andreas Huber
14554ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1474ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
14854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
14954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
15054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1515c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1525c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
15354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
15454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
15554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
15654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
15713aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
15865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
15965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
16013aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
161e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong      mTimeBetweenFrameCaptureUs(0),
1627757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
16313aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
164f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
165f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
16665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
16754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
16854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
16954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1704ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
1715c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1725c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
17395068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
17754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
17854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
18054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
1814ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
1824ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int32_t cameraId) {
18354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
18454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
18554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::connect(cameraId);
1864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
18754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
18854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
1894ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
1904ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
1914ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
1924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
19354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
1944ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
1954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
19654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
1973bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mDeathNotifier = new DeathNotifier();
1983bd3020c00ec8264ac1fe3870800f326487f9221James Dong        // isBinderAlive needs linkToDeath to work.
1993bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
20054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2024ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
2034ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isVideoSizeSupported");
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
22554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
257b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Camera does not support setVideoSize()");
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
2973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("configureCamera");
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
31954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
32254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
325635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
326635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
327635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
328635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
3293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Supported frame rates: %s", supportedFrameRates);
330635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
331635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
332635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
333635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            LOGE("Requested frame rate (%d) is not supported: %s",
334635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
335635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
336635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
337635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
338635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Could not change settings."
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
3733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkVideoSize");
374f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
375f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
376f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
377f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
37854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
37954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
380f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
381f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
382f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
383f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
384f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
385f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
386f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
387f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
388f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Failed to set video frame size to %dx%d. "
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkFrameRate");
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
45254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4565c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4575c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4585c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4595c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4605c9523154d106b555db6c41f85ab205a4f189b02James Dong *
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
4654ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4685c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4695c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
47054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
473ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
474ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    err = initWithCameraAccess(camera, proxy, cameraId,
475ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
476ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
477ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
478ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
479ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
480ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
481ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
482ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICamera>& camera,
483ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
484ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
485ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
486ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
487ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
4883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initWithCameraAccess");
489ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
4909d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
4914ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
4924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        LOGE("Camera connection could not be established.");
49354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
49654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
49754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
499be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
50054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
50454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
507653252be963c07c99109d20f942d1f30c52a9360James Dong
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
51054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
51154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
51254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
51354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
51454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
51554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
51654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
51754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
51854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // This CHECK is good, since we just passed the lock/unlock
51954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // check earlier by calling mCamera->setParameters().
52054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
5212b37ced30f89437c804c3945b901019b86d210aeJames Dong
522abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    // By default, do not store metadata in video buffers
5235c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
524abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    mCamera->storeMetaDataInBuffers(false);
525abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
526abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        if (OK == mCamera->storeMetaDataInBuffers(true)) {
527abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong            mIsMetaDataStoredInVideoBuffers = true;
528abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
5295c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
5305c9523154d106b555db6c41f85ab205a4f189b02James Dong
53154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
532f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
533f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
534f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
535f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
536ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
537ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
538653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
53954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
54054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
54154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
54254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
54354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
54454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
545393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
54654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
552ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
553ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
554ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
555ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
556ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
55720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
55820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
56065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() {
5613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startCameraRecording");
5624ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
5634ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
5644ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
5654ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
5663bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
5673bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
5683bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera.clear();
5693bd3020c00ec8264ac1fe3870800f326487f9221James Dong        CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
5703bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
5713bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(new CameraSourceListener(this));
5723bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->startRecording();
5733bd3020c00ec8264ac1fe3870800f326487f9221James Dong        CHECK(mCamera->recordingEnabled());
5743bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
5754ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
57665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
57765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
578f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
5793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("start");
5800c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
58154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
58254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("CameraSource is not initialized yet");
58354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
58454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
586365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
587365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
588365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
589365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
590365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
5919d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
592f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
593f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
594f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
595f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
596f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
597f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
598c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    startCameraRecording();
59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
6053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stopCameraRecording");
6063bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
6073bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCameraRecordingProxy->stopRecording();
6083bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
6093bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(NULL);
6103bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->stopRecording();
6113bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
61265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
61365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
614ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
6153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseCamera");
61695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCamera != 0) {
617ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
61895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
6193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Camera was cold when we started, stopping preview");
62095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->stopPreview();
62195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->disconnect();
62295068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
6233bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
62495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCamera.clear();
6253bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera = 0;
626ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
62795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
62895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCameraRecordingProxy != 0) {
62995068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
63095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy.clear();
631ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
632ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCameraFlags = 0;
633ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
634ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() {
636b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("stop: E");
637c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    Mutex::Autolock autoLock(mLock);
63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
639c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFrameAvailableCondition.signal();
640365a963142093a1cd8efdcea76b5f65096a5b115James Dong
6419197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    int64_t token;
6429197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    bool isTokenValid = false;
6439197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    if (mCamera != 0) {
6449197441e59be323e2f6f0c6506f7248eb6a944b2James Dong        token = IPCThreadState::self()->clearCallingIdentity();
6459197441e59be323e2f6f0c6506f7248eb6a944b2James Dong        isTokenValid = true;
6469197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    }
647c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    releaseQueuedFrames();
6487278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesBeingEncoded.empty()) {
64941152efd144ccf70c380d5c9a32105c02a039f43James Dong        if (NO_ERROR !=
650e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong            mFrameCompleteCondition.waitRelative(mLock,
651e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
65241152efd144ccf70c380d5c9a32105c02a039f43James Dong            LOGW("Timed out waiting for outstanding frames being encoded: %d",
653365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mFramesBeingEncoded.size());
65441152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
6557278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
656d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    stopCameraRecording();
657ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    releaseCamera();
6589197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    if (isTokenValid) {
6599197441e59be323e2f6f0c6506f7248eb6a944b2James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
6609197441e59be323e2f6f0c6506f7248eb6a944b2James Dong    }
6617278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
662365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
663df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
664365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
665365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
666365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
66713aec890216948b0c364f8f92792129d0335f506James Dong
668ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    if (mNumGlitches > 0) {
669a472613aec322e25891abf5c77bf3f7e3c244920James Dong        LOGW("%d long delays between neighboring video frames", mNumGlitches);
670ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
671ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
67213aec890216948b0c364f8f92792129d0335f506James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
673b8a805261bf0282e992d3608035e47d05a898710Steve Block    ALOGD("stop: X");
67420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
67520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
67765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
6783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseRecordingFrame");
6794ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (mCameraRecordingProxy != NULL) {
6804ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
681334d097870eefeb45137b6df026f7db861d47663James Dong    } else if (mCamera != NULL) {
6823bd3020c00ec8264ac1fe3870800f326487f9221James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
6833bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->releaseRecordingFrame(frame);
6843bd3020c00ec8264ac1fe3870800f326487f9221James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
685d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
68665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
68765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
688c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
689c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
6907278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
6917278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
69265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
6937278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
69413aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
695c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
696c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
697c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
699653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
702f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
70365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
704f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
705f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
7067278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
7073856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
70856223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
7097278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
7107278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
7117278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
712f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
7137278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
7147278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
7157278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
7167278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
7177278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
7187278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
7197278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
7207278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
7217278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
7227278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
7237278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
7263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read");
72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
731abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
732abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
737be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
74179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
74241152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
743e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                mFrameAvailableCondition.waitRelative(mLock,
744e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
7453bd3020c00ec8264ac1fe3870800f326487f9221James Dong                if (mCameraRecordingProxy != 0 &&
7463bd3020c00ec8264ac1fe3870800f326487f9221James Dong                    !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
7474ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    LOGW("camera recording proxy is gone");
7484ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
7494ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
75041152efd144ccf70c380d5c9a32105c02a039f43James Dong                LOGW("Timed out waiting for incoming camera video frames: %lld us",
75141152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
75241152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
75579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
75679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
75779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
75879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
75979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
76079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
76179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
76279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
76379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
76479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
76579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
76679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
7677278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
771c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
772c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
7733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
775a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
7763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
777f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
778c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
779c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78198cfde007490a5903b729a4718c0dada755ae8f8James Dong    if (mNumFramesReceived > 0) {
78298cfde007490a5903b729a4718c0dada755ae8f8James Dong        CHECK(timestampUs > mLastFrameTimestampUs);
78398cfde007490a5903b729a4718c0dada755ae8f8James Dong        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
78498cfde007490a5903b729a4718c0dada755ae8f8James Dong            ++mNumGlitches;
785f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
786f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
787f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
78865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
78965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
79079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
79165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
79265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
793fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
794fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
795365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
79613aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
797c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
798f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
799f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
800f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
801f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
802f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
803f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
804f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
805f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
806f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
807f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
808be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
80913aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
810be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
81198cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
8127278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
813f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
814f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
8153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initial delay: %lld, current time stamp: %lld",
816f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8205c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
8213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isMetaDataStoredInVideoBuffers");
8225c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
8235c9523154d106b555db6c41f85ab205a4f189b02James Dong}
8245c9523154d106b555db6c41f85ab205a4f189b02James Dong
8254ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
8264ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
8274ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8284ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
8294ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
8304ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
8314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
8324ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8334ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
8344ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
835df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Camera recording proxy died");
8364ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
8374ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
839