CameraSource.cpp revision d69c7f654cc772b03717999c1b24402d5c40e69f
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;
1185c9523154d106b555db6c41f85ab205a4f189b02James Dong    return new CameraSource(camera, 0, size, -1, NULL, false);
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
12130ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
12254ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
12354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
12454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
12554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
12654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1275c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1285c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
12954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
13054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraSource *source = new CameraSource(camera, cameraId,
1315c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate, surface,
1325c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
13354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
13430ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
13530ab66297501757d745b9ae10da61adcd891f497Andreas Huber
13654ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
13754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera,
13854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
13954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
14054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
1415c9523154d106b555db6c41f85ab205a4f189b02James Dong    const sp<Surface>& surface,
1425c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
14354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
14454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
14554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
14654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
14713aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
14865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
14965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
15065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mFirstFrameTimeUs(0),
15113aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
15213aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
153f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
154f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
15565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
1569d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
15754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
15854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
15954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1605c9523154d106b555db6c41f85ab205a4f189b02James Dong    mInitCheck = init(camera, cameraId,
1615c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
1625c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
16354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
16454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
16554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
16654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
16754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
16854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
16954ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
17054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const sp<ICamera>& camera, int32_t cameraId) {
17154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
17254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
17354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::connect(cameraId);
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
17654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
17754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
17854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
17954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
18054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Is camera available?
18154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mCamera == 0) {
18254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Camera connection could not be established.");
18354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return -EBUSY;
18454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
18554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (!(mCameraFlags & FLAGS_HOT_CAMERA)) {
18654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera->lock();
18754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
18854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
18954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
19154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
19254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
19354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
19454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
19554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
19654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
19754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
19954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
20054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
20154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
20254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
20354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    LOGV("isVideoSizeSupported");
20554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
20654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
20754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
21054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
21154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
21354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
21754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
21854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
21954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
22054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
22154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
22254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
22354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
22454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
22554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
22654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
22754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
23154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
23254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
23354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
23454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
23554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGD("Camera does not support setVideoSize()");
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
24354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
24454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
24754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
24854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
25154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
25254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
25354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
25454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
25654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
25754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
25954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
26054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
26154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
26454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
26554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
28254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Video dimension (%dx%d) is unsupported", width, height);
289ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong            releaseCamera();
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Requested video size (%dx%d) is not supported", width, height);
303ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        releaseCamera();
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
311635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
312635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
313635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
314635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
315635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        LOGV("Supported frame rates: %s", supportedFrameRates);
316635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
317635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
318635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
319635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            LOGE("Requested frame rate (%d) is not supported: %s",
320635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
321ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong            releaseCamera();
322635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
323635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
324635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
325635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
32754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
33054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
33154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
33254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Could not change settings."
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
35954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
360f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
361f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
362f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
363f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
366f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
367f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
368f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
369f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
370f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
371f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
372f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
373f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
374f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve video frame size (%dx%d)",
37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
37854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
37954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
38054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            LOGE("Failed to set video frame size to %dx%d. "
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
38754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
38854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
38954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
39054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
39154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
39354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
39454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
39554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
39654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
39754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
39854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
39954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
40054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
41254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("Failed to set preview frame rate to %d fps. The actual "
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
43554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
43654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
43754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
43854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
43954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
4415c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
4425c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
4435c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
4445c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
4455c9523154d106b555db6c41f85ab205a4f189b02James Dong *
44654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
44754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
44854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
44954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const sp<ICamera>& camera,
45054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
4525c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
4535c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
4569d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
4579d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err  = isCameraAvailable(camera, cameraId)) != OK) {
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
46154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
465be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
46854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
47054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
47154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
473653252be963c07c99109d20f942d1f30c52a9360James Dong
47454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
47554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
47654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
47754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
47854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
47954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
48054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
48154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
48254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
48354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
48454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // This CHECK is good, since we just passed the lock/unlock
48554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // check earlier by calling mCamera->setParameters().
48654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
4872b37ced30f89437c804c3945b901019b86d210aeJames Dong
4885c9523154d106b555db6c41f85ab205a4f189b02James Dong    mIsMetaDataStoredInVideoBuffers = false;
4895c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (storeMetaDataInVideoBuffers &&
4905c9523154d106b555db6c41f85ab205a4f189b02James Dong        OK == mCamera->storeMetaDataInBuffers(true)) {
4915c9523154d106b555db6c41f85ab205a4f189b02James Dong        mIsMetaDataStoredInVideoBuffers = true;
4925c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
4935c9523154d106b555db6c41f85ab205a4f189b02James Dong
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
49654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
497f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
498f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
499f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
500f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
501ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
502ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
503653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
50454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
510393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
51154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
51620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
51720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
51920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::startCameraRecording() {
52165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    CHECK_EQ(OK, mCamera->startRecording());
5222b37ced30f89437c804c3945b901019b86d210aeJames Dong    CHECK(mCamera->recordingEnabled());
52365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
52465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
525f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
5260c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
52754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
52854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        LOGE("CameraSource is not initialized yet");
52954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
53054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
532365a963142093a1cd8efdcea76b5f65096a5b115James Dong    char value[PROPERTY_VALUE_MAX];
533365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (property_get("media.stagefright.record-stats", value, NULL)
534365a963142093a1cd8efdcea76b5f65096a5b115James Dong        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
535365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
536365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
5379d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
538f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
539f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t startTimeUs;
540f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
541f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs = startTimeUs;
542f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
543f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
544c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    // Call setListener first before calling startCameraRecording()
545c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    // to avoid recording frames being dropped.
5469d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
547be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    mCamera->setListener(new CameraSourceListener(this));
548c42478ed7b8a379d2f8a43d4d349680c8a37573fJames Dong    startCameraRecording();
5499d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
55020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
55420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
55565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
55678eff720c86eb6d4e3d45a144df60b2ca464d2d4Nipun Kwatra    mCamera->setListener(NULL);
55765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    mCamera->stopRecording();
55865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
55965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
560ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
561ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    LOGV("releaseCamera");
562ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
563ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        LOGV("Camera was cold when we started, stopping preview");
564ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong        mCamera->stopPreview();
565ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
566ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCamera->unlock();
567ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCamera.clear();
568ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCamera = 0;
569ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    mCameraFlags = 0;
570ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
571ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::stop() {
573c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("stop");
574c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    Mutex::Autolock autoLock(mLock);
57520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
576c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    mFrameAvailableCondition.signal();
577365a963142093a1cd8efdcea76b5f65096a5b115James Dong
5789d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
579c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    releaseQueuedFrames();
5807278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesBeingEncoded.empty()) {
581365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Waiting for outstanding frames being encoded: %d",
582365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mFramesBeingEncoded.size());
5837278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFrameCompleteCondition.wait(mLock);
5847278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
585d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    stopCameraRecording();
586ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    releaseCamera();
5879d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
5887278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
589365a963142093a1cd8efdcea76b5f65096a5b115James Dong    if (mCollectStats) {
590365a963142093a1cd8efdcea76b5f65096a5b115James Dong        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
591365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
592365a963142093a1cd8efdcea76b5f65096a5b115James Dong                mLastFrameTimestampUs - mFirstFrameTimeUs);
593365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
59413aec890216948b0c364f8f92792129d0335f506James Dong
595ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    if (mNumGlitches > 0) {
596ba29002c7aee13c068049037cd14bba6a244da6bJames Dong        LOGW("%d long delays between neighboring video frames during",
597ba29002c7aee13c068049037cd14bba6a244da6bJames Dong                mNumGlitches);
598ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
599ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
60013aec890216948b0c364f8f92792129d0335f506James Dong    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
60465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
605d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    if (mCamera != NULL) {
606d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong        mCamera->releaseRecordingFrame(frame);
607d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
60865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
60965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
610c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
611c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
6127278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
6137278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
61465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
6157278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
61613aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
617c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
618c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
619c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
621653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
624f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
625f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
62665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
627f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
628f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
629f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
6307278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
6317278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    LOGV("signalBufferReturned: %p", buffer->data());
63256223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
6337278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
6347278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
6357278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
636f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
6377278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
6387278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
6397278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
6407278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
6417278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
6427278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
6437278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
6447278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
6457278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
6467278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
6477278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
64920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
650c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("read");
65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
655abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
656abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
65920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
661be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
665542db5d438988360d491a5add1040a2df9aa90c9James Dong        while (mStarted) {
666542db5d438988360d491a5add1040a2df9aa90c9James Dong            while(mFramesReceived.empty()) {
667542db5d438988360d491a5add1040a2df9aa90c9James Dong                mFrameAvailableCondition.wait(mLock);
668542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
669542db5d438988360d491a5add1040a2df9aa90c9James Dong
670542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (!mStarted) {
671542db5d438988360d491a5add1040a2df9aa90c9James Dong                return OK;
672542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
673542db5d438988360d491a5add1040a2df9aa90c9James Dong
674542db5d438988360d491a5add1040a2df9aa90c9James Dong            frame = *mFramesReceived.begin();
675542db5d438988360d491a5add1040a2df9aa90c9James Dong            mFramesReceived.erase(mFramesReceived.begin());
676542db5d438988360d491a5add1040a2df9aa90c9James Dong
677542db5d438988360d491a5add1040a2df9aa90c9James Dong            frameTime = *mFrameTimes.begin();
678542db5d438988360d491a5add1040a2df9aa90c9James Dong            mFrameTimes.erase(mFrameTimes.begin());
679542db5d438988360d491a5add1040a2df9aa90c9James Dong            int64_t skipTimeUs;
680542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (!options || !options->getSkipFrame(&skipTimeUs)) {
681542db5d438988360d491a5add1040a2df9aa90c9James Dong                skipTimeUs = frameTime;
682542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
683542db5d438988360d491a5add1040a2df9aa90c9James Dong            if (skipTimeUs > frameTime) {
684542db5d438988360d491a5add1040a2df9aa90c9James Dong                LOGV("skipTimeUs: %lld us > frameTime: %lld us",
685542db5d438988360d491a5add1040a2df9aa90c9James Dong                    skipTimeUs, frameTime);
686542db5d438988360d491a5add1040a2df9aa90c9James Dong                releaseOneRecordingFrame(frame);
687542db5d438988360d491a5add1040a2df9aa90c9James Dong                ++mNumFramesDropped;
688542db5d438988360d491a5add1040a2df9aa90c9James Dong                // Safeguard against the abuse of the kSkipFrame_Option.
689542db5d438988360d491a5add1040a2df9aa90c9James Dong                if (skipTimeUs - frameTime >= 1E6) {
690542db5d438988360d491a5add1040a2df9aa90c9James Dong                    LOGE("Frame skipping requested is way too long: %lld us",
691542db5d438988360d491a5add1040a2df9aa90c9James Dong                        skipTimeUs - frameTime);
692542db5d438988360d491a5add1040a2df9aa90c9James Dong                    return UNKNOWN_ERROR;
693542db5d438988360d491a5add1040a2df9aa90c9James Dong                }
694542db5d438988360d491a5add1040a2df9aa90c9James Dong            } else {
695542db5d438988360d491a5add1040a2df9aa90c9James Dong                mFramesBeingEncoded.push_back(frame);
696542db5d438988360d491a5add1040a2df9aa90c9James Dong                *buffer = new MediaBuffer(frame->pointer(), frame->size());
697542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->setObserver(this);
698542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->add_ref();
699542db5d438988360d491a5add1040a2df9aa90c9James Dong                (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
70056223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber
701542db5d438988360d491a5add1040a2df9aa90c9James Dong                return OK;
702542db5d438988360d491a5add1040a2df9aa90c9James Dong            }
70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
7047278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
708c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
709c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        int32_t msgType, const sp<IMemory> &data) {
710c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
712c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (!mStarted) {
713f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        releaseOneRecordingFrame(data);
71413aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesReceived;
71513aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
716c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        return;
717c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
719f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (mNumFramesReceived > 0 &&
720f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
721f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mNumGlitches % 10 == 0) {  // Don't spam the log
722ba29002c7aee13c068049037cd14bba6a244da6bJames Dong            LOGV("Long delay detected in video recording");
723f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
724f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        ++mNumGlitches;
725f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
726f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
72765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
72865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
72965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if(skipCurrentFrame(timestampUs)) {
73065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseOneRecordingFrame(data);
73165e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        return;
732fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
733fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
734365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
73513aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
736c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
737f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
738f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
739f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
740f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
741f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
742f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                releaseOneRecordingFrame(data);
743f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                return;
744f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
745f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
746f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
747be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
74813aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
749be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
7507278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
751f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
752f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
753f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    LOGV("initial delay: %lld, current time stamp: %lld",
754f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
75720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
7585c9523154d106b555db6c41f85ab205a4f189b02James Dongsize_t CameraSource::getNumberOfVideoBuffers() const {
7595c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("getNumberOfVideoBuffers");
7605c9523154d106b555db6c41f85ab205a4f189b02James Dong    size_t nBuffers = 0;
7615c9523154d106b555db6c41f85ab205a4f189b02James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
7625c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (mInitCheck == OK && mCamera != 0) {
7635c9523154d106b555db6c41f85ab205a4f189b02James Dong        nBuffers = mCamera->getNumberOfVideoBuffers();
7645c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
7655c9523154d106b555db6c41f85ab205a4f189b02James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
7665c9523154d106b555db6c41f85ab205a4f189b02James Dong    return nBuffers;
7675c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7685c9523154d106b555db6c41f85ab205a4f189b02James Dong
7695c9523154d106b555db6c41f85ab205a4f189b02James Dongsp<IMemory> CameraSource::getVideoBuffer(size_t index) const {
7705c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("getVideoBuffer: %d", index);
7715c9523154d106b555db6c41f85ab205a4f189b02James Dong    sp<IMemory> buffer = 0;
7725c9523154d106b555db6c41f85ab205a4f189b02James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
7735c9523154d106b555db6c41f85ab205a4f189b02James Dong    if (mInitCheck == OK && mCamera != 0) {
7745c9523154d106b555db6c41f85ab205a4f189b02James Dong        buffer = mCamera->getVideoBuffer(index);
7755c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
7765c9523154d106b555db6c41f85ab205a4f189b02James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
7775c9523154d106b555db6c41f85ab205a4f189b02James Dong    return buffer;
7785c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7795c9523154d106b555db6c41f85ab205a4f189b02James Dong
7805c9523154d106b555db6c41f85ab205a4f189b02James Dongbool CameraSource::isMetaDataStoredInVideoBuffers() const {
7815c9523154d106b555db6c41f85ab205a4f189b02James Dong    LOGV("isMetaDataStoredInVideoBuffers");
7825c9523154d106b555db6c41f85ab205a4f189b02James Dong    return mIsMetaDataStoredInVideoBuffers;
7835c9523154d106b555db6c41f85ab205a4f189b02James Dong}
7845c9523154d106b555db6c41f85ab205a4f189b02James Dong
78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
786