frameworks/base
Revisión | d5a403fef350592255cc99ee9b1db63973d6dc99 (tree) |
---|---|
Tiempo | 2010-02-27 17:47:44 |
Autor | Jeremy Chang <jeremy@0xla...> |
Commiter | Chih-Wei Huang |
bring up video recording function from 0xlab.org
@@ -8,7 +8,8 @@ include $(CLEAR_VARS) | ||
8 | 8 | |
9 | 9 | LOCAL_SRC_FILES:= \ |
10 | 10 | CameraHardware.cpp \ |
11 | - V4L2Camera.cpp | |
11 | + V4L2Camera.cpp \ | |
12 | + converter.cpp | |
12 | 13 | |
13 | 14 | LOCAL_CFLAGS += -Iexternal/jpeg |
14 | 15 |
@@ -1,5 +1,6 @@ | ||
1 | 1 | /* |
2 | 2 | ** |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
3 | 4 | ** Copyright 2008, The Android Open Source Project |
4 | 5 | ** |
5 | 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -19,15 +20,23 @@ | ||
19 | 20 | #include <utils/Log.h> |
20 | 21 | |
21 | 22 | #include "CameraHardware.h" |
23 | +#include "converter.h" | |
22 | 24 | #include <fcntl.h> |
23 | 25 | #include <sys/mman.h> |
24 | 26 | |
25 | 27 | #define VIDEO_DEVICE "/dev/video0" |
26 | -#define MIN_WIDTH 640 | |
27 | - | |
28 | -#define MIN_HEIGHT 480 | |
28 | +#define PREVIEW_WIDTH 352 | |
29 | +#define PREVIEW_HEIGHT 288 | |
30 | +#define PICTURE_WIDTH 1600 /* 2MP */ | |
31 | +#define PICTURE_HEIGHT 1200 /* 2MP */ | |
29 | 32 | #define PIXEL_FORMAT V4L2_PIX_FMT_YUYV |
30 | 33 | |
34 | +#include <cutils/properties.h> | |
35 | +#ifndef UNLIKELY | |
36 | +#define UNLIKELY(exp) (__builtin_expect( (exp) != 0, false )) | |
37 | +#endif | |
38 | +static int mDebugFps = 0; | |
39 | + | |
31 | 40 | namespace android { |
32 | 41 | |
33 | 42 | wp<CameraHardwareInterface> CameraHardware::singleton; |
@@ -37,7 +46,10 @@ CameraHardware::CameraHardware() | ||
37 | 46 | mHeap(0), |
38 | 47 | mPreviewHeap(0), |
39 | 48 | mRawHeap(0), |
40 | - mPreviewFrameSize(0), | |
49 | + mPreviewFrameSize(0), | |
50 | + mRecordingFrameSize(0), | |
51 | + mRecordingCallback(0), | |
52 | + mRecordingCallbackCookie(0), | |
41 | 53 | mRawPictureCallback(0), |
42 | 54 | mJpegPictureCallback(0), |
43 | 55 | mPictureCallbackCookie(0), |
@@ -45,24 +57,28 @@ CameraHardware::CameraHardware() | ||
45 | 57 | mPreviewCallbackCookie(0), |
46 | 58 | mAutoFocusCallback(0), |
47 | 59 | mAutoFocusCallbackCookie(0), |
48 | - mCurrentPreviewFrame(0), | |
49 | - previewStopped(true), | |
50 | - nQueued(0), | |
51 | - nDequeued(0) | |
60 | + previewStopped(true) | |
52 | 61 | { |
53 | 62 | initDefaultParameters(); |
63 | + /* whether prop "debug.camera.showfps" is enabled or not */ | |
64 | + char value[PROPERTY_VALUE_MAX]; | |
65 | + property_get("debug.camera.showfps", value, "0"); | |
66 | + mDebugFps = atoi(value); | |
67 | + LOGD_IF(mDebugFps, "showfps enabled"); | |
54 | 68 | } |
55 | 69 | |
56 | 70 | void CameraHardware::initDefaultParameters() |
57 | 71 | { |
58 | 72 | CameraParameters p; |
59 | 73 | |
60 | - p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT); | |
61 | - p.setPreviewFrameRate(15); | |
74 | + p.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
75 | + p.setPreviewFrameRate(DEFAULT_FRAME_RATE); | |
62 | 76 | p.setPreviewFormat("yuv422sp"); |
63 | - | |
64 | - p.setPictureSize(MIN_WIDTH, MIN_HEIGHT); | |
65 | 77 | p.setPictureFormat("jpeg"); |
78 | + p.setPictureSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
79 | + | |
80 | + p.set("jpeg-quality", "100"); // maximum quality | |
81 | + p.set("picture-size-values", "1600x1200,1024x768,640x480,352x288"); | |
66 | 82 | |
67 | 83 | if (setParameters(p) != NO_ERROR) { |
68 | 84 | LOGE("Failed to set default parameters?!"); |
@@ -76,7 +92,7 @@ CameraHardware::~CameraHardware() | ||
76 | 92 | |
77 | 93 | sp<IMemoryHeap> CameraHardware::getPreviewHeap() const |
78 | 94 | { |
79 | - return mHeap; | |
95 | + return mPreviewHeap; | |
80 | 96 | } |
81 | 97 | |
82 | 98 | sp<IMemoryHeap> CameraHardware::getRawHeap() const |
@@ -85,13 +101,59 @@ sp<IMemoryHeap> CameraHardware::getRawHeap() const | ||
85 | 101 | } |
86 | 102 | |
87 | 103 | // --------------------------------------------------------------------------- |
104 | +static void showFPS(const char *tag) | |
105 | +{ | |
106 | + static int mFrameCount = 0; | |
107 | + static int mLastFrameCount = 0; | |
108 | + static nsecs_t mLastFpsTime = 0; | |
109 | + static float mFps = 0; | |
110 | + mFrameCount++; | |
111 | + if (!(mFrameCount & 0x1F)) { | |
112 | + nsecs_t now = systemTime(); | |
113 | + nsecs_t diff = now - mLastFpsTime; | |
114 | + mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; | |
115 | + mLastFpsTime = now; | |
116 | + mLastFrameCount = mFrameCount; | |
117 | + LOGD("[%s] %d Frames, %f FPS", tag, mFrameCount, mFps); | |
118 | + } | |
119 | +} | |
88 | 120 | |
89 | 121 | int CameraHardware::previewThread() |
90 | 122 | { |
123 | + Mutex::Autolock lock(mPreviewLock); | |
91 | 124 | if (!previewStopped) { |
92 | - // Get preview frame | |
93 | - camera.GrabPreviewFrame(mHeap->getBase()); | |
94 | - mPreviewCallback(mBuffer, mPreviewCallbackCookie); | |
125 | + | |
126 | + camera.GrabRawFrame(mRawHeap->getBase()); | |
127 | + | |
128 | + if (mRecordingCallback) { | |
129 | + yuyv422_to_yuv420sp((unsigned char *)mRawHeap->getBase(), | |
130 | + (unsigned char *)mRecordingHeap->getBase(), | |
131 | + PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
132 | + nsecs_t timeStamp = systemTime(SYSTEM_TIME_MONOTONIC); | |
133 | + mRecordingCallback(timeStamp, mRecordingBuffer, mRecordingCallbackCookie); | |
134 | + | |
135 | + camera.convert((unsigned char *) mRawHeap->getBase(), | |
136 | + (unsigned char *) mPreviewHeap->getBase(), | |
137 | + PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
138 | + | |
139 | + if (UNLIKELY(mDebugFps)) { | |
140 | + showFPS("Recording"); | |
141 | + } | |
142 | + } | |
143 | + else { | |
144 | + camera.convert((unsigned char *) mRawHeap->getBase(), | |
145 | + (unsigned char *) mPreviewHeap->getBase(), | |
146 | + PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
147 | + | |
148 | + yuyv422_to_yuv420((unsigned char *)mRawHeap->getBase(), | |
149 | + (unsigned char *)mHeap->getBase(), | |
150 | + PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
151 | + mPreviewCallback(mBuffer, mPreviewCallbackCookie); | |
152 | + | |
153 | + if (UNLIKELY(mDebugFps)) { | |
154 | + showFPS("Preview"); | |
155 | + } | |
156 | + } | |
95 | 157 | } |
96 | 158 | |
97 | 159 | return NO_ERROR; |
@@ -104,16 +166,29 @@ status_t CameraHardware::startPreview(preview_callback cb, void* user) | ||
104 | 166 | Mutex::Autolock lock(mLock); |
105 | 167 | if (mPreviewThread != 0) { |
106 | 168 | //already running |
169 | + LOGD("startPreview: but already running"); | |
107 | 170 | return INVALID_OPERATION; |
108 | 171 | } |
109 | 172 | |
110 | - camera.Open(VIDEO_DEVICE, MIN_WIDTH, MIN_HEIGHT, PIXEL_FORMAT); | |
173 | + if (camera.Open(VIDEO_DEVICE, PREVIEW_WIDTH, PREVIEW_HEIGHT, PIXEL_FORMAT) < 0) { | |
174 | + LOGE("startPreview failed: cannot open device."); | |
175 | + return UNKNOWN_ERROR; | |
176 | + } | |
111 | 177 | |
112 | - mPreviewFrameSize = MIN_WIDTH * MIN_HEIGHT * 2; | |
178 | + mPreviewFrameSize = PREVIEW_WIDTH * PREVIEW_HEIGHT * 2; | |
113 | 179 | |
114 | 180 | mHeap = new MemoryHeapBase(mPreviewFrameSize); |
115 | 181 | mBuffer = new MemoryBase(mHeap, 0, mPreviewFrameSize); |
116 | 182 | |
183 | + mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize); | |
184 | + mPreviewBuffer = new MemoryBase(mPreviewHeap, 0, mPreviewFrameSize); | |
185 | + | |
186 | + mRecordingHeap = new MemoryHeapBase(mPreviewFrameSize); | |
187 | + mRecordingBuffer = new MemoryBase(mRecordingHeap, 0, mPreviewFrameSize); | |
188 | + | |
189 | + mRawHeap = new MemoryHeapBase(mPreviewFrameSize); | |
190 | + mRawBuffer = new MemoryBase(mRawHeap, 0, mPreviewFrameSize); | |
191 | + | |
117 | 192 | camera.Init(); |
118 | 193 | camera.StartStreaming(); |
119 | 194 |
@@ -161,20 +236,34 @@ bool CameraHardware::previewEnabled() | ||
161 | 236 | |
162 | 237 | status_t CameraHardware::startRecording(recording_callback cb, void* user) |
163 | 238 | { |
164 | - return UNKNOWN_ERROR; | |
239 | + LOGD("startRecording"); | |
240 | + mRecordingLock.lock(); | |
241 | + mRecordingCallback = cb; | |
242 | + mRecordingCallbackCookie = user; | |
243 | + mRecordingLock.unlock(); | |
244 | + return NO_ERROR; | |
245 | + | |
165 | 246 | } |
166 | 247 | |
167 | 248 | void CameraHardware::stopRecording() |
168 | 249 | { |
250 | + mRecordingLock.lock(); | |
251 | + mRecordingCallback = NULL; | |
252 | + mRecordingCallbackCookie = NULL; | |
253 | + mRecordingLock.unlock(); | |
169 | 254 | } |
170 | 255 | |
171 | 256 | bool CameraHardware::recordingEnabled() |
172 | 257 | { |
173 | - return false; | |
258 | + return mRecordingCallback !=0; | |
174 | 259 | } |
175 | 260 | |
176 | 261 | void CameraHardware::releaseRecordingFrame(const sp<IMemory>& mem) |
177 | 262 | { |
263 | + if (UNLIKELY(mDebugFps)) { | |
264 | + showFPS("Recording"); | |
265 | + } | |
266 | + return; | |
178 | 267 | } |
179 | 268 | |
180 | 269 | // --------------------------------------------------------------------------- |
@@ -219,44 +308,25 @@ status_t CameraHardware::autoFocus(autofocus_callback af_cb, | ||
219 | 308 | |
220 | 309 | int CameraHardware::pictureThread() |
221 | 310 | { |
222 | - unsigned char *frame; | |
223 | - int bufferSize; | |
224 | - int w,h; | |
225 | 311 | int ret; |
226 | - struct v4l2_buffer buffer; | |
227 | - struct v4l2_format format; | |
228 | - struct v4l2_buffer cfilledbuffer; | |
229 | - struct v4l2_requestbuffers creqbuf; | |
230 | - struct v4l2_capability cap; | |
231 | 312 | |
232 | 313 | if (mShutterCallback) |
233 | 314 | mShutterCallback(mPictureCallbackCookie); |
234 | 315 | |
235 | - mParameters.getPictureSize(&w, &h); | |
236 | - LOGD("Picture Size: Width = %d \t Height = %d", w, h); | |
237 | - | |
238 | - int width, height; | |
239 | - mParameters.getPictureSize(&width, &height); | |
240 | - camera.Open(VIDEO_DEVICE, MIN_WIDTH, MIN_HEIGHT, PIXEL_FORMAT); | |
241 | - camera.Init(); | |
242 | - camera.StartStreaming(); | |
243 | - | |
244 | - if (mRawPictureCallback) { | |
245 | - LOGD("mRawPictureCallback"); | |
246 | - | |
247 | -// mRawPictureCallback(camera.GrabRawFrame(), mPictureCallbackCookie); | |
316 | + sp<PreviewThread> previewThread; | |
317 | + Mutex::Autolock lock(mLock); | |
318 | + previewStopped = true; | |
319 | + previewThread = mPreviewThread; | |
320 | + if (previewThread != 0) { | |
321 | + previewThread->requestExitAndWait(); | |
248 | 322 | } |
249 | - | |
323 | + mPreviewThread.clear(); | |
324 | + // Grab the photo | |
250 | 325 | if (mJpegPictureCallback) { |
251 | - LOGD ("mJpegPictureCallback"); | |
252 | - | |
253 | 326 | mJpegPictureCallback(camera.GrabJpegFrame(), mPictureCallbackCookie); |
254 | 327 | } |
255 | - | |
256 | - camera.Uninit(); | |
257 | - camera.StopStreaming(); | |
258 | - camera.Close(); | |
259 | - | |
328 | + previewStopped = false; | |
329 | + mPreviewThread = new PreviewThread(this); | |
260 | 330 | return NO_ERROR; |
261 | 331 | } |
262 | 332 |
@@ -265,14 +335,10 @@ status_t CameraHardware::takePicture(shutter_callback shutter_cb, | ||
265 | 335 | jpeg_callback jpeg_cb, |
266 | 336 | void* user) |
267 | 337 | { |
268 | - stopPreview(); | |
269 | 338 | mShutterCallback = shutter_cb; |
270 | 339 | mRawPictureCallback = raw_cb; |
271 | 340 | mJpegPictureCallback = jpeg_cb; |
272 | 341 | mPictureCallbackCookie = user; |
273 | - //if (createThread(beginPictureThread, this) == false) | |
274 | - // return -1; | |
275 | - | |
276 | 342 | pictureThread(); |
277 | 343 | |
278 | 344 | return NO_ERROR; |
@@ -316,11 +382,13 @@ status_t CameraHardware::setParameters(const CameraParameters& params) | ||
316 | 382 | LOGD("PREVIEW SIZE: w=%d h=%d framerate=%d", w, h, framerate); |
317 | 383 | |
318 | 384 | params.getPictureSize(&w, &h); |
385 | + LOGD("requested size %d x %d", w, h); | |
319 | 386 | |
320 | 387 | mParameters = params; |
321 | 388 | |
322 | 389 | // Set to fixed sizes |
323 | - mParameters.setPreviewSize(MIN_WIDTH,MIN_HEIGHT); | |
390 | + mParameters.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
391 | + mParameters.setPictureSize(PREVIEW_WIDTH, PREVIEW_HEIGHT); | |
324 | 392 | |
325 | 393 | return NO_ERROR; |
326 | 394 | } |
@@ -330,7 +398,7 @@ CameraParameters CameraHardware::getParameters() const | ||
330 | 398 | CameraParameters params; |
331 | 399 | |
332 | 400 | { |
333 | - Mutex::Autolock lock(mLock); | |
401 | + Mutex::Autolock lock(mLock); | |
334 | 402 | params = mParameters; |
335 | 403 | } |
336 | 404 |
@@ -339,7 +407,6 @@ CameraParameters CameraHardware::getParameters() const | ||
339 | 407 | |
340 | 408 | void CameraHardware::release() |
341 | 409 | { |
342 | - close(camera_device); | |
343 | 410 | } |
344 | 411 | |
345 | 412 | sp<CameraHardwareInterface> CameraHardware::createInstance() |
@@ -1,5 +1,6 @@ | ||
1 | 1 | /* |
2 | 2 | ** |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
3 | 4 | ** Copyright 2008, The Android Open Source Project |
4 | 5 | ** |
5 | 6 | ** Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -24,7 +25,7 @@ | ||
24 | 25 | #include <utils/MemoryHeapBase.h> |
25 | 26 | #include <utils/threads.h> |
26 | 27 | |
27 | -#include <sys/ioctl.h> | |
28 | +#include <jpeglib.h> | |
28 | 29 | #include "V4L2Camera.h" |
29 | 30 | |
30 | 31 | namespace android { |
@@ -93,14 +94,17 @@ private: | ||
93 | 94 | int pictureThread(); |
94 | 95 | |
95 | 96 | mutable Mutex mLock; |
97 | + mutable Mutex mPreviewLock; | |
96 | 98 | |
97 | 99 | CameraParameters mParameters; |
98 | 100 | |
99 | - sp<MemoryHeapBase> mHeap; | |
100 | - sp<MemoryBase> mBuffer; | |
101 | + sp<MemoryHeapBase> mHeap; // format: 420 | |
102 | + sp<MemoryBase> mBuffer; | |
101 | 103 | |
102 | - sp<MemoryHeapBase> mPreviewHeap; | |
103 | - sp<MemoryHeapBase> mRawHeap; | |
104 | + sp<MemoryHeapBase> mPreviewHeap; // format: 565 | |
105 | + sp<MemoryBase> mPreviewBuffer; | |
106 | + sp<MemoryHeapBase> mRawHeap; // format: 422 | |
107 | + sp<MemoryBase> mRawBuffer; | |
104 | 108 | |
105 | 109 | bool mPreviewRunning; |
106 | 110 | int mPreviewFrameSize; |
@@ -110,7 +114,6 @@ private: | ||
110 | 114 | jpeg_callback mJpegPictureCallback; |
111 | 115 | void *mPictureCallbackCookie; |
112 | 116 | |
113 | - // protected by mLock | |
114 | 117 | sp<PreviewThread> mPreviewThread; |
115 | 118 | preview_callback mPreviewCallback; |
116 | 119 | void *mPreviewCallbackCookie; |
@@ -118,16 +121,16 @@ private: | ||
118 | 121 | autofocus_callback mAutoFocusCallback; |
119 | 122 | void *mAutoFocusCallbackCookie; |
120 | 123 | |
121 | - // only used from PreviewThread | |
122 | - int mCurrentPreviewFrame; | |
124 | + sp<MemoryHeapBase> mRecordingHeap; | |
125 | + sp<MemoryBase> mRecordingBuffer; | |
123 | 126 | |
124 | - void * framebuffer; | |
125 | - bool previewStopped; | |
126 | - int camera_device; | |
127 | - void* mem[4]; | |
128 | - int nQueued; | |
129 | - int nDequeued; | |
130 | - V4L2Camera camera; | |
127 | + Mutex mRecordingLock; | |
128 | + int mRecordingFrameSize; | |
129 | + recording_callback mRecordingCallback; | |
130 | + void *mRecordingCallbackCookie; | |
131 | + | |
132 | + bool previewStopped; | |
133 | + V4L2Camera camera; | |
131 | 134 | }; |
132 | 135 | |
133 | 136 | }; // namespace android |
@@ -1,11 +1,20 @@ | ||
1 | 1 | /* |
2 | - * This program is free software; you can redistribute it and/or modify | |
3 | - * it under the terms of the GNU General Public License as published by | |
4 | - * the Free Software Foundation; either version 2 of the License, or | |
5 | - * (at your option) any later version. | |
6 | - * Author: Niels Keeman nielskeeman@gmail.com | |
7 | - * | |
8 | - */ | |
2 | +** | |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
4 | +** Copyright 2008, The Android Open Source Project | |
5 | +** | |
6 | +** Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | +** you may not use this file except in compliance with the License. | |
8 | +** You may obtain a copy of the License at | |
9 | +** | |
10 | +** http://www.apache.org/licenses/LICENSE-2.0 | |
11 | +** | |
12 | +** Unless required by applicable law or agreed to in writing, software | |
13 | +** distributed under the License is distributed on an "AS IS" BASIS, | |
14 | +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | +** See the License for the specific language governing permissions and | |
16 | +** limitations under the License. | |
17 | +*/ | |
9 | 18 | |
10 | 19 | #define LOG_TAG "V4L2Camera" |
11 | 20 | #include <utils/Log.h> |
@@ -22,12 +31,12 @@ | ||
22 | 31 | |
23 | 32 | #include <linux/videodev.h> |
24 | 33 | |
25 | -#include "V4L2Camera.h" | |
26 | - | |
27 | -extern "C" { /* Android jpeglib.h missed extern "C" */ | |
28 | -#include <jpeglib.h> | |
34 | +extern "C" { | |
35 | + #include <jpeglib.h> | |
29 | 36 | } |
30 | 37 | |
38 | +#include "V4L2Camera.h" | |
39 | + | |
31 | 40 | namespace android { |
32 | 41 | |
33 | 42 | V4L2Camera::V4L2Camera () |
@@ -41,7 +50,7 @@ V4L2Camera::~V4L2Camera() | ||
41 | 50 | free(videoIn); |
42 | 51 | } |
43 | 52 | |
44 | -int V4L2Camera::Open (const char *device, int width, int height, int pixelformat) | |
53 | +int V4L2Camera::Open(const char *device, int width, int height, int pixelformat) | |
45 | 54 | { |
46 | 55 | int ret; |
47 | 56 |
@@ -82,6 +91,15 @@ int V4L2Camera::Open (const char *device, int width, int height, int pixelformat | ||
82 | 91 | return ret; |
83 | 92 | } |
84 | 93 | |
94 | + ret = init_parm(); | |
95 | + if (ret < 0) { | |
96 | + LOGE("Init_parm Failed: %s", strerror(errno)); | |
97 | + return ret; | |
98 | + } | |
99 | + | |
100 | + videoIn->width = videoIn->format.fmt.pix.width; | |
101 | + videoIn->height = videoIn->format.fmt.pix.height; | |
102 | + | |
85 | 103 | return 0; |
86 | 104 | } |
87 | 105 |
@@ -90,6 +108,8 @@ void V4L2Camera::Close () | ||
90 | 108 | close(fd); |
91 | 109 | } |
92 | 110 | |
111 | + | |
112 | +// Init mmap | |
93 | 113 | int V4L2Camera::Init() |
94 | 114 | { |
95 | 115 | int ret; |
@@ -143,7 +163,34 @@ int V4L2Camera::Init() | ||
143 | 163 | return 0; |
144 | 164 | } |
145 | 165 | |
146 | -void V4L2Camera::Uninit () | |
166 | +int V4L2Camera::init_parm() | |
167 | +{ | |
168 | + int ret; | |
169 | + int framerate; | |
170 | + struct v4l2_streamparm parm; | |
171 | + | |
172 | + framerate = DEFAULT_FRAME_RATE; | |
173 | + | |
174 | + parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
175 | + | |
176 | + ret = ioctl(fd, VIDIOC_G_PARM, &parm); | |
177 | + if(ret != 0) { | |
178 | + LOGE("VIDIOC_G_PARM fail...."); | |
179 | + return ret; | |
180 | + } | |
181 | + | |
182 | + parm.parm.capture.timeperframe.numerator = 1; | |
183 | + parm.parm.capture.timeperframe.denominator = framerate; | |
184 | + ret = ioctl(fd, VIDIOC_S_PARM, &parm); | |
185 | + if(ret != 0) { | |
186 | + LOGE("VIDIOC_S_PARM Fail...."); | |
187 | + return -1; | |
188 | + } | |
189 | + | |
190 | + return 0; | |
191 | +} | |
192 | + | |
193 | +void V4L2Camera::Uninit() | |
147 | 194 | { |
148 | 195 | int ret; |
149 | 196 |
@@ -220,16 +267,15 @@ void V4L2Camera::GrabPreviewFrame (void *previewBuffer) | ||
220 | 267 | /* DQ */ |
221 | 268 | ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf); |
222 | 269 | if (ret < 0) { |
223 | - //LOGE("GrabPreviewFrame: VIDIOC_DQBUF Failed"); | |
224 | - | |
270 | + LOGE("GrabPreviewFrame: VIDIOC_DQBUF Failed"); | |
225 | 271 | return; |
226 | 272 | } |
227 | 273 | nDequeued++; |
228 | 274 | |
229 | - memcpy (tmpBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused); | |
275 | + memcpy(tmpBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused); | |
230 | 276 | |
231 | - //convertYUYVtoYUV422SP((uint8_t *)tmpBuffer, (uint8_t *)previewBuffer, videoIn->width, videoIn->height); | |
232 | - convert((unsigned char *)tmpBuffer, (unsigned char *)previewBuffer, videoIn->width, videoIn->height); | |
277 | + convert((unsigned char *) tmpBuffer, (unsigned char *) previewBuffer, | |
278 | + videoIn->width, videoIn->height); | |
233 | 279 | |
234 | 280 | ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf); |
235 | 281 | if (ret < 0) { |
@@ -242,14 +288,49 @@ void V4L2Camera::GrabPreviewFrame (void *previewBuffer) | ||
242 | 288 | free(tmpBuffer); |
243 | 289 | } |
244 | 290 | |
245 | -sp<IMemory> V4L2Camera::GrabRawFrame () | |
291 | +void V4L2Camera::GrabRawFrame(void *previewBuffer) | |
292 | +{ | |
293 | + int ret; | |
294 | + | |
295 | + videoIn->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | |
296 | + videoIn->buf.memory = V4L2_MEMORY_MMAP; | |
297 | + | |
298 | + /* DQ */ | |
299 | + ret = ioctl(fd, VIDIOC_DQBUF, &videoIn->buf); | |
300 | + if (ret < 0) { | |
301 | + LOGE("GrabRawFrame: VIDIOC_DQBUF Failed"); | |
302 | + return; | |
303 | + } | |
304 | + nDequeued++; | |
305 | + | |
306 | + memcpy(previewBuffer, videoIn->mem[videoIn->buf.index], (size_t) videoIn->buf.bytesused); | |
307 | + | |
308 | + ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf); | |
309 | + if (ret < 0) { | |
310 | + LOGE("postGrabRawFrame: VIDIOC_QBUF Failed"); | |
311 | + return; | |
312 | + } | |
313 | + | |
314 | + nQueued++; | |
315 | +} | |
316 | + | |
317 | +int | |
318 | +V4L2Camera::savePicture(unsigned char *inputBuffer, const char * filename) | |
246 | 319 | { |
247 | - sp<MemoryHeapBase> memHeap = new MemoryHeapBase(videoIn->width * videoIn->height * 2); | |
248 | - sp<MemoryBase> memBase = new MemoryBase(memHeap, 0, videoIn->width * videoIn->height * 2); | |
320 | + FILE *output; | |
321 | + int fileSize; | |
322 | + int ret; | |
323 | + output = fopen(filename, "wb"); | |
324 | + | |
325 | + if (output == NULL) { | |
326 | + LOGE("GrabJpegFrame: Ouput file == NULL"); | |
327 | + return 0; | |
328 | + } | |
249 | 329 | |
250 | - // Not yet implemented, do I have to? | |
330 | + fileSize = saveYUYVtoJPEG(inputBuffer, videoIn->width, videoIn->height, output, 100); | |
251 | 331 | |
252 | - return memBase; | |
332 | + fclose(output); | |
333 | + return fileSize; | |
253 | 334 | } |
254 | 335 | |
255 | 336 | sp<IMemory> V4L2Camera::GrabJpegFrame () |
@@ -270,7 +351,7 @@ sp<IMemory> V4L2Camera::GrabJpegFrame () | ||
270 | 351 | } |
271 | 352 | nDequeued++; |
272 | 353 | |
273 | - LOGI("GrabJpegFrame: Generated a frame from capture device"); | |
354 | + fileSize = savePicture((unsigned char *)videoIn->mem[videoIn->buf.index], "/sdcard/tmp.jpg"); | |
274 | 355 | |
275 | 356 | /* Enqueue buffer */ |
276 | 357 | ret = ioctl(fd, VIDIOC_QBUF, &videoIn->buf); |
@@ -280,17 +361,6 @@ sp<IMemory> V4L2Camera::GrabJpegFrame () | ||
280 | 361 | } |
281 | 362 | nQueued++; |
282 | 363 | |
283 | - output = fopen("/sdcard/tmp.jpg", "wb"); | |
284 | - | |
285 | - if (output == NULL) { | |
286 | - LOGE("GrabJpegFrame: Ouput file == NULL"); | |
287 | - return NULL; | |
288 | - } | |
289 | - | |
290 | - fileSize = saveYUYVtoJPEG((unsigned char *)videoIn->mem[videoIn->buf.index], videoIn->width, videoIn->height, output, 85); | |
291 | - | |
292 | - fclose(output); | |
293 | - | |
294 | 364 | input = fopen("/sdcard/tmp.jpg", "rb"); |
295 | 365 | |
296 | 366 | if (input == NULL) |
@@ -324,8 +394,6 @@ int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int heigh | ||
324 | 394 | jpeg_create_compress (&cinfo); |
325 | 395 | jpeg_stdio_dest (&cinfo, file); |
326 | 396 | |
327 | - LOGI("JPEG PICTURE WIDTH AND HEIGHT: %dx%d", width, height); | |
328 | - | |
329 | 397 | cinfo.image_width = width; |
330 | 398 | cinfo.image_height = height; |
331 | 399 | cinfo.input_components = 3; |
@@ -380,6 +448,30 @@ int V4L2Camera::saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int heigh | ||
380 | 448 | return fileSize; |
381 | 449 | } |
382 | 450 | |
451 | +static inline void yuv_to_rgb16(unsigned char y, | |
452 | + unsigned char u, | |
453 | + unsigned char v, | |
454 | + unsigned char *rgb) | |
455 | +{ | |
456 | + register int r,g,b; | |
457 | + int rgb16; | |
458 | + | |
459 | + r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10; | |
460 | + g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u -128) ) >> 10; | |
461 | + b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10; | |
462 | + | |
463 | + r = r > 255 ? 255 : r < 0 ? 0 : r; | |
464 | + g = g > 255 ? 255 : g < 0 ? 0 : g; | |
465 | + b = b > 255 ? 255 : b < 0 ? 0 : b; | |
466 | + | |
467 | + rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0)); | |
468 | + | |
469 | + *rgb = (unsigned char)(rgb16 & 0xFF); | |
470 | + rgb++; | |
471 | + *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8); | |
472 | + | |
473 | +} | |
474 | + | |
383 | 475 | void V4L2Camera::convert(unsigned char *buf, unsigned char *rgb, int width, int height) |
384 | 476 | { |
385 | 477 | int x,y,z=0; |
@@ -398,36 +490,8 @@ void V4L2Camera::convert(unsigned char *buf, unsigned char *rgb, int width, int | ||
398 | 490 | yuv_to_rgb16(Y1, U, V, &rgb[y]); |
399 | 491 | yuv_to_rgb16(Y2, U, V, &rgb[y + 2]); |
400 | 492 | } |
401 | - | |
402 | 493 | } |
403 | 494 | |
404 | -void V4L2Camera::yuv_to_rgb16(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb) | |
405 | -{ | |
406 | - int r,g,b; | |
407 | - int z; | |
408 | - int rgb16; | |
409 | - | |
410 | - z = 0; | |
411 | - | |
412 | - r = 1.164 * (y - 16) + 1.596 * (v - 128); | |
413 | - g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u -128); | |
414 | - b = 1.164 * (y - 16) + 2.018 * (u - 128); | |
415 | - | |
416 | - if (r > 255) r = 255; | |
417 | - if (g > 255) g = 255; | |
418 | - if (b > 255) b = 255; | |
419 | - | |
420 | - if (r < 0) r = 0; | |
421 | - if (g < 0) g = 0; | |
422 | - if (b < 0) b = 0; | |
423 | - | |
424 | - rgb16 = (int)(((r >> 3)<<11) | ((g >> 2) << 5)| ((b >> 3) << 0)); | |
425 | - | |
426 | - *rgb = (unsigned char)(rgb16 & 0xFF); | |
427 | - rgb++; | |
428 | - *rgb = (unsigned char)((rgb16 & 0xFF00) >> 8); | |
429 | - | |
430 | -} | |
431 | 495 | |
432 | 496 | |
433 | 497 | }; // namespace android |
@@ -1,16 +1,26 @@ | ||
1 | 1 | /* |
2 | - * This program is free software; you can redistribute it and/or modify | |
3 | - * it under the terms of the GNU General Public License as published by | |
4 | - * the Free Software Foundation; either version 2 of the License, or | |
5 | - * (at your option) any later version. | |
6 | - * Author: Niels Keeman nielskeeman@gmail.com | |
7 | - * | |
8 | - */ | |
2 | +** | |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
4 | +** Copyright 2008, The Android Open Source Project | |
5 | +** | |
6 | +** Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | +** you may not use this file except in compliance with the License. | |
8 | +** You may obtain a copy of the License at | |
9 | +** | |
10 | +** http://www.apache.org/licenses/LICENSE-2.0 | |
11 | +** | |
12 | +** Unless required by applicable law or agreed to in writing, software | |
13 | +** distributed under the License is distributed on an "AS IS" BASIS, | |
14 | +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | +** See the License for the specific language governing permissions and | |
16 | +** limitations under the License. | |
17 | +*/ | |
9 | 18 | |
10 | 19 | #ifndef _V4L2CAMERA_H |
11 | 20 | #define _V4L2CAMERA_H |
12 | 21 | |
13 | 22 | #define NB_BUFFER 4 |
23 | +#define DEFAULT_FRAME_RATE 30 | |
14 | 24 | |
15 | 25 | #include <utils/MemoryBase.h> |
16 | 26 | #include <utils/MemoryHeapBase.h> |
@@ -41,14 +51,17 @@ public: | ||
41 | 51 | void Close (); |
42 | 52 | |
43 | 53 | int Init (); |
54 | + int init_parm(); | |
44 | 55 | void Uninit (); |
45 | 56 | |
46 | 57 | int StartStreaming (); |
47 | 58 | int StopStreaming (); |
48 | 59 | |
49 | 60 | void GrabPreviewFrame (void *previewBuffer); |
50 | - sp<IMemory> GrabRawFrame (); | |
61 | + void GrabRawFrame(void *previewBuffer); | |
51 | 62 | sp<IMemory> GrabJpegFrame (); |
63 | + int savePicture(unsigned char *inputBuffer, const char * filename); | |
64 | + void convert(unsigned char *buf, unsigned char *rgb, int width, int height); | |
52 | 65 | |
53 | 66 | private: |
54 | 67 | struct vdIn *videoIn; |
@@ -58,9 +71,6 @@ private: | ||
58 | 71 | int nDequeued; |
59 | 72 | |
60 | 73 | int saveYUYVtoJPEG (unsigned char *inputBuffer, int width, int height, FILE *file, int quality); |
61 | - | |
62 | - void convert(unsigned char *buf, unsigned char *rgb, int width, int height); | |
63 | - void yuv_to_rgb16(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb); | |
64 | 74 | }; |
65 | 75 | |
66 | 76 | }; // namespace android |
@@ -0,0 +1,261 @@ | ||
1 | +/* | |
2 | +** | |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
4 | +** Copyright 2008, The Android Open Source Project | |
5 | +** | |
6 | +** This work is based on yuvconverter project. | |
7 | +** | |
8 | +** Licensed under the Apache License, Version 2.0 (the "License"); | |
9 | +** you may not use this file except in compliance with the License. | |
10 | +** You may obtain a copy of the License at | |
11 | +** | |
12 | +** http://www.apache.org/licenses/LICENSE-2.0 | |
13 | +** | |
14 | +** Unless required by applicable law or agreed to in writing, software | |
15 | +** distributed under the License is distributed on an "AS IS" BASIS, | |
16 | +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
17 | +** See the License for the specific language governing permissions and | |
18 | +** limitations under the License. | |
19 | +*/ | |
20 | + | |
21 | +#include "converter.h" | |
22 | + | |
23 | +void | |
24 | +yuyv422_to_yuv420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height) | |
25 | +{ | |
26 | + unsigned char *ptrsrcy1, *ptrsrcy2; | |
27 | + unsigned char *ptrsrcy3, *ptrsrcy4; | |
28 | + unsigned char *ptrsrccb1, *ptrsrccb2; | |
29 | + unsigned char *ptrsrccb3, *ptrsrccb4; | |
30 | + unsigned char *ptrsrccr1, *ptrsrccr2; | |
31 | + unsigned char *ptrsrccr3, *ptrsrccr4; | |
32 | + int srcystride, srcccstride; | |
33 | + | |
34 | + ptrsrcy1 = bufsrc ; | |
35 | + ptrsrcy2 = bufsrc + (width<<1) ; | |
36 | + ptrsrcy3 = bufsrc + (width<<1)*2 ; | |
37 | + ptrsrcy4 = bufsrc + (width<<1)*3 ; | |
38 | + | |
39 | + ptrsrccb1 = bufsrc + 1; | |
40 | + ptrsrccb2 = bufsrc + (width<<1) + 1; | |
41 | + ptrsrccb3 = bufsrc + (width<<1)*2 + 1; | |
42 | + ptrsrccb4 = bufsrc + (width<<1)*3 + 1; | |
43 | + | |
44 | + ptrsrccr1 = bufsrc + 3; | |
45 | + ptrsrccr2 = bufsrc + (width<<1) + 3; | |
46 | + ptrsrccr3 = bufsrc + (width<<1)*2 + 3; | |
47 | + ptrsrccr4 = bufsrc + (width<<1)*3 + 3; | |
48 | + | |
49 | + srcystride = (width<<1)*3; | |
50 | + srcccstride = (width<<1)*3; | |
51 | + | |
52 | + unsigned char *ptrdesty1, *ptrdesty2; | |
53 | + unsigned char *ptrdesty3, *ptrdesty4; | |
54 | + unsigned char *ptrdestcb1, *ptrdestcb2; | |
55 | + unsigned char *ptrdestcr1, *ptrdestcr2; | |
56 | + int destystride, destccstride; | |
57 | + | |
58 | + ptrdesty1 = bufdest; | |
59 | + ptrdesty2 = bufdest + width; | |
60 | + ptrdesty3 = bufdest + width*2; | |
61 | + ptrdesty4 = bufdest + width*3; | |
62 | + | |
63 | + ptrdestcb1 = bufdest + width*height; | |
64 | + ptrdestcb2 = bufdest + width*height + (width>>1); | |
65 | + | |
66 | + ptrdestcr1 = bufdest + width*height + ((width*height) >> 2); | |
67 | + ptrdestcr2 = bufdest + width*height + ((width*height) >> 2) + (width>>1); | |
68 | + | |
69 | + destystride = (width)*3; | |
70 | + destccstride = (width>>1); | |
71 | + | |
72 | + int i, j; | |
73 | + | |
74 | + for(j=0; j<(height/4); j++) | |
75 | + { | |
76 | + for(i=0;i<(width/2);i++) | |
77 | + { | |
78 | + (*ptrdesty1++) = (*ptrsrcy1); | |
79 | + (*ptrdesty2++) = (*ptrsrcy2); | |
80 | + (*ptrdesty3++) = (*ptrsrcy3); | |
81 | + (*ptrdesty4++) = (*ptrsrcy4); | |
82 | + | |
83 | + ptrsrcy1 += 2; | |
84 | + ptrsrcy2 += 2; | |
85 | + ptrsrcy3 += 2; | |
86 | + ptrsrcy4 += 2; | |
87 | + | |
88 | + (*ptrdesty1++) = (*ptrsrcy1); | |
89 | + (*ptrdesty2++) = (*ptrsrcy2); | |
90 | + (*ptrdesty3++) = (*ptrsrcy3); | |
91 | + (*ptrdesty4++) = (*ptrsrcy4); | |
92 | + | |
93 | + ptrsrcy1 += 2; | |
94 | + ptrsrcy2 += 2; | |
95 | + ptrsrcy3 += 2; | |
96 | + ptrsrcy4 += 2; | |
97 | + | |
98 | + (*ptrdestcb1++) = (*ptrsrccb1); | |
99 | + (*ptrdestcb2++) = (*ptrsrccb3); | |
100 | + | |
101 | + ptrsrccb1 += 4; | |
102 | + ptrsrccb3 += 4; | |
103 | + | |
104 | + (*ptrdestcr1++) = (*ptrsrccr1); | |
105 | + (*ptrdestcr2++) = (*ptrsrccr3); | |
106 | + | |
107 | + ptrsrccr1 += 4; | |
108 | + ptrsrccr3 += 4; | |
109 | + | |
110 | + } | |
111 | + | |
112 | + | |
113 | + /* Update src pointers */ | |
114 | + ptrsrcy1 += srcystride; | |
115 | + ptrsrcy2 += srcystride; | |
116 | + ptrsrcy3 += srcystride; | |
117 | + ptrsrcy4 += srcystride; | |
118 | + | |
119 | + ptrsrccb1 += srcccstride; | |
120 | + ptrsrccb3 += srcccstride; | |
121 | + | |
122 | + ptrsrccr1 += srcccstride; | |
123 | + ptrsrccr3 += srcccstride; | |
124 | + | |
125 | + | |
126 | + /* Update dest pointers */ | |
127 | + ptrdesty1 += destystride; | |
128 | + ptrdesty2 += destystride; | |
129 | + ptrdesty3 += destystride; | |
130 | + ptrdesty4 += destystride; | |
131 | + | |
132 | + ptrdestcb1 += destccstride; | |
133 | + ptrdestcb2 += destccstride; | |
134 | + | |
135 | + ptrdestcr1 += destccstride; | |
136 | + ptrdestcr2 += destccstride; | |
137 | + | |
138 | + } | |
139 | +} | |
140 | + | |
141 | +void | |
142 | +yuyv422_to_yuv420sp(unsigned char *bufsrc, unsigned char *bufdest, int width, int height) | |
143 | +{ | |
144 | + unsigned char *ptrsrcy1, *ptrsrcy2; | |
145 | + unsigned char *ptrsrcy3, *ptrsrcy4; | |
146 | + unsigned char *ptrsrccb1, *ptrsrccb2; | |
147 | + unsigned char *ptrsrccb3, *ptrsrccb4; | |
148 | + unsigned char *ptrsrccr1, *ptrsrccr2; | |
149 | + unsigned char *ptrsrccr3, *ptrsrccr4; | |
150 | + int srcystride, srcccstride; | |
151 | + | |
152 | + ptrsrcy1 = bufsrc ; | |
153 | + ptrsrcy2 = bufsrc + (width<<1) ; | |
154 | + ptrsrcy3 = bufsrc + (width<<1)*2 ; | |
155 | + ptrsrcy4 = bufsrc + (width<<1)*3 ; | |
156 | + | |
157 | + ptrsrccb1 = bufsrc + 1; | |
158 | + ptrsrccb2 = bufsrc + (width<<1) + 1; | |
159 | + ptrsrccb3 = bufsrc + (width<<1)*2 + 1; | |
160 | + ptrsrccb4 = bufsrc + (width<<1)*3 + 1; | |
161 | + | |
162 | + ptrsrccr1 = bufsrc + 3; | |
163 | + ptrsrccr2 = bufsrc + (width<<1) + 3; | |
164 | + ptrsrccr3 = bufsrc + (width<<1)*2 + 3; | |
165 | + ptrsrccr4 = bufsrc + (width<<1)*3 + 3; | |
166 | + | |
167 | + srcystride = (width<<1)*3; | |
168 | + srcccstride = (width<<1)*3; | |
169 | + | |
170 | + unsigned char *ptrdesty1, *ptrdesty2; | |
171 | + unsigned char *ptrdesty3, *ptrdesty4; | |
172 | + unsigned char *ptrdestcb1, *ptrdestcb2; | |
173 | + unsigned char *ptrdestcr1, *ptrdestcr2; | |
174 | + int destystride, destccstride; | |
175 | + | |
176 | + ptrdesty1 = bufdest; | |
177 | + ptrdesty2 = bufdest + width; | |
178 | + ptrdesty3 = bufdest + width*2; | |
179 | + ptrdesty4 = bufdest + width*3; | |
180 | + | |
181 | + ptrdestcb1 = bufdest + width*height; | |
182 | + ptrdestcb2 = bufdest + width*height + width; | |
183 | + | |
184 | + ptrdestcr1 = bufdest + width*height + 1; | |
185 | + ptrdestcr2 = bufdest + width*height + width + 1; | |
186 | + | |
187 | + destystride = (width)*3; | |
188 | + destccstride = width; | |
189 | + | |
190 | + int i, j; | |
191 | + | |
192 | + for(j=0; j<(height/4); j++) | |
193 | + { | |
194 | + for(i=0;i<(width/2);i++) | |
195 | + { | |
196 | + (*ptrdesty1++) = (*ptrsrcy1); | |
197 | + (*ptrdesty2++) = (*ptrsrcy2); | |
198 | + (*ptrdesty3++) = (*ptrsrcy3); | |
199 | + (*ptrdesty4++) = (*ptrsrcy4); | |
200 | + | |
201 | + ptrsrcy1 += 2; | |
202 | + ptrsrcy2 += 2; | |
203 | + ptrsrcy3 += 2; | |
204 | + ptrsrcy4 += 2; | |
205 | + | |
206 | + (*ptrdesty1++) = (*ptrsrcy1); | |
207 | + (*ptrdesty2++) = (*ptrsrcy2); | |
208 | + (*ptrdesty3++) = (*ptrsrcy3); | |
209 | + (*ptrdesty4++) = (*ptrsrcy4); | |
210 | + | |
211 | + ptrsrcy1 += 2; | |
212 | + ptrsrcy2 += 2; | |
213 | + ptrsrcy3 += 2; | |
214 | + ptrsrcy4 += 2; | |
215 | + | |
216 | + (*ptrdestcb1) = (*ptrsrccb1); | |
217 | + (*ptrdestcb2) = (*ptrsrccb3); | |
218 | + ptrdestcb1 += 2; | |
219 | + ptrdestcb2 += 2; | |
220 | + | |
221 | + ptrsrccb1 += 4; | |
222 | + ptrsrccb3 += 4; | |
223 | + | |
224 | + (*ptrdestcr1) = (*ptrsrccr1); | |
225 | + (*ptrdestcr2) = (*ptrsrccr3); | |
226 | + ptrdestcr1 += 2; | |
227 | + ptrdestcr2 += 2; | |
228 | + | |
229 | + ptrsrccr1 += 4; | |
230 | + ptrsrccr3 += 4; | |
231 | + | |
232 | + } | |
233 | + | |
234 | + | |
235 | + /* Update src pointers */ | |
236 | + ptrsrcy1 += srcystride; | |
237 | + ptrsrcy2 += srcystride; | |
238 | + ptrsrcy3 += srcystride; | |
239 | + ptrsrcy4 += srcystride; | |
240 | + | |
241 | + ptrsrccb1 += srcccstride; | |
242 | + ptrsrccb3 += srcccstride; | |
243 | + | |
244 | + ptrsrccr1 += srcccstride; | |
245 | + ptrsrccr3 += srcccstride; | |
246 | + | |
247 | + | |
248 | + /* Update dest pointers */ | |
249 | + ptrdesty1 += destystride; | |
250 | + ptrdesty2 += destystride; | |
251 | + ptrdesty3 += destystride; | |
252 | + ptrdesty4 += destystride; | |
253 | + | |
254 | + ptrdestcb1 += destccstride; | |
255 | + ptrdestcb2 += destccstride; | |
256 | + | |
257 | + ptrdestcr1 += destccstride; | |
258 | + ptrdestcr2 += destccstride; | |
259 | + | |
260 | + } | |
261 | +} |
@@ -0,0 +1,25 @@ | ||
1 | +/* | |
2 | +** | |
3 | +** Copyright (C) 2009 0xlab.org - http://0xlab.org/ | |
4 | +** Copyright 2008, The Android Open Source Project | |
5 | +** | |
6 | +** Licensed under the Apache License, Version 2.0 (the "License"); | |
7 | +** you may not use this file except in compliance with the License. | |
8 | +** You may obtain a copy of the License at | |
9 | +** | |
10 | +** http://www.apache.org/licenses/LICENSE-2.0 | |
11 | +** | |
12 | +** Unless required by applicable law or agreed to in writing, software | |
13 | +** distributed under the License is distributed on an "AS IS" BASIS, | |
14 | +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | +** See the License for the specific language governing permissions and | |
16 | +** limitations under the License. | |
17 | +*/ | |
18 | + | |
19 | +#ifndef CONVERTER_H | |
20 | +#define CONVERTER_H | |
21 | + | |
22 | +void yuyv422_to_yuv420(unsigned char *bufsrc, unsigned char *bufdest, int width, int height); | |
23 | +void yuyv422_to_yuv420sp(unsigned char *bufsrc, unsigned char *bufdest, int width, int height); | |
24 | + | |
25 | +#endif |