blob: 772154cc4d807bb03a811dae2cab86179cbde4df
1 | /* |
2 | * Copyright (C) 2013 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 | |
18 | //reinclude because of a bug with the log macros |
19 | //#define LOG_NDEBUG 0 |
20 | #define LOG_TAG "V4L2VINSOURCE" |
21 | #include <utils/Log.h> |
22 | #include <utils/String8.h> |
23 | |
24 | #include <signal.h> |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <fcntl.h> |
29 | #include <unistd.h> |
30 | #include <errno.h> |
31 | #include <sys/ioctl.h> |
32 | #include <sys/mman.h> |
33 | #include <sys/select.h> |
34 | #include <linux/videodev2.h> |
35 | #include <sys/time.h> |
36 | |
37 | #include <cutils/properties.h> |
38 | #include <sys/types.h> |
39 | #include <sys/stat.h> |
40 | |
41 | #include "v4l2_vdin.h" |
42 | #include <ui/GraphicBufferMapper.h> |
43 | #include <ui/GraphicBuffer.h> |
44 | #include <linux/videodev2.h> |
45 | |
46 | namespace android { |
47 | |
48 | #define V4L2_ROTATE_ID 0x980922 |
49 | |
50 | #ifndef container_of |
51 | #define container_of(ptr, type, member) ({ \ |
52 | const typeof(((type *) 0)->member) *__mptr = (ptr); \ |
53 | (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); }) |
54 | #endif |
55 | |
56 | #define BOUNDRY 32 |
57 | |
58 | #define ALIGN(x) (x + (BOUNDRY) - 1)& ~((BOUNDRY) - 1) |
59 | |
60 | static size_t getBufSize(int format, int width, int height) |
61 | { |
62 | size_t buf_size = 0; |
63 | |
64 | switch(format){ |
65 | case V4L2_PIX_FMT_YVU420: |
66 | case V4L2_PIX_FMT_NV21: |
67 | buf_size = width * height * 3 / 2; |
68 | break; |
69 | case V4L2_PIX_FMT_YUYV: |
70 | case V4L2_PIX_FMT_RGB565: |
71 | buf_size = width * height * 2; |
72 | break; |
73 | case V4L2_PIX_FMT_RGB24: |
74 | buf_size = width * height * 3; |
75 | break; |
76 | case V4L2_PIX_FMT_RGB32: |
77 | buf_size = width * height * 4; |
78 | break; |
79 | default: |
80 | ALOGE("Invalid format"); |
81 | buf_size = 0; |
82 | } |
83 | return buf_size; |
84 | } |
85 | |
86 | static int getNativeWindowFormat(int format) |
87 | { |
88 | int nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I; |
89 | |
90 | switch(format){ |
91 | case V4L2_PIX_FMT_YVU420: |
92 | nativeFormat = HAL_PIXEL_FORMAT_YV12; |
93 | break; |
94 | case V4L2_PIX_FMT_NV21: |
95 | nativeFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
96 | break; |
97 | case V4L2_PIX_FMT_YUYV: |
98 | nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I; |
99 | break; |
100 | case V4L2_PIX_FMT_RGB565: |
101 | nativeFormat = HAL_PIXEL_FORMAT_RGB_565; |
102 | break; |
103 | case V4L2_PIX_FMT_RGB24: |
104 | nativeFormat = HAL_PIXEL_FORMAT_RGB_888; |
105 | break; |
106 | case V4L2_PIX_FMT_RGB32: |
107 | nativeFormat = HAL_PIXEL_FORMAT_RGBA_8888; |
108 | break; |
109 | default: |
110 | ALOGE("Invalid format,Use default format"); |
111 | } |
112 | return nativeFormat; |
113 | } |
114 | |
115 | |
116 | static ANativeWindowBuffer* handle_to_buffer(buffer_handle_t *handle) |
117 | { |
118 | return container_of(handle, ANativeWindowBuffer, handle); |
119 | } |
120 | |
121 | vdin_screen_source::vdin_screen_source() |
122 | : mCameraHandle(-1), |
123 | mVideoInfo(NULL) |
124 | { |
125 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
126 | } |
127 | |
128 | int vdin_screen_source::init(){ |
129 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
130 | mCameraHandle = open("/dev/video11", O_RDWR| O_NONBLOCK); |
131 | if (mCameraHandle < 0) |
132 | { |
133 | ALOGE("[%s %d] mCameraHandle:%x [%s]", __FUNCTION__, __LINE__, mCameraHandle,strerror(errno)); |
134 | return -1; |
135 | } |
136 | mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo)); |
137 | if (mVideoInfo == NULL) |
138 | { |
139 | ALOGE("[%s %d] no memory for mVideoInfo", __FUNCTION__, __LINE__); |
140 | close(mCameraHandle); |
141 | return NO_MEMORY; |
142 | } |
143 | mBufferCount = 4; |
144 | mPixelFormat = V4L2_PIX_FMT_NV21; |
145 | mNativeWindowPixelFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
146 | mFrameWidth = 1280; |
147 | mFrameHeight = 720; |
148 | mBufferSize = mFrameWidth * mFrameHeight * 3/2; |
149 | mSetStateCB = NULL; |
150 | mState = STOP; |
151 | mANativeWindow = NULL; |
152 | mFrameType = 0; |
153 | mWorkThread = NULL; |
154 | mDataCB = NULL; |
155 | mOpen = false; |
156 | return NO_ERROR; |
157 | } |
158 | |
159 | vdin_screen_source::~vdin_screen_source() |
160 | { |
161 | if (mVideoInfo) |
162 | free (mVideoInfo); |
163 | if (mCameraHandle >= 0) |
164 | close(mCameraHandle); |
165 | } |
166 | |
167 | int vdin_screen_source::start_v4l2_device() |
168 | { |
169 | int ret = -1; |
170 | |
171 | ALOGV("[%s %d] mCameraHandle:%x", __FUNCTION__, __LINE__, mCameraHandle); |
172 | |
173 | ioctl(mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap); |
174 | |
175 | mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
176 | mVideoInfo->rb.memory = V4L2_MEMORY_MMAP; |
177 | mVideoInfo->rb.count = mBufferCount; |
178 | |
179 | ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb); |
180 | |
181 | if (ret < 0) { |
182 | ALOGE("[%s %d] VIDIOC_REQBUFS:%d mCameraHandle:%x", __FUNCTION__, __LINE__, ret, mCameraHandle); |
183 | return ret; |
184 | } |
185 | |
186 | for (int i = 0; i < mBufferCount; i++) { |
187 | memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer)); |
188 | |
189 | mVideoInfo->buf.index = i; |
190 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
191 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
192 | |
193 | ret = ioctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf); |
194 | if (ret < 0) { |
195 | ALOGE("[%s %d]VIDIOC_QUERYBUF %d failed", __FUNCTION__, __LINE__, i); |
196 | return ret; |
197 | } |
198 | mVideoInfo->canvas[i] = mVideoInfo->buf.reserved; |
199 | mVideoInfo->mem[i] = (long *)mmap (0, mVideoInfo->buf.length, PROT_READ | PROT_WRITE, |
200 | MAP_SHARED, mCameraHandle, mVideoInfo->buf.m.offset); |
201 | |
202 | if (mVideoInfo->mem[i] == MAP_FAILED) { |
203 | ALOGE("[%s %d] MAP_FAILED", __FUNCTION__, __LINE__); |
204 | return -1; |
205 | } |
206 | mVideoInfo->refcount[i] = 0; |
207 | mBufs.add(mVideoInfo->mem[i],i); |
208 | } |
209 | ALOGV("[%s %d] VIDIOC_QUERYBUF successful", __FUNCTION__, __LINE__); |
210 | |
211 | for (int i = 0; i < mBufferCount; i++) { |
212 | mVideoInfo->buf.index = i; |
213 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
214 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
215 | ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf); |
216 | if (ret < 0) { |
217 | ALOGE("VIDIOC_QBUF Failed"); |
218 | return -1; |
219 | } |
220 | } |
221 | enum v4l2_buf_type bufType; |
222 | bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
223 | |
224 | ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType); |
225 | |
226 | ALOGV("[%s %d] VIDIOC_STREAMON:%x", __FUNCTION__, __LINE__, ret); |
227 | return ret; |
228 | } |
229 | |
230 | int vdin_screen_source::stop_v4l2_device() |
231 | { |
232 | ALOGE("%s %d", __FUNCTION__, __LINE__); |
233 | int ret; |
234 | enum v4l2_buf_type bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
235 | |
236 | ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType); |
237 | if (ret < 0) { |
238 | ALOGE("StopStreaming: Unable to stop capture: %s", strerror(errno)); |
239 | } |
240 | for (int i = 0; i < mBufferCount; i++) { |
241 | if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) { |
242 | ALOGE("Unmap failed"); |
243 | } |
244 | } |
245 | return ret; |
246 | } |
247 | int vdin_screen_source::start() |
248 | { |
249 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
250 | int ret; |
251 | if(mOpen == true){ |
252 | ALOGI("already open"); |
253 | return NO_ERROR; |
254 | } |
255 | |
256 | ret = start_v4l2_device(); |
257 | if(ret != NO_ERROR){ |
258 | ALOGE("Start v4l2 device failed:%d",ret); |
259 | return ret; |
260 | } |
261 | if(mFrameType & NATIVE_WINDOW_DATA){ |
262 | ret = init_native_window(); |
263 | if(ret != NO_ERROR){ |
264 | ALOGE("Init Native Window Failed:%d",ret); |
265 | return ret; |
266 | } |
267 | } |
268 | if(mFrameType & NATIVE_WINDOW_DATA || mFrameType & CALL_BACK_DATA){ |
269 | ALOGD("Create Work Thread"); |
270 | mWorkThread = new WorkThread(this); |
271 | } |
272 | if(mSetStateCB != NULL) |
273 | mSetStateCB(START); |
274 | mState = START; |
275 | mOpen = true; |
276 | ALOGV("%s %d ret:%d", __FUNCTION__, __LINE__, ret); |
277 | return NO_ERROR; |
278 | } |
279 | |
280 | int vdin_screen_source::pause() |
281 | { |
282 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
283 | mState = PAUSE; |
284 | if(mSetStateCB != NULL) |
285 | mSetStateCB(PAUSE); |
286 | return NO_ERROR; |
287 | } |
288 | int vdin_screen_source::stop() |
289 | { |
290 | ALOGE("!!!!!!!!!%s %d", __FUNCTION__, __LINE__); |
291 | int ret; |
292 | mState = STOPING; |
293 | |
294 | if(mWorkThread != NULL){ |
295 | mWorkThread->requestExitAndWait(); |
296 | mWorkThread.clear(); |
297 | } |
298 | |
299 | enum v4l2_buf_type bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
300 | |
301 | ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType); |
302 | if (ret < 0) { |
303 | ALOGE("StopStreaming: Unable to stop capture: %s", strerror(errno)); |
304 | } |
305 | for (int i = 0; i < mBufferCount; i++){ |
306 | if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) |
307 | ALOGE("Unmap failed"); |
308 | } |
309 | |
310 | mBufferCount = 0; |
311 | mState = STOP; |
312 | if(mSetStateCB != NULL) |
313 | mSetStateCB(STOP); |
314 | mOpen = false; |
315 | return ret; |
316 | } |
317 | |
318 | int vdin_screen_source::set_state_callback(olStateCB callback) |
319 | { |
320 | if (!callback){ |
321 | ALOGE("NULL state callback pointer"); |
322 | return BAD_VALUE; |
323 | } |
324 | mSetStateCB = callback; |
325 | return NO_ERROR; |
326 | } |
327 | |
328 | int vdin_screen_source::set_preview_window(ANativeWindow* window) |
329 | { |
330 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
331 | if(mOpen == true) |
332 | return NO_ERROR; |
333 | //can work without a valid window object ? |
334 | if (window == NULL){ |
335 | ALOGD("NULL window object passed to ScreenSource"); |
336 | if(mWorkThread != NULL){ |
337 | mWorkThread->requestExitAndWait(); |
338 | mWorkThread.clear(); |
339 | } |
340 | mFrameType &= ~NATIVE_WINDOW_DATA; |
341 | return NO_ERROR; |
342 | } |
343 | mFrameType |= NATIVE_WINDOW_DATA; |
344 | mANativeWindow = window; |
345 | return NO_ERROR; |
346 | } |
347 | |
348 | int vdin_screen_source::set_data_callback(app_data_callback callback, void* user) |
349 | { |
350 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
351 | if (callback == NULL){ |
352 | ALOGE("NULL data callback pointer"); |
353 | return BAD_VALUE; |
354 | } |
355 | mDataCB = callback; |
356 | mUser = user; |
357 | mFrameType |= CALL_BACK_DATA; |
358 | return NO_ERROR; |
359 | } |
360 | |
361 | int vdin_screen_source::get_format() |
362 | { |
363 | return mPixelFormat; |
364 | } |
365 | |
366 | int vdin_screen_source::set_format(int width, int height, int color_format) |
367 | { |
368 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
369 | if(mOpen == true) |
370 | return NO_ERROR; |
371 | int ret; |
372 | mVideoInfo->width = ALIGN(width); |
373 | mVideoInfo->height = height; |
374 | mVideoInfo->framesizeIn = (mVideoInfo->width * mVideoInfo->height << 3); //note color format |
375 | mVideoInfo->formatIn = color_format; |
376 | |
377 | mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
378 | mVideoInfo->format.fmt.pix.width = ALIGN(width); |
379 | mVideoInfo->format.fmt.pix.height = height; |
380 | mVideoInfo->format.fmt.pix.pixelformat = color_format; |
381 | mPixelFormat = color_format; |
382 | mNativeWindowPixelFormat = getNativeWindowFormat(color_format); |
383 | mFrameWidth = ALIGN(width); |
384 | mFrameHeight = height; |
385 | mBufferSize = getBufSize(color_format, mFrameWidth, mFrameHeight); |
386 | ALOGD("mFrameWidth:%d,mFrameHeight:%d",mFrameWidth,mFrameHeight); |
387 | ALOGD("mPixelFormat:%x,mNativeWindowPixelFormat:%x,mBufferSize:%d",mPixelFormat,mNativeWindowPixelFormat,mBufferSize); |
388 | ret = ioctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format); |
389 | if (ret < 0) { |
390 | ALOGE("[%s %d]VIDIOC_S_FMT %d", __FUNCTION__, __LINE__, ret); |
391 | return ret; |
392 | } |
393 | return ret; |
394 | } |
395 | |
396 | int vdin_screen_source::set_rotation(int degree) |
397 | { |
398 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
399 | |
400 | int ret = 0; |
401 | struct v4l2_control ctl; |
402 | |
403 | if(mCameraHandle<0) |
404 | return -1; |
405 | |
406 | if((degree!=0)&&(degree!=90)&&(degree!=180)&&(degree!=270)){ |
407 | ALOGE("Set rotate value invalid: %d.", degree); |
408 | return -1; |
409 | } |
410 | |
411 | memset( &ctl, 0, sizeof(ctl)); |
412 | ctl.value=degree; |
413 | ctl.id = V4L2_ROTATE_ID; |
414 | ret = ioctl(mCameraHandle, VIDIOC_S_CTRL, &ctl); |
415 | |
416 | if(ret<0){ |
417 | ALOGE("Set rotate value fail: %s. ret=%d", strerror(errno),ret); |
418 | } |
419 | return ret ; |
420 | } |
421 | |
422 | int vdin_screen_source::set_crop(int x, int y, int width, int height) |
423 | { |
424 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
425 | if (NULL == mANativeWindow.get()) |
426 | return BAD_VALUE; |
427 | |
428 | int err = NO_ERROR; |
429 | android_native_rect_t crop = { x, y, x + width - 1, y + height - 1 }; |
430 | err = native_window_set_crop(mANativeWindow.get(), &crop); |
431 | if (err != 0) { |
432 | ALOGW("Failed to set crop!"); |
433 | return err; |
434 | } |
435 | return NO_ERROR; |
436 | } |
437 | |
438 | int vdin_screen_source::set_frame_rate(int frameRate) |
439 | { |
440 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
441 | int ret = 0; |
442 | struct v4l2_control ctl; |
443 | |
444 | if(mCameraHandle<0) |
445 | return -1; |
446 | |
447 | struct v4l2_streamparm sparm; |
448 | memset(&sparm, 0, sizeof( sparm )); |
449 | sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//stream_flag; |
450 | sparm.parm.output.timeperframe.denominator = frameRate; |
451 | sparm.parm.output.timeperframe.numerator = 1; |
452 | |
453 | ret = ioctl(mCameraHandle, VIDIOC_S_PARM, &sparm); |
454 | if(ret < 0){ |
455 | ALOGE("Set frame rate fail: %s. ret=%d", strerror(errno),ret); |
456 | } |
457 | return ret ; |
458 | } |
459 | |
460 | int vdin_screen_source::set_amlvideo2_crop(int x, int y, int width, int height) |
461 | { |
462 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
463 | int ret = 0; |
464 | |
465 | struct v4l2_crop crop; |
466 | memset(&crop, 0, sizeof(struct v4l2_crop)); |
467 | |
468 | crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
469 | crop.c.left = x; |
470 | crop.c.top = y; |
471 | crop.c.width = width; |
472 | crop.c.height = height; |
473 | ret = ioctl(mCameraHandle, VIDIOC_S_CROP, &crop); |
474 | if (ret) { |
475 | ALOGE("Set frame rate fail: %s. ret=%d", strerror(errno),ret); |
476 | } |
477 | |
478 | return ret ; |
479 | } |
480 | |
481 | int vdin_screen_source::set_source_type(int sourceType) |
482 | { |
483 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
484 | int ret = 0; |
485 | |
486 | ret = ioctl(mCameraHandle, VIDIOC_S_INPUT, &sourceType); |
487 | if(ret < 0){ |
488 | ALOGE("Set source type fail: %s. ret:%d", strerror(errno),ret); |
489 | } |
490 | return ret; |
491 | } |
492 | |
493 | int vdin_screen_source::set_port_type(int sourceType) |
494 | { |
495 | ALOGD("[%s %d]", __FUNCTION__, __LINE__); |
496 | int ret = 0; |
497 | unsigned int portType = (unsigned int)sourceType; |
498 | ALOGE("portType:%d",portType); |
499 | ret = ioctl(mCameraHandle, VIDIOC_S_INPUT, &portType); |
500 | if (ret < 0) { |
501 | ALOGE("Set port type fail: %s. ret:%d", strerror(errno),ret); |
502 | } |
503 | return ret; |
504 | } |
505 | int vdin_screen_source::get_source_type() |
506 | { |
507 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
508 | int ret = -1; |
509 | int sourceType; |
510 | |
511 | ret = ioctl(mCameraHandle, VIDIOC_G_INPUT, &sourceType); |
512 | if(ret < 0){ |
513 | ALOGE("Set source type fail: %s. ret:%d", strerror(errno),ret); |
514 | return ret; |
515 | } |
516 | return sourceType; |
517 | } |
518 | |
519 | int vdin_screen_source::aquire_buffer(aml_screen_buffer_info_t *buff_info) |
520 | { |
521 | ALOGE("%s %d", __FUNCTION__, __LINE__); |
522 | int ret = -1; |
523 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
524 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
525 | |
526 | ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf); |
527 | if (ret < 0) { |
528 | if(EAGAIN == errno){ |
529 | ret = -EAGAIN; |
530 | }else{ |
531 | ALOGE("[%s %d]aquire_buffer %d", __FUNCTION__, __LINE__, ret); |
532 | } |
533 | buff_info->buffer_mem = 0; |
534 | buff_info->buffer_canvas = 0; |
535 | ALOGE("aquire_buffer %d %d", ret ,__LINE__); |
536 | return ret; |
537 | } |
538 | |
539 | if (!(mFrameType & NATIVE_WINDOW_DATA || mFrameType & CALL_BACK_DATA)) |
540 | mVideoInfo->refcount[mVideoInfo->buf.index] += 1; |
541 | |
542 | ALOGE("%s finish %d ", __FUNCTION__, __LINE__); |
543 | buff_info->buffer_mem = mVideoInfo->mem[mVideoInfo->buf.index]; |
544 | buff_info->buffer_canvas = mVideoInfo->canvas[mVideoInfo->buf.index]; |
545 | buff_info->tv_sec = mVideoInfo->buf.timestamp.tv_sec; |
546 | buff_info->tv_usec = mVideoInfo->buf.timestamp.tv_usec; |
547 | return ret; |
548 | } |
549 | |
550 | /* int vdin_screen_source::inc_buffer_refcount(int *ptr){ |
551 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
552 | int ret = -1; |
553 | int index; |
554 | index = mBufs.valueFor((unsigned int)ptr); |
555 | mVideoInfo->refcount[index] += 1; |
556 | return true; |
557 | } */ |
558 | |
559 | int vdin_screen_source::release_buffer(long* ptr) |
560 | { |
561 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
562 | int ret = -1; |
563 | int currentIndex; |
564 | v4l2_buffer hbuf_query; |
565 | |
566 | Mutex::Autolock autoLock(mLock); |
567 | |
568 | currentIndex = mBufs.valueFor(ptr); |
569 | if(mVideoInfo->refcount[currentIndex] > 0){ |
570 | mVideoInfo->refcount[currentIndex] -= 1; |
571 | }else{ |
572 | ALOGE("return buffer when refcount already zero"); |
573 | return 0; |
574 | } |
575 | if(mVideoInfo->refcount[currentIndex] == 0){ |
576 | memset(&hbuf_query,0,sizeof(v4l2_buffer)); |
577 | hbuf_query.index = currentIndex; |
578 | hbuf_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
579 | hbuf_query.memory = V4L2_MEMORY_MMAP; |
580 | ALOGV("return buffer :%d",currentIndex); |
581 | ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query); |
582 | if(ret != 0){ |
583 | ALOGE("Return Buffer :%d failed", currentIndex); |
584 | } |
585 | } |
586 | return 0; |
587 | } |
588 | |
589 | int vdin_screen_source::init_native_window() |
590 | { |
591 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
592 | int err = NO_ERROR; |
593 | |
594 | if(NULL == mANativeWindow.get()) |
595 | return BAD_VALUE; |
596 | |
597 | // Set gralloc usage bits for window. |
598 | err = native_window_set_usage(mANativeWindow.get(), SCREENSOURCE_GRALLOC_USAGE); |
599 | if (err != 0) { |
600 | ALOGE("native_window_set_usage failed: %s\n", strerror(-err)); |
601 | if(ENODEV == err ){ |
602 | ALOGE("Preview surface abandoned!"); |
603 | mANativeWindow = NULL; |
604 | } |
605 | return err; |
606 | } |
607 | |
608 | ALOGD("Number of buffers set to ANativeWindow %d", mBufferCount); |
609 | ///Set the number of buffers needed for camera preview |
610 | err = native_window_set_buffer_count(mANativeWindow.get(), mBufferCount); |
611 | if (err != 0) { |
612 | ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); |
613 | if(ENODEV == err){ |
614 | ALOGE("Preview surface abandoned!"); |
615 | mANativeWindow = NULL; |
616 | } |
617 | return err; |
618 | } |
619 | |
620 | ALOGD("native_window_set_buffers_geometry format:0x%x",mNativeWindowPixelFormat); |
621 | // Set window geometry |
622 | err = native_window_set_buffers_geometry( |
623 | mANativeWindow.get(), |
624 | mFrameWidth, |
625 | mFrameHeight, |
626 | mNativeWindowPixelFormat); |
627 | |
628 | if (err != 0) { |
629 | ALOGE("native_window_set_buffers_geometry failed: %s", strerror(-err)); |
630 | if ( ENODEV == err ) { |
631 | ALOGE("Surface abandoned!"); |
632 | mANativeWindow = NULL; |
633 | } |
634 | return err; |
635 | } |
636 | err = native_window_set_scaling_mode(mANativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); |
637 | if (err != 0) { |
638 | ALOGW("Failed to set scaling mode: %d", err); |
639 | return err; |
640 | } |
641 | return NO_ERROR; |
642 | } |
643 | |
644 | int vdin_screen_source::workThread() |
645 | { |
646 | bool buff_keep = false; |
647 | int index; |
648 | aml_screen_buffer_info_t buff_info; |
649 | int ret; |
650 | long *src = NULL; |
651 | unsigned char *dest = NULL; |
652 | uint8_t *handle = NULL; |
653 | ANativeWindowBuffer* buf; |
654 | if(mState == START){ |
655 | usleep(5000); |
656 | ret = aquire_buffer(&buff_info); |
657 | if (ret != 0 || (buff_info.buffer_mem == 0)) { |
658 | ALOGV("Get V4l2 buffer failed"); |
659 | return ret; |
660 | } |
661 | src = buff_info.buffer_mem; |
662 | index = mBufs.valueFor(src); |
663 | if(mFrameType & NATIVE_WINDOW_DATA){ |
664 | mVideoInfo->refcount[index] += 1; |
665 | if(mANativeWindow.get() == NULL){ |
666 | ALOGE("Null window"); |
667 | return BAD_VALUE; |
668 | } |
669 | ret = mANativeWindow->dequeueBuffer_DEPRECATED(mANativeWindow.get(), &buf); |
670 | if(ret != 0){ |
671 | ALOGE("dequeue buffer failed :%s (%d)",strerror(-ret), -ret); |
672 | return BAD_VALUE; |
673 | } |
674 | mANativeWindow->lockBuffer_DEPRECATED(mANativeWindow.get(), buf); |
675 | sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); |
676 | graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest); |
677 | if(dest == NULL){ |
678 | ALOGE("Invalid Gralloc Handle"); |
679 | return BAD_VALUE; |
680 | } |
681 | memcpy(dest, src, mBufferSize); |
682 | graphicBuffer->unlock(); |
683 | mANativeWindow->queueBuffer_DEPRECATED(mANativeWindow.get(), buf); |
684 | graphicBuffer.clear(); |
685 | ALOGV("queue one buffer to native window"); |
686 | release_buffer(src); |
687 | } |
688 | if(mFrameType & CALL_BACK_DATA && mDataCB != NULL&& mState == START){ |
689 | mVideoInfo->refcount[index] += 1; |
690 | mDataCB(mUser, &buff_info); |
691 | } |
692 | } |
693 | return NO_ERROR; |
694 | } |
695 | |
696 | } |
697 |