CameraSource.cpp revision 03b268eac37ca2589bfff0bf58daf79d29cc14f4
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <sys/time.h>
18
19#include <OMX_Component.h>
20
21#include <binder/IServiceManager.h>
22#include <cutils/properties.h> // for property_get
23#include <media/stagefright/CameraSource.h>
24#include <media/stagefright/MediaDebug.h>
25#include <media/stagefright/MediaDefs.h>
26#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MetaData.h>
28#include <camera/Camera.h>
29#include <camera/CameraParameters.h>
30#include <ui/GraphicBuffer.h>
31#include <ui/Overlay.h>
32#include <surfaceflinger/ISurface.h>
33#include <utils/String8.h>
34
35namespace android {
36
37static int64_t getNowUs() {
38    struct timeval tv;
39    gettimeofday(&tv, NULL);
40
41    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
42}
43
44struct DummySurface : public BnSurface {
45    DummySurface() {}
46
47    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) {
48        return NULL;
49    }
50
51    virtual status_t registerBuffers(const BufferHeap &buffers) {
52        return OK;
53    }
54
55    virtual void postBuffer(ssize_t offset) {}
56    virtual void unregisterBuffers() {}
57
58    virtual sp<OverlayRef> createOverlay(
59            uint32_t w, uint32_t h, int32_t format, int32_t orientation) {
60        return NULL;
61    }
62
63protected:
64    virtual ~DummySurface() {}
65
66    DummySurface(const DummySurface &);
67    DummySurface &operator=(const DummySurface &);
68};
69
70struct CameraSourceListener : public CameraListener {
71    CameraSourceListener(const sp<CameraSource> &source);
72
73    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
74    virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr);
75
76    virtual void postDataTimestamp(
77            nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
78
79protected:
80    virtual ~CameraSourceListener();
81
82private:
83    wp<CameraSource> mSource;
84
85    CameraSourceListener(const CameraSourceListener &);
86    CameraSourceListener &operator=(const CameraSourceListener &);
87};
88
89CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
90    : mSource(source) {
91}
92
93CameraSourceListener::~CameraSourceListener() {
94}
95
96void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
97    LOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
98}
99
100void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
101    LOGV("postData(%d, ptr:%p, size:%d)",
102         msgType, dataPtr->pointer(), dataPtr->size());
103
104    sp<CameraSource> source = mSource.promote();
105    if (source.get() != NULL) {
106        source->dataCallback(msgType, dataPtr);
107    }
108}
109
110void CameraSourceListener::postDataTimestamp(
111        nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
112    LOGV("postDataTimestamp(%lld, %d, ptr:%p, size:%d)",
113         timestamp, msgType, dataPtr->pointer(), dataPtr->size());
114}
115
116// static
117CameraSource *CameraSource::Create() {
118    sp<Camera> camera = Camera::connect();
119
120    if (camera.get() == NULL) {
121        return NULL;
122    }
123
124    return new CameraSource(camera);
125}
126
127// static
128CameraSource *CameraSource::CreateFromICamera(const sp<ICamera> &icamera) {
129    sp<Camera> camera = Camera::create(icamera);
130
131    if (camera.get() == NULL) {
132        return NULL;
133    }
134
135    return new CameraSource(camera);
136}
137
138CameraSource::CameraSource(const sp<Camera> &camera)
139    : mCamera(camera),
140      mWidth(0),
141      mHeight(0),
142      mFirstFrameTimeUs(0),
143      mNumFrames(0),
144      mStarted(false) {
145    String8 s = mCamera->getParameters();
146    printf("params: \"%s\"\n", s.string());
147
148    CameraParameters params(s);
149    params.getPreviewSize(&mWidth, &mHeight);
150}
151
152CameraSource::~CameraSource() {
153    if (mStarted) {
154        stop();
155    }
156}
157
158void CameraSource::setPreviewSurface(const sp<ISurface> &surface) {
159    mPreviewSurface = surface;
160}
161
162status_t CameraSource::start(MetaData *) {
163    CHECK(!mStarted);
164
165    mCamera->setListener(new CameraSourceListener(this));
166
167    status_t err =
168        mCamera->setPreviewDisplay(
169                mPreviewSurface != NULL ? mPreviewSurface : new DummySurface);
170    CHECK_EQ(err, OK);
171
172    mCamera->setPreviewCallbackFlags(
173            FRAME_CALLBACK_FLAG_ENABLE_MASK
174            | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);
175
176    err = mCamera->startPreview();
177    CHECK_EQ(err, OK);
178
179    mStarted = true;
180
181    return OK;
182}
183
184status_t CameraSource::stop() {
185    CHECK(mStarted);
186
187    mCamera->stopPreview();
188
189    mStarted = false;
190
191    return OK;
192}
193
194sp<MetaData> CameraSource::getFormat() {
195    sp<MetaData> meta = new MetaData;
196    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
197    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
198    meta->setInt32(kKeyWidth, mWidth);
199    meta->setInt32(kKeyHeight, mHeight);
200
201    return meta;
202}
203
204status_t CameraSource::read(
205        MediaBuffer **buffer, const ReadOptions *options) {
206    CHECK(mStarted);
207
208    *buffer = NULL;
209
210    int64_t seekTimeUs;
211    if (options && options->getSeekTo(&seekTimeUs)) {
212        return ERROR_UNSUPPORTED;
213    }
214
215    sp<IMemory> frame;
216    int64_t frameTime;
217
218    {
219        Mutex::Autolock autoLock(mLock);
220        while (mFrames.empty()) {
221            mFrameAvailableCondition.wait(mLock);
222        }
223
224        frame = *mFrames.begin();
225        mFrames.erase(mFrames.begin());
226
227        frameTime = *mFrameTimes.begin();
228        mFrameTimes.erase(mFrameTimes.begin());
229    }
230
231    *buffer = new MediaBuffer(frame->size());
232    memcpy((*buffer)->data(), frame->pointer(), frame->size());
233    (*buffer)->set_range(0, frame->size());
234
235    (*buffer)->meta_data()->clear();
236    (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
237
238    return OK;
239}
240
241void CameraSource::dataCallback(int32_t msgType, const sp<IMemory> &data) {
242    Mutex::Autolock autoLock(mLock);
243
244    int64_t nowUs = getNowUs();
245    if (mNumFrames == 0) {
246        mFirstFrameTimeUs = nowUs;
247    }
248    ++mNumFrames;
249
250    mFrames.push_back(data);
251    mFrameTimes.push_back(nowUs - mFirstFrameTimeUs);
252    mFrameAvailableCondition.signal();
253}
254
255}  // namespace android
256