blob: bd862e0de34e1515e6526e53d30fd780b075bee2 [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
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
Andreas Huber20111aa2009-07-14 16:56:47 -070019#include <OMX_Component.h>
20
21#include <binder/IServiceManager.h>
Andreas Huber30ab6622009-11-16 15:43:38 -080022#include <cutils/properties.h> // for property_get
Andreas Huber20111aa2009-07-14 16:56:47 -070023#include <media/stagefright/CameraSource.h>
Andreas Huber0c891992009-08-26 14:48:20 -070024#include <media/stagefright/MediaDebug.h>
Andreas Huberbe5c74f2009-10-13 17:08:31 -070025#include <media/stagefright/MediaDefs.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070026#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MetaData.h>
Andreas Huberbe5c74f2009-10-13 17:08:31 -070028#include <ui/Camera.h>
29#include <ui/CameraParameters.h>
30#include <ui/GraphicBuffer.h>
31#include <ui/ISurface.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070032#include <ui/Overlay.h>
Andreas Huberbe5c74f2009-10-13 17:08:31 -070033#include <utils/String8.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070034
35namespace android {
36
Andreas Huberbe5c74f2009-10-13 17:08:31 -070037static int64_t getNowUs() {
38 struct timeval tv;
39 gettimeofday(&tv, NULL);
Andreas Huber20111aa2009-07-14 16:56:47 -070040
Andreas Huberbe5c74f2009-10-13 17:08:31 -070041 return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
42}
Andreas Huber20111aa2009-07-14 16:56:47 -070043
Andreas Huberbe5c74f2009-10-13 17:08:31 -070044struct DummySurface : public BnSurface {
Andreas Huber20111aa2009-07-14 16:56:47 -070045 DummySurface() {}
46
Andreas Huberbe5c74f2009-10-13 17:08:31 -070047 virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) {
48 return NULL;
49 }
50
Andreas Huber20111aa2009-07-14 16:56:47 -070051 virtual status_t registerBuffers(const BufferHeap &buffers) {
52 return OK;
53 }
54
Andreas Huberbe5c74f2009-10-13 17:08:31 -070055 virtual void postBuffer(ssize_t offset) {}
56 virtual void unregisterBuffers() {}
Andreas Huber20111aa2009-07-14 16:56:47 -070057
Andreas Huber20111aa2009-07-14 16:56:47 -070058 virtual sp<OverlayRef> createOverlay(
59 uint32_t w, uint32_t h, int32_t format) {
60 return NULL;
61 }
Andreas Huberbe5c74f2009-10-13 17:08:31 -070062
63protected:
64 virtual ~DummySurface() {}
65
66 DummySurface(const DummySurface &);
67 DummySurface &operator=(const DummySurface &);
Andreas Huber20111aa2009-07-14 16:56:47 -070068};
69
Andreas Huberbe5c74f2009-10-13 17:08:31 -070070struct 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
Andreas Huber20111aa2009-07-14 16:56:47 -0700116// static
117CameraSource *CameraSource::Create() {
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700118 sp<Camera> camera = Camera::connect();
Andreas Huber20111aa2009-07-14 16:56:47 -0700119
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700120 if (camera.get() == NULL) {
121 return NULL;
122 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700123
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700124 return new CameraSource(camera);
Andreas Huber20111aa2009-07-14 16:56:47 -0700125}
126
Andreas Huber30ab6622009-11-16 15:43:38 -0800127// 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
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700138CameraSource::CameraSource(const sp<Camera> &camera)
Andreas Huber20111aa2009-07-14 16:56:47 -0700139 : mCamera(camera),
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700140 mWidth(0),
141 mHeight(0),
142 mFirstFrameTimeUs(0),
Andreas Huber20111aa2009-07-14 16:56:47 -0700143 mNumFrames(0),
144 mStarted(false) {
Andreas Huber30ab6622009-11-16 15:43:38 -0800145 char value[PROPERTY_VALUE_MAX];
146 if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) {
147 // The hardware encoder(s) do not support yuv420, but only YCbYCr,
148 // fortunately the camera also supports this, so we needn't transcode.
149 mCamera->setParameters(String8("preview-format=yuv422i-yuyv"));
150 }
151
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700152 String8 s = mCamera->getParameters();
153 printf("params: \"%s\"\n", s.string());
154
155 CameraParameters params(s);
156 params.getPreviewSize(&mWidth, &mHeight);
Andreas Huber20111aa2009-07-14 16:56:47 -0700157}
158
159CameraSource::~CameraSource() {
160 if (mStarted) {
161 stop();
162 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700163}
164
Andreas Huber30ab6622009-11-16 15:43:38 -0800165void CameraSource::setPreviewSurface(const sp<ISurface> &surface) {
166 mPreviewSurface = surface;
167}
168
Andreas Huber20111aa2009-07-14 16:56:47 -0700169status_t CameraSource::start(MetaData *) {
Andreas Huber0c891992009-08-26 14:48:20 -0700170 CHECK(!mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700171
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700172 mCamera->setListener(new CameraSourceListener(this));
173
Andreas Huber30ab6622009-11-16 15:43:38 -0800174 status_t err =
175 mCamera->setPreviewDisplay(
176 mPreviewSurface != NULL ? mPreviewSurface : new DummySurface);
Andreas Huber0c891992009-08-26 14:48:20 -0700177 CHECK_EQ(err, OK);
Andreas Huber20111aa2009-07-14 16:56:47 -0700178
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700179 mCamera->setPreviewCallbackFlags(
180 FRAME_CALLBACK_FLAG_ENABLE_MASK
181 | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);
182
183 err = mCamera->startPreview();
Andreas Huber0c891992009-08-26 14:48:20 -0700184 CHECK_EQ(err, OK);
Andreas Huber20111aa2009-07-14 16:56:47 -0700185
186 mStarted = true;
187
188 return OK;
189}
190
191status_t CameraSource::stop() {
Andreas Huber0c891992009-08-26 14:48:20 -0700192 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700193
194 mCamera->stopPreview();
Andreas Huber20111aa2009-07-14 16:56:47 -0700195
196 mStarted = false;
197
198 return OK;
199}
200
201sp<MetaData> CameraSource::getFormat() {
202 sp<MetaData> meta = new MetaData;
Andreas Huber18291bc2009-09-10 14:13:30 -0700203 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huber20111aa2009-07-14 16:56:47 -0700204 meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700205 meta->setInt32(kKeyWidth, mWidth);
206 meta->setInt32(kKeyHeight, mHeight);
Andreas Huber20111aa2009-07-14 16:56:47 -0700207
208 return meta;
209}
210
211status_t CameraSource::read(
212 MediaBuffer **buffer, const ReadOptions *options) {
Andreas Huber0c891992009-08-26 14:48:20 -0700213 CHECK(mStarted);
Andreas Huber20111aa2009-07-14 16:56:47 -0700214
215 *buffer = NULL;
216
217 int64_t seekTimeUs;
218 if (options && options->getSeekTo(&seekTimeUs)) {
219 return ERROR_UNSUPPORTED;
220 }
221
222 sp<IMemory> frame;
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700223 int64_t frameTime;
Andreas Huber20111aa2009-07-14 16:56:47 -0700224
225 {
226 Mutex::Autolock autoLock(mLock);
227 while (mFrames.empty()) {
228 mFrameAvailableCondition.wait(mLock);
229 }
230
231 frame = *mFrames.begin();
232 mFrames.erase(mFrames.begin());
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700233
234 frameTime = *mFrameTimes.begin();
235 mFrameTimes.erase(mFrameTimes.begin());
Andreas Huber20111aa2009-07-14 16:56:47 -0700236 }
237
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700238 *buffer = new MediaBuffer(frame->size());
239 memcpy((*buffer)->data(), frame->pointer(), frame->size());
240 (*buffer)->set_range(0, frame->size());
Andreas Huber20111aa2009-07-14 16:56:47 -0700241
242 (*buffer)->meta_data()->clear();
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700243 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
Andreas Huber20111aa2009-07-14 16:56:47 -0700244
245 return OK;
246}
247
Andreas Huber20111aa2009-07-14 16:56:47 -0700248void CameraSource::dataCallback(int32_t msgType, const sp<IMemory> &data) {
249 Mutex::Autolock autoLock(mLock);
250
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700251 int64_t nowUs = getNowUs();
252 if (mNumFrames == 0) {
253 mFirstFrameTimeUs = nowUs;
254 }
255 ++mNumFrames;
256
Andreas Huber20111aa2009-07-14 16:56:47 -0700257 mFrames.push_back(data);
Andreas Huberbe5c74f2009-10-13 17:08:31 -0700258 mFrameTimes.push_back(nowUs - mFirstFrameTimeUs);
Andreas Huber20111aa2009-07-14 16:56:47 -0700259 mFrameAvailableCondition.signal();
260}
261
Andreas Huber20111aa2009-07-14 16:56:47 -0700262} // namespace android