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
17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
19c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong//#define LOG_NDEBUG 0
20c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#define LOG_TAG "CameraSource"
21c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <utils/Log.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <OMX_Component.h>
249d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong#include <binder/IPCThreadState.h>
258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <binder/MemoryBase.h>
268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <binder/MemoryHeapBase.h>
278cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen#include <media/hardware/HardwareAPI.h>
28f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h>
30be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <media/stagefright/MediaDefs.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaErrors.h>
3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
333cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/Camera.h>
343cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/CameraParameters.h>
35df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <gui/Surface.h>
36be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber#include <utils/String8.h>
37365a963142093a1cd8efdcea76b5f65096a5b115James Dong#include <cutils/properties.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#if LOG_NDEBUG
4084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
4184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#else
4284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#define UNUSED_UNLESS_VERBOSE(x)
4384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber#endif
4484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
47e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dongstatic const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
48e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong
49be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberstruct CameraSourceListener : public CameraListener {
50090ef604f81447eab4aa0a5b45d6307482573560Chih-Hung Hsieh    explicit CameraSourceListener(const sp<CameraSource> &source);
51be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
52be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
5357c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
5457c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Li                          camera_frame_metadata_t *metadata);
55be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
56be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual void postDataTimestamp(
57be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
58be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
592d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle);
602d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
61b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    virtual void postRecordingFrameHandleTimestampBatch(
62b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                const std::vector<nsecs_t>& timestamps,
63b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                const std::vector<native_handle_t*>& handles);
64b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
65be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huberprotected:
66be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    virtual ~CameraSourceListener();
67be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
69be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    wp<CameraSource> mSource;
70be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
71be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener(const CameraSourceListener &);
72be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    CameraSourceListener &operator=(const CameraSourceListener &);
7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
76be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    : mSource(source) {
77be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas HuberCameraSourceListener::~CameraSourceListener() {
80be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
8384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(msgType);
8484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext1);
8584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    UNUSED_UNLESS_VERBOSE(ext2);
863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
87be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8957c86189bc07d9ccb0fd044e66df736d0bf19639Wu-cheng Livoid CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
9084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber                                    camera_frame_metadata_t * /* metadata */) {
91a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("postData(%d, ptr:%p, size:%zu)",
92be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber         msgType, dataPtr->pointer(), dataPtr->size());
9365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
9465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    sp<CameraSource> source = mSource.promote();
9565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    if (source.get() != NULL) {
9665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        source->dataCallback(msgType, dataPtr);
9765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    }
98be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
99be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
100be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Hubervoid CameraSourceListener::postDataTimestamp(
101be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
102c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
103c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    sp<CameraSource> source = mSource.promote();
104c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    if (source.get() != NULL) {
105c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
106c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
107be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber}
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1092d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSourceListener::postRecordingFrameHandleTimestamp(nsecs_t timestamp,
1102d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        native_handle_t* handle) {
1112d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    sp<CameraSource> source = mSource.promote();
1122d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    if (source.get() != nullptr) {
1132d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        source->recordingFrameHandleCallbackTimestamp(timestamp/1000, handle);
1142d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    }
1152d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
1162d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
117b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yehvoid CameraSourceListener::postRecordingFrameHandleTimestampBatch(
118b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<nsecs_t>& timestamps,
119b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<native_handle_t*>& handles) {
120b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    sp<CameraSource> source = mSource.promote();
121b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    if (source.get() != nullptr) {
122b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        int n = timestamps.size();
123b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        std::vector<nsecs_t> modifiedTimestamps(n);
124b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        for (int i = 0; i < n; i++) {
125b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            modifiedTimestamps[i] = timestamps[i] / 1000;
126b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        }
127b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        source->recordingFrameHandleCallbackTimestampBatch(modifiedTimestamps, handles);
128b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
129b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh}
130b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
131653252be963c07c99109d20f942d1f30c52a9360James Dongstatic int32_t getColorFormat(const char* colorFormat) {
1322d1bcf2b8f2f23e204adcca45ca134247bdf87f9Praveen Chavan    if (!colorFormat) {
1332d1bcf2b8f2f23e204adcca45ca134247bdf87f9Praveen Chavan        ALOGE("Invalid color format");
1342d1bcf2b8f2f23e204adcca45ca134247bdf87f9Praveen Chavan        return -1;
1352d1bcf2b8f2f23e204adcca45ca134247bdf87f9Praveen Chavan    }
1362d1bcf2b8f2f23e204adcca45ca134247bdf87f9Praveen Chavan
137e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
138e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong       return OMX_COLOR_FormatYUV420Planar;
139e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong    }
140e2d8ba8c36fd39eb98f604b11654aa5466673260James Dong
141653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
142653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_FormatYUV422SemiPlanar;
143653252be963c07c99109d20f942d1f30c52a9360James Dong    }
144653252be963c07c99109d20f942d1f30c52a9360James Dong
145653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
146653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYUV420SemiPlanar;
147653252be963c07c99109d20f942d1f30c52a9360James Dong    }
148653252be963c07c99109d20f942d1f30c52a9360James Dong
149653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
150653252be963c07c99109d20f942d1f30c52a9360James Dong        return OMX_COLOR_FormatYCbYCr;
151653252be963c07c99109d20f942d1f30c52a9360James Dong    }
152653252be963c07c99109d20f942d1f30c52a9360James Dong
153653252be963c07c99109d20f942d1f30c52a9360James Dong    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
154653252be963c07c99109d20f942d1f30c52a9360James Dong       return OMX_COLOR_Format16bitRGB565;
155653252be963c07c99109d20f942d1f30c52a9360James Dong    }
156653252be963c07c99109d20f942d1f30c52a9360James Dong
1571374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
1581374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket       return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
1591374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket    }
1601374eddc4455b26d1dffdca10fc70534b3f08c1dDandawate Saket
161bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE)) {
162bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala        return OMX_COLOR_FormatAndroidOpaque;
163bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala    }
164bf5bea96f236adb5eef78c2f414ef82b3602a0f7Eino-Ville Talvala
16529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    ALOGE("Uknown color format (%s), please add it to "
166a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong         "CameraSource::getColorFormat", colorFormat);
167a1abc1a76741914c7bc43f1df9e32744f023ab75James Dong
168f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"Unknown color format");
169dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn    return -1;
170653252be963c07c99109d20f942d1f30c52a9360James Dong}
171653252be963c07c99109d20f942d1f30c52a9360James Dong
172ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville TalvalaCameraSource *CameraSource::Create(const String16 &clientName) {
17354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size size;
17454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.width = -1;
17554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    size.height = -1;
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
177d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    sp<hardware::ICamera> camera;
17898a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    return new CameraSource(camera, NULL, 0, clientName, Camera::USE_CALLING_UID,
17998a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            Camera::USE_CALLING_PID, size, -1, NULL, false);
18020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18230ab66297501757d745b9ae10da61adcd891f497Andreas Huber// static
18354ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource *CameraSource::CreateFromCamera(
184d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    const sp<hardware::ICamera>& camera,
1854ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
18654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
187ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
188ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
18998a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    pid_t clientPid,
19054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
19154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
19299617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
1935c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers) {
19454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
1954ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    CameraSource *source = new CameraSource(camera, proxy, cameraId,
19698a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            clientName, clientUid, clientPid, videoSize, frameRate, surface,
197ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala            storeMetaDataInVideoBuffers);
19854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return source;
19930ab66297501757d745b9ae10da61adcd891f497Andreas Huber}
20030ab66297501757d745b9ae10da61adcd891f497Andreas Huber
20154ff19ac69ace7c05ea90d225e26dab3b133f487James DongCameraSource::CameraSource(
202d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    const sp<hardware::ICamera>& camera,
2034ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    const sp<ICameraRecordingProxy>& proxy,
20454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t cameraId,
205ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    const String16& clientName,
206ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    uid_t clientUid,
20798a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    pid_t clientPid,
20854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Size videoSize,
20954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRate,
21099617adda9bc46c43f511f0940bc735c73de61deMathias Agopian    const sp<IGraphicBufferProducer>& surface,
2115c9523154d106b555db6c41f85ab205a4f189b02James Dong    bool storeMetaDataInVideoBuffers)
21254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    : mCameraFlags(0),
213983cf231ab2d176a14595cdae46ff1b0c239af47James Dong      mNumInputBuffers(0),
21454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mVideoFrameRate(-1),
21554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mCamera(0),
21654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong      mSurface(surface),
21713aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesReceived(0),
21865e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mLastFrameTimestampUs(0),
21965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mStarted(false),
22013aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesEncoded(0),
221e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong      mTimeBetweenFrameCaptureUs(0),
2227757f5010a771fb8824b6fdf9788f588a1577e3fJames Dong      mFirstFrameTimeUs(0),
223f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang      mStopSystemTimeUs(-1),
22413aec890216948b0c364f8f92792129d0335f506James Dong      mNumFramesDropped(0),
225f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mNumGlitches(0),
226f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong      mGlitchDurationThresholdUs(200000),
22765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra      mCollectStats(false) {
22854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width  = -1;
22954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = -1;
23054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2314ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mInitCheck = init(camera, proxy, cameraId,
23298a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen                    clientName, clientUid, clientPid,
2335c9523154d106b555db6c41f85ab205a4f189b02James Dong                    videoSize, frameRate,
2345c9523154d106b555db6c41f85ab205a4f189b02James Dong                    storeMetaDataInVideoBuffers);
23595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    if (mInitCheck != OK) releaseCamera();
23654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
23754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
23854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::initCheck() const {
23954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return mInitCheck;
24054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
24154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
24254ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraAvailable(
243d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
24498a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid) {
24554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
24654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (camera == 0) {
24798a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid);
2484ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
24954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags &= ~FLAGS_HOT_CAMERA;
25054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {
2514ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // We get the proxy from Camera, not ICamera. We need to get the proxy
2524ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // to the remote Camera owned by the application. Here mCamera is a
2534ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // local Camera object created by us. We cannot use the proxy from
2544ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        // mCamera here.
25554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCamera = Camera::create(camera);
2564ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        if (mCamera == 0) return -EBUSY;
2574ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        mCameraRecordingProxy = proxy;
25854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        mCameraFlags |= FLAGS_HOT_CAMERA;
2593bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mDeathNotifier = new DeathNotifier();
2603bd3020c00ec8264ac1fe3870800f326487f9221James Dong        // isBinderAlive needs linkToDeath to work.
26106b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen        IInterface::asBinder(mCameraRecordingProxy)->linkToDeath(mDeathNotifier);
26254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
26354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2644ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mCamera->lock();
2654ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
26654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
26754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
26854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
26954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
27054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
27154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check to see whether the requested video width and height is one
27254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * of the supported sizes.
27354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the video frame width in pixels
27454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the video frame height in pixels
27554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param suppportedSizes the vector of sizes that we check against
27654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return true if the dimension (width and height) is supported.
27754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
27854ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic bool isVideoSizeSupported(
27954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t width, int32_t height,
28054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const Vector<Size>& supportedSizes) {
28154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
2823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("isVideoSizeSupported");
28354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    for (size_t i = 0; i < supportedSizes.size(); ++i) {
28454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (width  == supportedSizes[i].width &&
28554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            height == supportedSizes[i].height) {
28654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return true;
28754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
28854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
28954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return false;
29054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
29154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
29254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
29354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the preview and video output is separate, we only set the
29454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * the video size, and applications should set the preview size
29554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * to some proper value, and the recording framework will not
29654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * change the preview size; otherwise, if the video and preview
29754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * output is the same, we need to set the preview to be the same
29854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * as the requested video size.
29954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
30054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
30154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
30254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Query the camera to retrieve the supported video frame sizes
30354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * and also to see whether CameraParameters::setVideoSize()
30454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is supported or not.
30554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
30654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @@param isSetVideoSizeSupported retunrs whether method
30754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      CameraParameters::setVideoSize() is supported or not.
30854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param sizes returns the vector of Size objects for the
30954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      supported video frame sizes advertised by the camera.
31054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
31154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatic void getSupportedVideoSizes(
31254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    const CameraParameters& params,
31354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool *isSetVideoSizeSupported,
31454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size>& sizes) {
31554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
31654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    *isSetVideoSizeSupported = true;
31754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    params.getSupportedVideoSizes(sizes);
31854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (sizes.size() == 0) {
319b8a805261bf0282e992d3608035e47d05a898710Steve Block        ALOGD("Camera does not support setVideoSize()");
32054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params.getSupportedPreviewSizes(sizes);
32154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        *isSetVideoSizeSupported = false;
32254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
32354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
32454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
32554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
32654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the camera has the supported color format
32754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
32854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
32954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
33054ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::isCameraColorFormatSupported(
33154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params) {
33254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mColorFormat = getColorFormat(params.get(
33354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            CameraParameters::KEY_VIDEO_FRAME_FORMAT));
33454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mColorFormat == -1) {
33554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
33654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
33754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
33854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
33954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
34054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
34154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Configure the camera to use the requested video size
34254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * (width and height) and/or frame rate. If both width and
34354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * height are -1, configuration on the video size is skipped.
34454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * if frameRate is -1, configuration on the frame rate
34554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is skipped. Skipping the configuration allows one to
34654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * use the current camera setting without the need to
34754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * actually know the specific values (see Create() method).
34854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
34954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params the CameraParameters to be configured
35054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param width the target video frame width in pixels
35154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param height the target video frame height in pixels
35254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
35354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
35454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
35554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::configureCamera(
35654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        CameraParameters* params,
35754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height,
35854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
3593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("configureCamera");
36054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    Vector<Size> sizes;
36154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isSetVideoSizeSupportedByCamera = true;
36254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
36354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    bool isCameraParamChanged = false;
36454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
36554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (!isVideoSizeSupported(width, height, sizes)) {
36629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Video dimension (%dx%d) is unsupported", width, height);
36754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return BAD_VALUE;
36854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
36954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (isSetVideoSizeSupportedByCamera) {
37054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setVideoSize(width, height);
37154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        } else {
37254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            params->setPreviewSize(width, height);
37354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
37454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
37554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else if ((width == -1 && height != -1) ||
37654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong               (width != -1 && height == -1)) {
37754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // If one and only one of the width and height is -1
37854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // we reject such a request.
37929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Requested video size (%dx%d) is not supported", width, height);
38054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return BAD_VALUE;
38154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // width == -1 && height == -1
38254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
38354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current width and height value setting from the camera.
38454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
38554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
38654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1) {
387635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(frameRate > 0 && frameRate <= 120);
388635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        const char* supportedFrameRates =
389635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
390635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        CHECK(supportedFrameRates != NULL);
3913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Supported frame rates: %s", supportedFrameRates);
392635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        char buf[4];
393635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        snprintf(buf, 4, "%d", frameRate);
394635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        if (strstr(supportedFrameRates, buf) == NULL) {
39529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Requested frame rate (%d) is not supported: %s",
396635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong                frameRate, supportedFrameRates);
397635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong            return BAD_VALUE;
398635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        }
399635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong
400635730831e08c32a5fe7c59125e0919b7e7899cdJames Dong        // The frame rate is supported, set the camera to the requested value.
40154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        params->setPreviewFrameRate(frameRate);
40254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        isCameraParamChanged = true;
40354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    } else {  // frameRate == -1
40454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Do not configure the camera.
40554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Use the current frame rate value setting from the camera
40654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
40754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
40854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (isCameraParamChanged) {
40954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        // Either frame rate or frame size needs to be changed.
41054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        String8 s = params->flatten();
41154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (OK != mCamera->setParameters(s)) {
41229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Could not change settings."
41354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                 " Someone else is using camera %p?", mCamera.get());
41454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return -EBUSY;
41554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
41654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
41754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
41854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
41954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
42054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
42154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check whether the requested video frame size
42254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * has been successfully configured or not. If both width and height
42354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * are -1, check on the current width and height value setting
42454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * is performed.
42554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
42654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
42754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame width in pixels to check against
42854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame height in pixels to check against
42954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error
43054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
43154ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkVideoSize(
43254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
43354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t width, int32_t height) {
43454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkVideoSize");
436f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // The actual video size is the same as the preview size
437f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // if the camera hal does not support separate video and
438f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // preview output. In this case, we retrieve the video
439f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    // size from preview.
44054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameWidthActual = -1;
44154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameHeightActual = -1;
442f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    Vector<Size> sizes;
443f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    params.getSupportedVideoSizes(sizes);
444f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    if (sizes.size() == 0) {
445f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size is the same as preview size
446f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getPreviewSize(&frameWidthActual, &frameHeightActual);
447f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    } else {
448f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        // video size may not be the same as preview
449f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong        params.getVideoSize(&frameWidthActual, &frameHeightActual);
450f96c9d193c70c7216b34e6c65f046a09a2a81f14James Dong    }
45154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameWidthActual < 0 || frameHeightActual < 0) {
45229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve video frame size (%dx%d)",
45354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                frameWidthActual, frameHeightActual);
45454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
45554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
45654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
45754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame size against the target/requested
45854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame size.
45954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (width != -1 && height != -1) {
46054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        if (frameWidthActual != width || frameHeightActual != height) {
46129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Failed to set video frame size to %dx%d. "
46254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    "The actual video size is %dx%d ", width, height,
46354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameWidthActual, frameHeightActual);
46454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong            return UNKNOWN_ERROR;
46554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        }
46654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
46754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
46854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
46954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.width = frameWidthActual;
47054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoSize.height = frameHeightActual;
47154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
47254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
47354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
47454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
47554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Check the requested frame rate has been successfully configured or not.
47654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * If the target frameRate is -1, check on the current frame rate value
47754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * setting is performed.
47854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *
47954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param params CameraParameters to retrieve the information
48054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param the target video frame rate to check against
48154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
48254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
48354ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::checkFrameRate(
48454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        const CameraParameters& params,
48554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t frameRate) {
48654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
4873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("checkFrameRate");
48854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int32_t frameRateActual = params.getPreviewFrameRate();
48954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRateActual < 0) {
49029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
49154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
49254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
49354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
49454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check the actual video frame rate against the target/requested
49554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // video frame rate.
49654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
49729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to set preview frame rate to %d fps. The actual "
49854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                "frame rate is %d", frameRate, frameRateActual);
49954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return UNKNOWN_ERROR;
50054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
50154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
50254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Good now.
50354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mVideoFrameRate = frameRateActual;
50454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
50554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong}
50654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
50754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong/*
50854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * Initialize the CameraSource to so that it becomes
50954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * ready for providing the video input streams as requested.
51054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param camera the camera object used for the video source
51154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param cameraId if camera == 0, use camera with this id
51254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      as the video source
51354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param videoSize the target video frame size. If both
51454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and height in videoSize is -1, use the current
51554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      width and heigth settings by the camera
51654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @param frameRate the target frame rate in frames per second.
51754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong *      if it is -1, use the current camera frame rate setting.
5185c9523154d106b555db6c41f85ab205a4f189b02James Dong * @param storeMetaDataInVideoBuffers request to store meta
5195c9523154d106b555db6c41f85ab205a4f189b02James Dong *      data or real YUV data in video buffers. Request to
5205c9523154d106b555db6c41f85ab205a4f189b02James Dong *      store meta data in video buffers may not be honored
5215c9523154d106b555db6c41f85ab205a4f189b02James Dong *      if the source does not support this feature.
5225c9523154d106b555db6c41f85ab205a4f189b02James Dong *
52354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong * @return OK if no error.
52454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong */
52554ff19ac69ace7c05ea90d225e26dab3b133f487James Dongstatus_t CameraSource::init(
526d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        const sp<hardware::ICamera>& camera,
5274ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        const sp<ICameraRecordingProxy>& proxy,
52854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        int32_t cameraId,
529ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
530ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
53198a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
53254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        Size videoSize,
5335c9523154d106b555db6c41f85ab205a4f189b02James Dong        int32_t frameRate,
5345c9523154d106b555db6c41f85ab205a4f189b02James Dong        bool storeMetaDataInVideoBuffers) {
53554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
5363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("init");
53754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    status_t err = OK;
538ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    int64_t token = IPCThreadState::self()->clearCallingIdentity();
53998a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen    err = initWithCameraAccess(camera, proxy, cameraId, clientName, clientUid, clientPid,
540ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               videoSize, frameRate,
541ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong                               storeMetaDataInVideoBuffers);
542ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    IPCThreadState::self()->restoreCallingIdentity(token);
543ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    return err;
544ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong}
545ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong
5462d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSource::createVideoBufferMemoryHeap(size_t size, uint32_t bufferCount) {
5472d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mMemoryHeapBase = new MemoryHeapBase(size * bufferCount, 0,
5482d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            "StageFright-CameraSource-BufferHeap");
5492d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    for (uint32_t i = 0; i < bufferCount; i++) {
5502d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        mMemoryBases.push_back(new MemoryBase(mMemoryHeapBase, i * size, size));
5512d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    }
5522d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
5532d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
5548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenstatus_t CameraSource::initBufferQueue(uint32_t width, uint32_t height,
5558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        uint32_t format, android_dataspace dataSpace, uint32_t bufferCount) {
5568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("initBufferQueue");
5578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mVideoBufferConsumer != nullptr || mVideoBufferProducer != nullptr) {
5598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Buffer queue already exists", __FUNCTION__);
5608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return ALREADY_EXISTS;
5618cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5628cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5638cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Create a buffer queue.
5648cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IGraphicBufferProducer> producer;
5658cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IGraphicBufferConsumer> consumer;
5668cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    BufferQueue::createBufferQueue(&producer, &consumer);
5678cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5688cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
5698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
5708cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        usage = GRALLOC_USAGE_HW_VIDEO_ENCODER;
5718cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5728cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5738cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    bufferCount += kConsumerBufferCount;
5748cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5758cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer = new BufferItemConsumer(consumer, usage, bufferCount);
5768cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer->setName(String8::format("StageFright-CameraSource"));
5778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferProducer = producer;
5788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5798cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    status_t res = mVideoBufferConsumer->setDefaultBufferSize(width, height);
5808cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5818cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set buffer dimensions %dx%d: %s (%d)", __FUNCTION__, width, height,
5828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5838cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5848cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5858cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5868cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mVideoBufferConsumer->setDefaultBufferFormat(format);
5878cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5888cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set buffer format %d: %s (%d)", __FUNCTION__, format,
5898cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5908cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5918cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5928cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
5938cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mVideoBufferConsumer->setDefaultBufferDataSpace(dataSpace);
5948cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
5958cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not set data space %d: %s (%d)", __FUNCTION__, dataSpace,
5968cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
5978cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
5988cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
5998cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6008cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mCamera->setVideoTarget(mVideoBufferProducer);
6018cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
6028cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Failed to set video target: %s (%d)", __FUNCTION__, strerror(-res), res);
6038cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
6048cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
6058cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6068cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Create memory heap to store buffers as VideoNativeMetadata.
6072d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    createVideoBufferMemoryHeap(sizeof(VideoNativeMetadata), bufferCount);
6088cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6098cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mBufferQueueListener = new BufferQueueListener(mVideoBufferConsumer, this);
6108cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    res = mBufferQueueListener->run("CameraSource-BufferQueueListener");
6118cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (res != OK) {
6128cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ALOGE("%s: Could not run buffer queue listener thread: %s (%d)", __FUNCTION__,
6138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                strerror(-res), res);
6148cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return res;
6158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
6168cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
6178cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return OK;
6188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
6198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
620ae4c1ac6401185539c03ce0819e174fd1b04b136James Dongstatus_t CameraSource::initWithCameraAccess(
621d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        const sp<hardware::ICamera>& camera,
622ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        const sp<ICameraRecordingProxy>& proxy,
623ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t cameraId,
624ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        const String16& clientName,
625ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala        uid_t clientUid,
62698a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen        pid_t clientPid,
627ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        Size videoSize,
628ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int32_t frameRate,
629ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        bool storeMetaDataInVideoBuffers) {
6303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("initWithCameraAccess");
631ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    status_t err = OK;
6329d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
633ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala    if ((err = isCameraAvailable(camera, proxy, cameraId,
63498a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen            clientName, clientUid, clientPid)) != OK) {
63529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Camera connection could not be established.");
63654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
63754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
63854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters params(mCamera->getParameters());
63954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = isCameraColorFormatSupported(params)) != OK) {
64054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
64154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
642be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
64354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Set the camera to use the requested video frame size
64454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // and/or frame rate.
64554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = configureCamera(&params,
64654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    videoSize.width, videoSize.height,
64754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                    frameRate))) {
64854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
64954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
650653252be963c07c99109d20f942d1f30c52a9360James Dong
65154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    // Check on video frame size and frame rate.
65254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    CameraParameters newCameraParams(mCamera->getParameters());
65354ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkVideoSize(newCameraParams,
65454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong                videoSize.width, videoSize.height)) != OK) {
65554ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
65654ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
65754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
65854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return err;
65954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
66054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong
6618e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // Set the preview display. Skip this if mSurface is null because
6628e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    // applications may already set a surface to the camera.
6638e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    if (mSurface != NULL) {
6648e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // This CHECK is good, since we just passed the lock/unlock
6658e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li        // check earlier by calling mCamera->setParameters().
6664b820b0e1fa069714b123fc35784541d0f94d267Eino-Ville Talvala        CHECK_EQ((status_t)OK, mCamera->setPreviewTarget(mSurface));
6678e0792bb55a604ffcd4aa90fdb4419d8b3c6ad24Wu-cheng Li    }
6682b37ced30f89437c804c3945b901019b86d210aeJames Dong
6698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // By default, store real data in video buffers.
670d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    mVideoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV;
671abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong    if (storeMetaDataInVideoBuffers) {
672d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        if (OK == mCamera->setVideoBufferMode(hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE)) {
673d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala            mVideoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE;
6748cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        } else if (OK == mCamera->setVideoBufferMode(
675d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala                hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA)) {
676d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala            mVideoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA;
6778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
6788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
6798cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
680d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    if (mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV) {
681d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala        err = mCamera->setVideoBufferMode(hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV);
6828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (err != OK) {
6838cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Setting video buffer mode to VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV failed: "
6848cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    "%s (err=%d)", __FUNCTION__, strerror(-err), err);
6858cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return err;
686abdd2ba259a5dc863a821c9d1187d83f2e2395acJames Dong        }
6875c9523154d106b555db6c41f85ab205a4f189b02James Dong    }
6885c9523154d106b555db6c41f85ab205a4f189b02James Dong
68954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
690f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    if (glitchDurationUs > mGlitchDurationThresholdUs) {
691f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mGlitchDurationThresholdUs = glitchDurationUs;
692f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
693f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
694ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // XXX: query camera for the stride and slice height
695ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong    // when the capability becomes available.
696653252be963c07c99109d20f942d1f30c52a9360James Dong    mMeta = new MetaData;
69754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setCString(kKeyMIMEType,  MEDIA_MIMETYPE_VIDEO_RAW);
69854ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyColorFormat, mColorFormat);
69954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyWidth,       mVideoSize.width);
70054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyHeight,      mVideoSize.height);
70154ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeyStride,      mVideoSize.width);
70254ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
703393410a441b6d06daf286ed496470e9d6b2b6ca8James Dong    mMeta->setInt32(kKeyFrameRate,   mVideoFrameRate);
70454ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    return OK;
70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
70620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
70720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberCameraSource::~CameraSource() {
70820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
709b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong        reset();
710ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong    } else if (mInitCheck == OK) {
711ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera is initialized but because start() is never called,
712ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // the lock on Camera is never released(). This makes sure
713ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        // Camera's lock is released in this case.
714ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        releaseCamera();
71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
71826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunkstatus_t CameraSource::startCameraRecording() {
7193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("startCameraRecording");
7204ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // Reset the identity to the current thread because media server owns the
7214ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // camera and recording is started by the applications. The applications
7224ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    // will connect to the camera in ICameraRecordingProxy::startRecording.
7234ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    int64_t token = IPCThreadState::self()->clearCallingIdentity();
72426cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
7258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
726d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    if (mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE) {
7278cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Initialize buffer queue.
7288cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        err = initBufferQueue(mVideoSize.width, mVideoSize.height, mEncoderFormat,
7298cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                (android_dataspace_t)mEncoderDataSpace,
7308cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                mNumInputBuffers > 0 ? mNumInputBuffers : 1);
7318cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (err != OK) {
7328cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Failed to initialize buffer queue: %s (err=%d)", __FUNCTION__,
7338cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    strerror(-err), err);
7348cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return err;
7358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
7368cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    } else {
7378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (mNumInputBuffers > 0) {
7388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            err = mCamera->sendCommand(
7398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0);
7408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
7418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            // This could happen for CameraHAL1 clients; thus the failure is
7428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            // not a fatal error
7438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            if (err != OK) {
7448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                ALOGW("Failed to set video buffer count to %d due to %d",
7458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    mNumInputBuffers, err);
7468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            }
7478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
7488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
74926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        err = mCamera->sendCommand(
7508cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            CAMERA_CMD_SET_VIDEO_FORMAT, mEncoderFormat, mEncoderDataSpace);
751983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
752983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // This could happen for CameraHAL1 clients; thus the failure is
753983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        // not a fatal error
754983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (err != OK) {
7558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGW("Failed to set video encoder format/dataspace to %d, %d due to %d",
7568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    mEncoderFormat, mEncoderDataSpace, err);
757983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
7582d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
7592d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        // Create memory heap to store buffers as VideoNativeMetadata.
7602d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        createVideoBufferMemoryHeap(sizeof(VideoNativeHandleMetadata), kDefaultVideoBufferCount);
761983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    }
762983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
76326cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    err = OK;
7643bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
7653bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->unlock();
7663bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera.clear();
76726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if ((err = mCameraRecordingProxy->startRecording(
76826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                new ProxyListener(this))) != OK) {
76926cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording, received error: %s (%d)",
77026cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk                    strerror(-err), err);
77126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
7723bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
7733bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->setListener(new CameraSourceListener(this));
7743bd3020c00ec8264ac1fe3870800f326487f9221James Dong        mCamera->startRecording();
77526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        if (!mCamera->recordingEnabled()) {
77626cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            err = -EINVAL;
77726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk            ALOGE("Failed to start recording");
77826cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        }
7793bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
7804ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    IPCThreadState::self()->restoreCallingIdentity(token);
78126cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
78265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
78365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
784f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongstatus_t CameraSource::start(MetaData *meta) {
7853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("start");
7860c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    CHECK(!mStarted);
78754ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    if (mInitCheck != OK) {
78829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("CameraSource is not initialized yet");
78954ff19ac69ace7c05ea90d225e26dab3b133f487James Dong        return mInitCheck;
79054ff19ac69ace7c05ea90d225e26dab3b133f487James Dong    }
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79296626b7f9a4e5c9e1e04f7f710383631d1470364Marco Nelissen    if (property_get_bool("media.stagefright.record-stats", false)) {
793365a963142093a1cd8efdcea76b5f65096a5b115James Dong        mCollectStats = true;
794365a963142093a1cd8efdcea76b5f65096a5b115James Dong    }
7959d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong
796f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mStartTimeUs = 0;
797983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    mNumInputBuffers = 0;
798d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala    mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
7992cbf6cea23539bfe99e36d1d221de62255452e86Eino-Ville Talvala    mEncoderDataSpace = HAL_DATASPACE_V0_BT709;
800d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala
801983cf231ab2d176a14595cdae46ff1b0c239af47James Dong    if (meta) {
802983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int64_t startTimeUs;
803983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt64(kKeyTime, &startTimeUs)) {
804983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mStartTimeUs = startTimeUs;
805983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
806983cf231ab2d176a14595cdae46ff1b0c239af47James Dong
807983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        int32_t nBuffers;
808983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        if (meta->findInt32(kKeyNumBuffers, &nBuffers)) {
809983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            CHECK_GT(nBuffers, 0);
810983cf231ab2d176a14595cdae46ff1b0c239af47James Dong            mNumInputBuffers = nBuffers;
811983cf231ab2d176a14595cdae46ff1b0c239af47James Dong        }
812d46a6b9fd8b2a4f9098757384711e2cd03a91651Eino-Ville Talvala
813c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        // apply encoder color format if specified
814c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) {
815b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            ALOGI("Using encoder format: %#x", mEncoderFormat);
816c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
817c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
818b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            ALOGI("Using encoder data space: %#x", mEncoderDataSpace);
819c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
820f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    }
821f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
82226cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    status_t err;
82326cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    if ((err = startCameraRecording()) == OK) {
82426cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk        mStarted = true;
82526cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    }
82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
82726cee964ab4e0a2bd6ae9ad199ba78ea9634421cRuben Brunk    return err;
82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
83065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::stopCameraRecording() {
8313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stopCameraRecording");
8323bd3020c00ec8264ac1fe3870800f326487f9221James Dong    if (mCameraFlags & FLAGS_HOT_CAMERA) {
8332da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        if (mCameraRecordingProxy != 0) {
8342da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCameraRecordingProxy->stopRecording();
8352da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        }
8363bd3020c00ec8264ac1fe3870800f326487f9221James Dong    } else {
8372da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        if (mCamera != 0) {
8382da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCamera->setListener(NULL);
8392da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim            mCamera->stopRecording();
8402da037b416ad30b7d9a7447d17435026ddc77727Wonsik Kim        }
8413bd3020c00ec8264ac1fe3870800f326487f9221James Dong    }
84265e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
84365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
844ea7b485595f8cec6a66668b5c54c8f297d843f77James Dongvoid CameraSource::releaseCamera() {
8453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseCamera");
846121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    sp<Camera> camera;
847121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    bool coldCamera = false;
848121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
849121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
850121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        // get a local ref and clear ref to mCamera now
851121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera = mCamera;
852121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCamera.clear();
853121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        coldCamera = (mCameraFlags & FLAGS_HOT_CAMERA) == 0;
854121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    }
855121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
856121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    if (camera != 0) {
857ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        int64_t token = IPCThreadState::self()->clearCallingIdentity();
858121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (coldCamera) {
8593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("Camera was cold when we started, stopping preview");
860121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->stopPreview();
861121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            camera->disconnect();
86295068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li        }
863121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        camera->unlock();
864ae4c1ac6401185539c03ce0819e174fd1b04b136James Dong        IPCThreadState::self()->restoreCallingIdentity(token);
86595068be1426dc0a4dc856cf9e35550c31b901711Wu-cheng Li    }
866121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
867121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
868121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
869121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCameraRecordingProxy != 0) {
87006b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen            IInterface::asBinder(mCameraRecordingProxy)->unlinkToDeath(mDeathNotifier);
871121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            mCameraRecordingProxy.clear();
872121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
873121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mCameraFlags = 0;
874ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong    }
875ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong}
876ea7b485595f8cec6a66668b5c54c8f297d843f77James Dong
877b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dongstatus_t CameraSource::reset() {
878b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: E");
879121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
880121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    {
881121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        Mutex::Autolock autoLock(mLock);
882121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mStarted = false;
883f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        mStopSystemTimeUs = -1;
884121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        mFrameAvailableCondition.signal();
885121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
886121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        int64_t token;
887121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        bool isTokenValid = false;
888121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCamera != 0) {
889121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            token = IPCThreadState::self()->clearCallingIdentity();
890121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            isTokenValid = true;
891121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
892121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        releaseQueuedFrames();
893121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        while (!mFramesBeingEncoded.empty()) {
894121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            if (NO_ERROR !=
895121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                mFrameCompleteCondition.waitRelative(mLock,
896121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                        mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
897121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                ALOGW("Timed out waiting for outstanding frames being encoded: %zu",
898121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mFramesBeingEncoded.size());
899121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            }
900121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
901121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        stopCameraRecording();
902121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (isTokenValid) {
903121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            IPCThreadState::self()->restoreCallingIdentity(token);
90441152efd144ccf70c380d5c9a32105c02a039f43James Dong        }
9057278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
906121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mCollectStats) {
907121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGI("Frames received/encoded/dropped: %d/%d/%d in %" PRId64 " us",
908121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
909121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang                    mLastFrameTimestampUs - mFirstFrameTimeUs);
910121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
911121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
912121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        if (mNumGlitches > 0) {
913121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang            ALOGW("%d long delays between neighboring video frames", mNumGlitches);
914121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        }
91513aec890216948b0c364f8f92792129d0335f506James Dong
916121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang        CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
917ba29002c7aee13c068049037cd14bba6a244da6bJames Dong    }
918ba29002c7aee13c068049037cd14bba6a244da6bJames Dong
9198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mBufferQueueListener != nullptr) {
9208cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener->requestExit();
9218cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener->join();
9228cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mBufferQueueListener.clear();
9238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
9248cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferConsumer.clear();
9268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mVideoBufferProducer.clear();
927121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang    releaseCamera();
928121969b7e0d958092fae76226dc55fe8547a1da6Chong Zhang
929b44c9d2bdc0d5b9cb03254022a58e017b516e9e6James Dong    ALOGD("reset: X");
93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
93220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
93365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatravoid CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
9343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("releaseRecordingFrame");
9358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
936d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala    if (mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE) {
9378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Return the buffer to buffer queue in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
9388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ssize_t offset;
9398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        size_t size;
9408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
9418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (heap->getHeapID() != mMemoryHeapBase->getHeapID()) {
9428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Mismatched heap ID, ignoring release (got %x, expected %x)", __FUNCTION__,
9438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                    heap->getHeapID(), mMemoryHeapBase->getHeapID());
9448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return;
9458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
9468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        VideoNativeMetadata *payload = reinterpret_cast<VideoNativeMetadata*>(
9488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                (uint8_t*)heap->getBase() + offset);
9498cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9508cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        // Find the corresponding buffer item for the native window buffer.
9518cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        ssize_t index = mReceivedBufferItemMap.indexOfKey(payload->pBuffer);
9528cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        if (index == NAME_NOT_FOUND) {
9538cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            ALOGE("%s: Couldn't find buffer item for %p", __FUNCTION__, payload->pBuffer);
9548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return;
9558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
9568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
9578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        BufferItem buffer = mReceivedBufferItemMap.valueAt(index);
9588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mReceivedBufferItemMap.removeItemsAt(index);
9598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mVideoBufferConsumer->releaseBuffer(buffer);
9608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mMemoryBases.push_back(frame);
9610419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        mMemoryBaseAvailableCond.signal();
9622d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    } else {
9632d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        native_handle_t* handle = nullptr;
9642d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
9652d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        // Check if frame contains a VideoNativeHandleMetadata.
9662d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        if (frame->size() == sizeof(VideoNativeHandleMetadata)) {
9672d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            VideoNativeHandleMetadata *metadata =
9682d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen                (VideoNativeHandleMetadata*)(frame->pointer());
9692d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
9702d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen                handle = metadata->pHandle;
9712d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            }
9722d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        }
9732d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
9742d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        if (handle != nullptr) {
9757eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick            ssize_t offset;
9767eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick            size_t size;
9777eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick            sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
9787eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick            if (heap->getHeapID() != mMemoryHeapBase->getHeapID()) {
9797eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick                ALOGE("%s: Mismatched heap ID, ignoring release (got %x, expected %x)",
9807eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick		     __FUNCTION__, heap->getHeapID(), mMemoryHeapBase->getHeapID());
9817eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick                return;
9827eb18466d9ee817ae1087ddc895902e8eae05535Ray Essick            }
983b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            uint32_t batchSize = 0;
984b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            {
985b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                Mutex::Autolock autoLock(mBatchLock);
986b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                if (mInflightBatchSizes.size() > 0) {
987b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    batchSize = mInflightBatchSizes[0];
988b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                }
989b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            }
990b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            if (batchSize == 0) { // return buffers one by one
991b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                // Frame contains a VideoNativeHandleMetadata. Send the handle back to camera.
992b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                releaseRecordingFrameHandle(handle);
993b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                mMemoryBases.push_back(frame);
994b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                mMemoryBaseAvailableCond.signal();
995b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            } else { // Group buffers in batch then return
996b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                Mutex::Autolock autoLock(mBatchLock);
997b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                mInflightReturnedHandles.push_back(handle);
998b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                mInflightReturnedMemorys.push_back(frame);
999b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                if (mInflightReturnedHandles.size() == batchSize) {
1000b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    releaseRecordingFrameHandleBatch(mInflightReturnedHandles);
1001b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1002b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    mInflightBatchSizes.pop_front();
1003b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    mInflightReturnedHandles.clear();
1004b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    for (const auto& mem : mInflightReturnedMemorys) {
1005b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                        mMemoryBases.push_back(mem);
1006b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                        mMemoryBaseAvailableCond.signal();
1007b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    }
1008b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    mInflightReturnedMemorys.clear();
1009b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                }
1010b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            }
1011b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
10122d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        } else if (mCameraRecordingProxy != nullptr) {
10132d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            // mCamera is created by application. Return the frame back to camera via camera
10142d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            // recording proxy.
10152d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            mCameraRecordingProxy->releaseRecordingFrame(frame);
10162d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        } else if (mCamera != nullptr) {
10172d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            // mCamera is created by CameraSource. Return the frame directly back to camera.
10182d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            int64_t token = IPCThreadState::self()->clearCallingIdentity();
10192d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            mCamera->releaseRecordingFrame(frame);
10202d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            IPCThreadState::self()->restoreCallingIdentity(token);
10212d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        }
1022d69c7f654cc772b03717999c1b24402d5c40e69fJames Dong    }
102365e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra}
102465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra
1025c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dongvoid CameraSource::releaseQueuedFrames() {
1026c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    List<sp<IMemory> >::iterator it;
10277278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    while (!mFramesReceived.empty()) {
10287278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        it = mFramesReceived.begin();
102965e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra        releaseRecordingFrame(*it);
10307278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        mFramesReceived.erase(it);
103113aec890216948b0c364f8f92792129d0335f506James Dong        ++mNumFramesDropped;
1032c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
1033c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong}
1034c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong
103520111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> CameraSource::getFormat() {
1036653252be963c07c99109d20f942d1f30c52a9360James Dong    return mMeta;
103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1039f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dongvoid CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
104065e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    releaseRecordingFrame(frame);
1041f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong}
1042f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong
10437278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dongvoid CameraSource::signalBufferReturned(MediaBuffer *buffer) {
10443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("signalBufferReturned: %p", buffer->data());
104556223b96c2f6de5998496fac9d6703f06adc1dcaAndreas Huber    Mutex::Autolock autoLock(mLock);
10467278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
10477278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong         it != mFramesBeingEncoded.end(); ++it) {
10487278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        if ((*it)->pointer() ==  buffer->data()) {
1049f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            releaseOneRecordingFrame((*it));
10507278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFramesBeingEncoded.erase(it);
10517278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            ++mNumFramesEncoded;
10527278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->setObserver(0);
10537278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            buffer->release();
10547278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            mFrameCompleteCondition.signal();
10557278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong            return;
10567278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong        }
10577278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
1058f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    CHECK(!"signalBufferReturned: bogus buffer");
10597278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong}
10607278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t CameraSource::read(
106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **buffer, const ReadOptions *options) {
10633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("read");
106420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *buffer = NULL;
106620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
1068abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
1069abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
107020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_UNSUPPORTED;
107120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
107220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<IMemory> frame;
1074be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    int64_t frameTime;
107520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
107620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    {
107720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Mutex::Autolock autoLock(mLock);
107879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        while (mStarted && mFramesReceived.empty()) {
107941152efd144ccf70c380d5c9a32105c02a039f43James Dong            if (NO_ERROR !=
1080e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                mFrameAvailableCondition.waitRelative(mLock,
1081e8e5f86e9e310b065596c8cbbca1543eb833dee1James Dong                    mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
10823bd3020c00ec8264ac1fe3870800f326487f9221James Dong                if (mCameraRecordingProxy != 0 &&
108306b46062d2f8bc82ca3061a23d197734ae51918bMarco Nelissen                    !IInterface::asBinder(mCameraRecordingProxy)->isBinderAlive()) {
10845ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW("camera recording proxy is gone");
10854ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                    return ERROR_END_OF_STREAM;
10864ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li                }
1087a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn                ALOGW("Timed out waiting for incoming camera video frames: %" PRId64 " us",
108841152efd144ccf70c380d5c9a32105c02a039f43James Dong                    mLastFrameTimestampUs);
108941152efd144ccf70c380d5c9a32105c02a039f43James Dong            }
109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
109179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        if (!mStarted) {
109279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong            return OK;
109379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        }
109479e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frame = *mFramesReceived.begin();
109579e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesReceived.erase(mFramesReceived.begin());
109679e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong
109779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        frameTime = *mFrameTimes.begin();
109879e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFrameTimes.erase(mFrameTimes.begin());
109979e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        mFramesBeingEncoded.push_back(frame);
110079e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        *buffer = new MediaBuffer(frame->pointer(), frame->size());
110179e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->setObserver(this);
110279e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->add_ref();
110379e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
11047278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    }
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1108f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuangstatus_t CameraSource::setStopTimeUs(int64_t stopTimeUs) {
1109f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    Mutex::Autolock autoLock(mLock);
1110f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    ALOGV("Set stoptime: %lld us", (long long)stopTimeUs);
1111f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
1112f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    if (stopTimeUs < -1) {
1113f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        ALOGE("Invalid stop time %lld us", (long long)stopTimeUs);
1114f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        return BAD_VALUE;
1115f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    } else if (stopTimeUs == -1) {
1116f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        ALOGI("reset stopTime to be -1");
1117f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    }
1118f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
1119f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    mStopSystemTimeUs = stopTimeUs;
1120f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    return OK;
1121f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang}
1122f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
11238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenbool CameraSource::shouldSkipFrameLocked(int64_t timestampUs) {
1124a472613aec322e25891abf5c77bf3f7e3c244920James Dong    if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
1125ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar        ALOGV("Drop frame at %lld/%lld us", (long long)timestampUs, (long long)mStartTimeUs);
11268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return true;
1127c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong    }
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1129f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    if (mStopSystemTimeUs != -1 && timestampUs >= mStopSystemTimeUs) {
1130f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        ALOGV("Drop Camera frame at %lld  stop time: %lld us",
1131f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang                (long long)timestampUs, (long long)mStopSystemTimeUs);
1132f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        return true;
1133f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    }
1134f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
113565e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // May need to skip frame or modify timestamp. Currently implemented
113665e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra    // by the subclass CameraSourceTimeLapse.
113779e23b41fad961008bfde6e26b3c6f86878ca69dJames Dong    if (skipCurrentFrame(timestampUs)) {
11388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return true;
1139fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra    }
1140fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra
11410aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang    if (mNumFramesReceived > 0) {
11420aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        if (timestampUs <= mLastFrameTimestampUs) {
11430aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang            ALOGW("Dropping frame with backward timestamp %lld (last %lld)",
11440aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang                    (long long)timestampUs, (long long)mLastFrameTimestampUs);
11458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            return true;
11460aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        }
11470aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
11480aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang            ++mNumGlitches;
11490aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang        }
11500aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang    }
11510aaff700f6c7885887bbf42f7bb64754e21e5fceChong Zhang
1152365a963142093a1cd8efdcea76b5f65096a5b115James Dong    mLastFrameTimestampUs = timestampUs;
115313aec890216948b0c364f8f92792129d0335f506James Dong    if (mNumFramesReceived == 0) {
1154c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong        mFirstFrameTimeUs = timestampUs;
1155f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        // Initial delay
1156f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        if (mStartTimeUs > 0) {
1157f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            if (timestampUs < mStartTimeUs) {
1158f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Frame was captured before recording was started
1159f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong                // Drop it without updating the statistical data.
11608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                return true;
1161f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            }
1162f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong            mStartTimeUs = timestampUs - mStartTimeUs;
1163f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        }
1164be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber    }
11658cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11668cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return false;
11678cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
11688cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenvoid CameraSource::dataCallbackTimestamp(int64_t timestampUs,
11708cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        int32_t msgType __unused, const sp<IMemory> &data) {
11718cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("dataCallbackTimestamp: timestamp %lld us", (long long)timestampUs);
11728cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock autoLock(mLock);
11738cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
11748cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (shouldSkipFrameLocked(timestampUs)) {
11758cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        releaseOneRecordingFrame(data);
11768cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return;
11778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
11788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
117913aec890216948b0c364f8f92792129d0335f506James Dong    ++mNumFramesReceived;
1180be5c74f5da6a93b0d23f96e11848acfcc3b4d1d9Andreas Huber
118198cfde007490a5903b729a4718c0dada755ae8f8James Dong    CHECK(data != NULL && data->size() > 0);
11827278cf32f1aa6a322f6dff1f8b7dacf7b6dddba6James Dong    mFramesReceived.push_back(data);
1183f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
1184f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong    mFrameTimes.push_back(timeUs);
1185a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64,
1186f60cafe0e6aad8f9ce54660fa88b651ae4e749e6James Dong        mStartTimeUs, timeUs);
118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFrameAvailableCondition.signal();
118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11902d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSource::releaseRecordingFrameHandle(native_handle_t* handle) {
11912d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    if (mCameraRecordingProxy != nullptr) {
11922d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        mCameraRecordingProxy->releaseRecordingFrameHandle(handle);
11932d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    } else if (mCamera != nullptr) {
11942d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        int64_t token = IPCThreadState::self()->clearCallingIdentity();
11952d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        mCamera->releaseRecordingFrameHandle(handle);
11962d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        IPCThreadState::self()->restoreCallingIdentity(token);
1197cb9e825306cd0a97e50a4ef9d7c58f4e961692d9Chien-Yu Chen    } else {
1198cb9e825306cd0a97e50a4ef9d7c58f4e961692d9Chien-Yu Chen        native_handle_close(handle);
1199cb9e825306cd0a97e50a4ef9d7c58f4e961692d9Chien-Yu Chen        native_handle_delete(handle);
12002d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    }
12012d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
12022d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
1203b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yehvoid CameraSource::releaseRecordingFrameHandleBatch(const std::vector<native_handle_t*>& handles) {
1204b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    if (mCameraRecordingProxy != nullptr) {
1205b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mCameraRecordingProxy->releaseRecordingFrameHandleBatch(handles);
1206b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    } else if (mCamera != nullptr) {
1207b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        int64_t token = IPCThreadState::self()->clearCallingIdentity();
1208b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mCamera->releaseRecordingFrameHandleBatch(handles);
1209b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        IPCThreadState::self()->restoreCallingIdentity(token);
1210b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    } else {
1211b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        for (auto& handle : handles) {
1212b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            native_handle_close(handle);
1213b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            native_handle_delete(handle);
1214b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        }
1215b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1216b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh}
1217b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
12182d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSource::recordingFrameHandleCallbackTimestamp(int64_t timestampUs,
12192d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen                native_handle_t* handle) {
12202d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    ALOGV("%s: timestamp %lld us", __FUNCTION__, (long long)timestampUs);
12212d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    Mutex::Autolock autoLock(mLock);
12222d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    if (handle == nullptr) return;
12232d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12242d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    if (shouldSkipFrameLocked(timestampUs)) {
12252d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        releaseRecordingFrameHandle(handle);
12262d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        return;
12272d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    }
12282d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12292d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    while (mMemoryBases.empty()) {
12302d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        if (mMemoryBaseAvailableCond.waitRelative(mLock, kMemoryBaseAvailableTimeoutNs) ==
12312d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen                TIMED_OUT) {
12322d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            ALOGW("Waiting on an available memory base timed out. Dropping a recording frame.");
12332d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            releaseRecordingFrameHandle(handle);
12342d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen            return;
12352d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        }
12362d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    }
12372d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12382d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    ++mNumFramesReceived;
12392d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12402d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    sp<IMemory> data = *mMemoryBases.begin();
12412d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mMemoryBases.erase(mMemoryBases.begin());
12422d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12432d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    // Wrap native handle in sp<IMemory> so it can be pushed to mFramesReceived.
12442d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->pointer());
12452d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    metadata->eType = kMetadataBufferTypeNativeHandleSource;
12462d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    metadata->pHandle = handle;
12472d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
12482d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mFramesReceived.push_back(data);
12492d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
12502d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mFrameTimes.push_back(timeUs);
12512d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64, mStartTimeUs, timeUs);
12522d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mFrameAvailableCondition.signal();
12532d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
12542d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
1255b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yehvoid CameraSource::recordingFrameHandleCallbackTimestampBatch(
1256b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<int64_t>& timestampsUs,
1257b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<native_handle_t*>& handles) {
1258b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    size_t n = timestampsUs.size();
1259b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    if (n != handles.size()) {
1260b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        ALOGE("%s: timestampsUs(%zu) and handles(%zu) size mismatch!",
1261b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                __FUNCTION__, timestampsUs.size(), handles.size());
1262b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1263b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1264b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    Mutex::Autolock autoLock(mLock);
1265b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    int batchSize = 0;
1266b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    for (size_t i = 0; i < n; i++) {
1267b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        int64_t timestampUs = timestampsUs[i];
1268b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        native_handle_t* handle = handles[i];
1269b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1270b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        ALOGV("%s: timestamp %lld us", __FUNCTION__, (long long)timestampUs);
1271b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        if (handle == nullptr) continue;
1272b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1273b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        if (shouldSkipFrameLocked(timestampUs)) {
1274b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            releaseRecordingFrameHandle(handle);
1275b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            continue;
1276b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        }
1277b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1278b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        while (mMemoryBases.empty()) {
1279b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            if (mMemoryBaseAvailableCond.waitRelative(mLock, kMemoryBaseAvailableTimeoutNs) ==
1280b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                    TIMED_OUT) {
1281b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                ALOGW("Waiting on an available memory base timed out. Dropping a recording frame.");
1282b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                releaseRecordingFrameHandle(handle);
1283b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh                continue;
1284b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh            }
1285b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        }
1286b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        ++batchSize;
1287b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        ++mNumFramesReceived;
1288b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        sp<IMemory> data = *mMemoryBases.begin();
1289b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mMemoryBases.erase(mMemoryBases.begin());
1290b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1291b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        // Wrap native handle in sp<IMemory> so it can be pushed to mFramesReceived.
1292b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        VideoNativeHandleMetadata *metadata = (VideoNativeHandleMetadata*)(data->pointer());
1293b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        metadata->eType = kMetadataBufferTypeNativeHandleSource;
1294b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        metadata->pHandle = handle;
1295b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1296b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mFramesReceived.push_back(data);
1297b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
1298b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mFrameTimes.push_back(timeUs);
1299b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64, mStartTimeUs, timeUs);
1300b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1301b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1302b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    if (batchSize > 0) {
1303b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        Mutex::Autolock autoLock(mBatchLock);
1304b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mInflightBatchSizes.push_back(batchSize);
1305b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1306b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    for (int i = 0; i < batchSize; i++) {
1307b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        mFrameAvailableCondition.signal();
1308b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1309b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh}
1310b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
13118cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu ChenCameraSource::BufferQueueListener::BufferQueueListener(const sp<BufferItemConsumer>& consumer,
13128cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        const sp<CameraSource>& cameraSource) {
13138cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mConsumer = consumer;
13148cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mConsumer->setFrameAvailableListener(this);
13158cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mCameraSource = cameraSource;
13168cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
13178cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13188cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenvoid CameraSource::BufferQueueListener::onFrameAvailable(const BufferItem& /*item*/) {
13198cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("%s: onFrameAvailable", __FUNCTION__);
13208cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13218cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock l(mLock);
13228cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13238cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (!mFrameAvailable) {
13248cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailable = true;
13258cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailableSignal.signal();
13268cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13278cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
13288cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13298cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chenbool CameraSource::BufferQueueListener::threadLoop() {
13308cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (mConsumer == nullptr || mCameraSource == nullptr) {
13318cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return false;
13328cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13338cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13348cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    {
13358cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        Mutex::Autolock l(mLock);
13368cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        while (!mFrameAvailable) {
13378cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            if (mFrameAvailableSignal.waitRelative(mLock, kFrameAvailableTimeout) == TIMED_OUT) {
13388cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen                return true;
13398cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen            }
13408cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        }
13418cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mFrameAvailable = false;
13428cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13438cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13448cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    BufferItem buffer;
13458cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    while (mConsumer->acquireBuffer(&buffer, 0) == OK) {
13468cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mCameraSource->processBufferQueueFrame(buffer);
13478cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13488cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13498cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    return true;
13508cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
13518cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13528fc3c670fff26cb21d1e16dbfcbc4410d7758574Chien-Yu Chenvoid CameraSource::processBufferQueueFrame(BufferItem& buffer) {
13538cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    Mutex::Autolock autoLock(mLock);
13548cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13558cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    int64_t timestampUs = buffer.mTimestamp / 1000;
13568cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    if (shouldSkipFrameLocked(timestampUs)) {
13578cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mVideoBufferConsumer->releaseBuffer(buffer);
13588cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        return;
13598cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13608cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13610419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen    while (mMemoryBases.empty()) {
13620419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        if (mMemoryBaseAvailableCond.waitRelative(mLock, kMemoryBaseAvailableTimeoutNs) ==
13630419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen                TIMED_OUT) {
13640419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            ALOGW("Waiting on an available memory base timed out. Dropping a recording frame.");
13650419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            mVideoBufferConsumer->releaseBuffer(buffer);
13660419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen            return;
13670419ba7b1c1bd4f19b2fab06234eacb4547a7c04Chien-Yu Chen        }
13688cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    }
13698cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13708cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ++mNumFramesReceived;
13718cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13728cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Find a available memory slot to store the buffer as VideoNativeMetadata.
13738cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IMemory> data = *mMemoryBases.begin();
13748cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mMemoryBases.erase(mMemoryBases.begin());
13758cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13768cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ssize_t offset;
13778cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    size_t size;
13788cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    sp<IMemoryHeap> heap = data->getMemory(&offset, &size);
13798cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    VideoNativeMetadata *payload = reinterpret_cast<VideoNativeMetadata*>(
13808cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        (uint8_t*)heap->getBase() + offset);
13818cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    memset(payload, 0, sizeof(VideoNativeMetadata));
13828cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->eType = kMetadataBufferTypeANWBuffer;
13838cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->pBuffer = buffer.mGraphicBuffer->getNativeBuffer();
13848cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    payload->nFenceFd = -1;
13858cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13868cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Add the mapping so we can find the corresponding buffer item to release to the buffer queue
13878cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // when the encoder returns the native window buffer.
13888cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mReceivedBufferItemMap.add(payload->pBuffer, buffer);
13898cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13908cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFramesReceived.push_back(data);
13918cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
13928cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFrameTimes.push_back(timeUs);
13938cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64,
13948cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen        mStartTimeUs, timeUs);
13958cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    mFrameAvailableCondition.signal();
13968cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen}
13978cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
13983e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos MolnarMetadataBufferType CameraSource::metaDataStoredInVideoBuffers() const {
13993e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    ALOGV("metaDataStoredInVideoBuffers");
14008cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen
14018cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // Output buffers will contain metadata if camera sends us buffer in metadata mode or via
14028cca0750a84c2d97224c0cfef7cf255308ee80b3Chien-Yu Chen    // buffer queue.
14033e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    switch (mVideoBufferMode) {
14043e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        case hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA:
14053e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar            return kMetadataBufferTypeNativeHandleSource;
14063e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        case hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE:
14073e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar            return kMetadataBufferTypeANWBuffer;
14083e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar        default:
14093e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar            return kMetadataBufferTypeInvalid;
14103e328782f1e1061d08ea0c45b855cc418a2d9ea6Lajos Molnar    }
14115c9523154d106b555db6c41f85ab205a4f189b02James Dong}
14125c9523154d106b555db6c41f85ab205a4f189b02James Dong
14134ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng LiCameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
14144ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource = source;
14154ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
14164ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
14174ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Livoid CameraSource::ProxyListener::dataCallbackTimestamp(
14184ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
14194ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li    mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
14204ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
14214ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
14222d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chenvoid CameraSource::ProxyListener::recordingFrameHandleCallbackTimestamp(nsecs_t timestamp,
14232d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen        native_handle_t* handle) {
14242d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen    mSource->recordingFrameHandleCallbackTimestamp(timestamp / 1000, handle);
14252d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen}
14262d13b1d3eeaba31d8c15acc6037fd68b150a9a66Chien-Yu Chen
1427b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yehvoid CameraSource::ProxyListener::recordingFrameHandleCallbackTimestampBatch(
1428b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<int64_t>& timestampsUs,
1429b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        const std::vector<native_handle_t*>& handles) {
1430b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    int n = timestampsUs.size();
1431b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    std::vector<nsecs_t> modifiedTimestamps(n);
1432b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    for (int i = 0; i < n; i++) {
1433b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh        modifiedTimestamps[i] = timestampsUs[i] / 1000;
1434b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    }
1435b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh    mSource->recordingFrameHandleCallbackTimestampBatch(modifiedTimestamps, handles);
1436b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh}
1437b5df547bce900fa5764d735bee304e79c001d60dYin-Chia Yeh
1438ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnarvoid CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who __unused) {
1439df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("Camera recording proxy died");
14404ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li}
14414ca2c7c913f8bd4ada13aca56d36045d42d1e00fWu-cheng Li
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
1443