CameraSource.cpp revision ae4c1ac6401185539c03ce0819e174fd1b04b136
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
36be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
37be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const sp<CameraSource> &source);
38be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
39be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
40be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr);
41be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
42be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
43be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
44be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
45be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
46be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
47be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
50be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
59be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
60be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
62be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
63be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
64be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    LOGV("postData(%d, ptr:%p, size:%d)",
68be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
6965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
7065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
7165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
7265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
7365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
74be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
75be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
77be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
78c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
79c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
80c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
81c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
82c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
83be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
85653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
86e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
87e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
88e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
89e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
90653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
91653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
92653252be963c07c99109d20f942d1f30c52a9360James Dong    }
93653252be963c07c99109d20f942d1f30c52a9360James Dong
94653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
95653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
96653252be963c07c99109d20f942d1f30c52a9360James Dong    }
97653252be963c07c99109d20f942d1f30c52a9360James Dong
98653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
99653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
100653252be963c07c99109d20f942d1f30c52a9360James Dong    }
101653252be963c07c99109d20f942d1f30c52a9360James Dong
102653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
103653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
104653252be963c07c99109d20f942d1f30c52a9360James Dong    }
105653252be963c07c99109d20f942d1f30c52a9360James Dong
106a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong    LOGE("Uknown color format (%s), please add it to "
107a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
108a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
109653252be963c07c99109d20f942d1f30c52a9360James Dong    CHECK_EQ(0, "Unknown color format");
110653252be963c07c99109d20f942d1f30c52a9360James Dong}
111653252be963c07c99109d20f942d1f30c52a9360James Dong
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource *CameraSource::Create() {
11354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
11454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
11554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    sp<ICamera> camera;
1184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12130ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
12254ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1244ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
12554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
12654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
12754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1285c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1295c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
13054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
1325c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate, surface,
1335c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
13454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
13530ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
13630ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13754ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
1394ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
14054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
14154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
14254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1435c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1445c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
14554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
14754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
14854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
14913aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
15065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
15165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
15213aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
1537757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
15413aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
155f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
156f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
15765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
15854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
15954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
16054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1614ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
1625c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1635c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
16495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
16654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
16754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
16854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
16954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
17054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
1724ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
1734ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int32_t cameraId) {
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::connect(cameraId);
1774ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
1784ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // If proxy is not passed in by applications, still use the proxy of
1794ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // our own Camera to simplify the code.
1804ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = mCamera->getRecordingProxy();
18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
1834ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
1844ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
1854ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
1864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
18754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
1884ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
1894ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
19154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
19254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1934ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
1944ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mDeathNotifier = new DeathNotifier();
1954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // isBinderAlive needs linkToDeath to work.
1964ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
1974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
19954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
20054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    LOGV("isVideoSizeSupported");
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
22054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
22554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGD("Camera does not support setVideoSize()");
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
319635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
320635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
321635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
322635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
323635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        LOGV("Supported frame rates: %s", supportedFrameRates);
324635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
325635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
326635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
327635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            LOGE("Requested frame rate (%d) is not supported: %s",
328635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
329635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
330635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
331635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
332635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Could not change settings."
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
36654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
367f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
368f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
369f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
370f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
373f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
374f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
375f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
376f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
377f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
378f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
379f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
380f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
381f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Failed to set video frame size to %dx%d. "
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
44254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
44354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
44454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
44554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4485c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4495c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4505c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4515c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4525c9523154d106b555db6c41f85ab205a4f189b02James Dong *
45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
45654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
4574ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4605c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4615c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
464ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
465ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    err = initWithCameraAccess(camera, proxy, cameraId,
466ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
467ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
468ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
469ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
470ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
471ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
472ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
473ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICamera>& camera,
474ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
475ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
476ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
477ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
478ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
479ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
4809d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
4814ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
4824ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        LOGE("Camera connection could not be established.");
48354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
48454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
48554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
48654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
48754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
48854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
489be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
49054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
49154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
49354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
49654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
497653252be963c07c99109d20f942d1f30c52a9360James Dong
49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
49954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
50054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
50454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // This CHECK is good, since we just passed the lock/unlock
50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // check earlier by calling mCamera->setParameters().
51054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
5112b37ced30f89437c804c3945b901019b86d210aeJames Dong
512abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    // By default, do not store metadata in video buffers
5135c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
514abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    mCamera->storeMetaDataInBuffers(false);
515abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
516abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        if (OK == mCamera->storeMetaDataInBuffers(true)) {
517abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong            mIsMetaDataStoredInVideoBuffers = true;
518abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
5195c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
5205c9523154d106b555db6c41f85ab205a4f189b02James Dong
52154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
522f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
523f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
524f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
525f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
526ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
527ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
528653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
52954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
53054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
53154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
53254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
53354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
53454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
535393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
53654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
53720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
54020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
54120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
542ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
543ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
544ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
545ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
546ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
54720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
54820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
54920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() {
5514ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
5524ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
5534ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
5544ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
5554ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->unlock();
5564ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera.clear();
5574ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
5584ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CHECK_EQ(OK, mCameraRecordingProxy->startRecording(new ProxyListener(this)));
55965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
56065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
561f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
5620c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
56354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
56454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("CameraSource is not initialized yet");
56554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
56654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
568365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
569365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
570365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
571365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
572365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
5739d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
574f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
575f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
576f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
577f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
578f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
579f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
580c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    startCameraRecording();
58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
58665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
5874ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCameraRecordingProxy->stopRecording();
58865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
58965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
590ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
591ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    LOGV("releaseCamera");
59295068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCamera != 0) {
593ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
59495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
59595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            LOGV("Camera was cold when we started, stopping preview");
59695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->stopPreview();
59795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->disconnect();
59895068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        } else {
59995068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            // Unlock the camera so the application can lock it back.
60095068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li            mCamera->unlock();
60195068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
60295068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCamera.clear();
603ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
60495068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
60595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mCameraRecordingProxy != 0) {
60695068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
60795068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        mCameraRecordingProxy.clear();
608ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
609ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCameraFlags = 0;
610ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
611ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() {
61341152efd144ccf70c380d5c9a32105c02a039f43James Dong    LOGD("stop: E");
614c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    Mutex::Autolock autoLock(mLock);
61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
616c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFrameAvailableCondition.signal();
617365a963142093a1cd8efdcea76b5f65096a5b115James Dong
618c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    releaseQueuedFrames();
6197278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesBeingEncoded.empty()) {
62041152efd144ccf70c380d5c9a32105c02a039f43James Dong        if (NO_ERROR !=
62141152efd144ccf70c380d5c9a32105c02a039f43James Dong            mFrameCompleteCondition.waitRelative(mLock, 3000000000LL)) {
62241152efd144ccf70c380d5c9a32105c02a039f43James Dong            LOGW("Timed out waiting for outstanding frames being encoded: %d",
623365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mFramesBeingEncoded.size());
62441152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
6257278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
626d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    stopCameraRecording();
627ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    releaseCamera();
6287278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
629365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
630365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
631365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
632365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
633365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
63413aec890216948b0c364f8f92792129d0335f506James Dong
635ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    if (mNumGlitches > 0) {
636a472613aec322e25891abf5c77bf3f7e3c244920James Dong        LOGW("%d long delays between neighboring video frames", mNumGlitches);
637ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
638ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
63913aec890216948b0c364f8f92792129d0335f506James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
64041152efd144ccf70c380d5c9a32105c02a039f43James Dong    LOGD("stop: X");
64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
6454ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    if (mCameraRecordingProxy != NULL) {
6464ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy->releaseRecordingFrame(frame);
647d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
64865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
64965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
650c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
651c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
6527278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
6537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
65465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
6557278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
65613aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
657c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
658c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
659c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
661653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
664f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
66565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
666f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
667f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
6687278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
6697278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    LOGV("signalBufferReturned: %p", buffer->data());
67056223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
6717278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
6727278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
6737278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
674f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
6757278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
6767278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
6777278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
6787278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
6797278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
6807278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
6817278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
6827278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
6837278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
6847278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
6857278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
688c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("read");
68920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
69120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
693abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
694abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
699be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
70379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
70441152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
7054ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                mFrameAvailableCondition.waitRelative(mLock, 1000000000LL)) {
7064ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                if (!mCameraRecordingProxy->asBinder()->isBinderAlive()) {
7074ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    LOGW("camera recording proxy is gone");
7084ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
7094ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
71041152efd144ccf70c380d5c9a32105c02a039f43James Dong                LOGW("Timed out waiting for incoming camera video frames: %lld us",
71141152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
71241152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
71479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
71579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
71679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
71779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
71879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
71979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
72079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
72179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
72279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
72379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
72479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
72579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
72679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
7277278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
72920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
731c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
732c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
733c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
735a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
736a472613aec322e25891abf5c77bf3f7e3c244920James Dong        LOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
737f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
738c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
739c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
74198cfde007490a5903b729a4718c0dada755ae8f8James Dong    if (mNumFramesReceived > 0) {
74298cfde007490a5903b729a4718c0dada755ae8f8James Dong        CHECK(timestampUs > mLastFrameTimestampUs);
74398cfde007490a5903b729a4718c0dada755ae8f8James Dong        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
74498cfde007490a5903b729a4718c0dada755ae8f8James Dong            ++mNumGlitches;
745f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
746f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
747f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
74865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
74965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
75079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
75165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
75265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
753fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
754fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
755365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
75613aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
757c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
758f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
759f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
760f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
761f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
762f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
763f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
764f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
765f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
766f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
767f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
768be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
76913aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
770be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
77198cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
7727278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
773f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
774f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
775f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGV("initial delay: %lld, current time stamp: %lld",
776f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
77920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7805c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
7815c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("isMetaDataStoredInVideoBuffers");
7825c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
7835c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7845c9523154d106b555db6c41f85ab205a4f189b02James Dong
7854ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
7864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
7874ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
7884ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
7894ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
7904ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
7914ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
7924ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
7934ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
7944ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
7954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    LOGI("Camera recording proxy died");
7964ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
7974ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
799