blob: 38ae48a4989d4ff889a29f401b2a9cb768becc7f
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 ALIGN(b,w) (((b)+((w)-1))/(w)*(w)) |
57 | |
58 | static size_t getBufSize(int format, int width, int height) |
59 | { |
60 | size_t buf_size = 0; |
61 | switch (format) { |
62 | case V4L2_PIX_FMT_YVU420: |
63 | case V4L2_PIX_FMT_NV21: |
64 | buf_size = width * height * 3 / 2; |
65 | break; |
66 | case V4L2_PIX_FMT_YUYV: |
67 | case V4L2_PIX_FMT_RGB565: |
68 | case V4L2_PIX_FMT_RGB565X: |
69 | buf_size = width * height * 2; |
70 | break; |
71 | case V4L2_PIX_FMT_RGB24: |
72 | buf_size = width * height * 3; |
73 | break; |
74 | case V4L2_PIX_FMT_RGB32: |
75 | buf_size = width * height * 4; |
76 | break; |
77 | default: |
78 | ALOGE("Invalid format"); |
79 | buf_size = width * height * 3 / 2; |
80 | } |
81 | return buf_size; |
82 | } |
83 | |
84 | static void two_bytes_per_pixel_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
85 | { |
86 | int stride = (width + 31) & ( ~31); |
87 | int w, h; |
88 | for (h=0; h<height; h++) |
89 | { |
90 | memcpy( dst, src, width*2); |
91 | dst += width*2; |
92 | src += stride*2; |
93 | } |
94 | } |
95 | |
96 | static void nv21_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
97 | { |
98 | int stride = (width + 31) & ( ~31); |
99 | int w, h; |
100 | for (h=0; h<height*3/2; h++) |
101 | { |
102 | memcpy( dst, src, width); |
103 | dst += width; |
104 | src += stride; |
105 | } |
106 | } |
107 | |
108 | static void yv12_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
109 | { |
110 | int new_width = (width + 63) & ( ~63); |
111 | int stride; |
112 | int w, h; |
113 | for (h=0; h<height; h++) |
114 | { |
115 | memcpy( dst, src, width); |
116 | dst += width; |
117 | src += new_width; |
118 | } |
119 | |
120 | stride = ALIGN(width/2, 16); |
121 | for (h=0; h<height; h++) |
122 | { |
123 | memcpy( dst, src, width/2); |
124 | dst += stride; |
125 | src += new_width/2; |
126 | } |
127 | } |
128 | |
129 | static void rgb24_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
130 | { |
131 | int stride = (width + 31) & ( ~31); |
132 | int w, h; |
133 | for (h=0; h<height; h++) |
134 | { |
135 | memcpy( dst, src, width*3); |
136 | dst += width*3; |
137 | src += stride*3; |
138 | } |
139 | } |
140 | |
141 | static void rgb32_memcpy_align32(unsigned char *dst, unsigned char *src, int width, int height) |
142 | { |
143 | int stride = (width + 31) & ( ~31); |
144 | int w, h; |
145 | for (h=0; h<height; h++) |
146 | { |
147 | memcpy( dst, src, width*4); |
148 | dst += width*4; |
149 | src += stride*4; |
150 | } |
151 | } |
152 | |
153 | static int getNativeWindowFormat(int format) |
154 | { |
155 | int nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I; |
156 | |
157 | switch(format){ |
158 | case V4L2_PIX_FMT_YVU420: |
159 | nativeFormat = HAL_PIXEL_FORMAT_YV12; |
160 | break; |
161 | case V4L2_PIX_FMT_NV21: |
162 | nativeFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
163 | break; |
164 | case V4L2_PIX_FMT_YUYV: |
165 | nativeFormat = HAL_PIXEL_FORMAT_YCbCr_422_I; |
166 | break; |
167 | case V4L2_PIX_FMT_RGB565: |
168 | nativeFormat = HAL_PIXEL_FORMAT_RGB_565; |
169 | break; |
170 | case V4L2_PIX_FMT_RGB24: |
171 | nativeFormat = HAL_PIXEL_FORMAT_RGB_888; |
172 | break; |
173 | case V4L2_PIX_FMT_RGB32: |
174 | nativeFormat = HAL_PIXEL_FORMAT_RGBA_8888; |
175 | break; |
176 | default: |
177 | ALOGE("Invalid format,Use default format"); |
178 | } |
179 | return nativeFormat; |
180 | } |
181 | |
182 | |
183 | static ANativeWindowBuffer* handle_to_buffer(buffer_handle_t *handle) |
184 | { |
185 | return container_of(handle, ANativeWindowBuffer, handle); |
186 | } |
187 | |
188 | vdin_screen_source::vdin_screen_source() |
189 | : mCameraHandle(-1), |
190 | mVideoInfo(NULL) |
191 | { |
192 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
193 | } |
194 | |
195 | int vdin_screen_source::init(int id){ |
196 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
197 | if (id == 0) { |
198 | mCameraHandle = open("/dev/video11", O_RDWR| O_NONBLOCK); |
199 | if (mCameraHandle < 0) |
200 | { |
201 | ALOGE("[%s %d] mCameraHandle:%x [%s]", __FUNCTION__, __LINE__, mCameraHandle,strerror(errno)); |
202 | return -1; |
203 | } |
204 | } else { |
205 | mCameraHandle = open("/dev/video12", O_RDWR| O_NONBLOCK); |
206 | if (mCameraHandle < 0) |
207 | { |
208 | ALOGE("[%s %d] mCameraHandle:%x [%s]", __FUNCTION__, __LINE__, mCameraHandle,strerror(errno)); |
209 | return -1; |
210 | } |
211 | } |
212 | mVideoInfo = (struct VideoInfo *) calloc (1, sizeof (struct VideoInfo)); |
213 | if (mVideoInfo == NULL) |
214 | { |
215 | ALOGE("[%s %d] no memory for mVideoInfo", __FUNCTION__, __LINE__); |
216 | close(mCameraHandle); |
217 | return NO_MEMORY; |
218 | } |
219 | mBufferCount = 4; |
220 | for (int i = 0; i < mBufferCount; i++) { |
221 | src_temp[i] = NULL; |
222 | } |
223 | mPixelFormat = V4L2_PIX_FMT_NV21; |
224 | mNativeWindowPixelFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
225 | mFrameWidth = 1280; |
226 | mFrameHeight = 720; |
227 | mBufferSize = mFrameWidth * mFrameHeight * 3/2; |
228 | mSetStateCB = NULL; |
229 | mState = STOP; |
230 | mANativeWindow = NULL; |
231 | mFrameType = 0; |
232 | mWorkThread = NULL; |
233 | mDataCB = NULL; |
234 | mOpen = false; |
235 | return NO_ERROR; |
236 | } |
237 | |
238 | vdin_screen_source::~vdin_screen_source() |
239 | { |
240 | if (mVideoInfo) |
241 | free (mVideoInfo); |
242 | if (mCameraHandle >= 0) |
243 | close(mCameraHandle); |
244 | } |
245 | |
246 | int vdin_screen_source::start_v4l2_device() |
247 | { |
248 | int ret = -1; |
249 | |
250 | ALOGV("[%s %d] mCameraHandle:%x", __FUNCTION__, __LINE__, mCameraHandle); |
251 | |
252 | ioctl(mCameraHandle, VIDIOC_QUERYCAP, &mVideoInfo->cap); |
253 | |
254 | mVideoInfo->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
255 | mVideoInfo->rb.memory = V4L2_MEMORY_MMAP; |
256 | mVideoInfo->rb.count = mBufferCount; |
257 | |
258 | ret = ioctl(mCameraHandle, VIDIOC_REQBUFS, &mVideoInfo->rb); |
259 | |
260 | if (ret < 0) { |
261 | ALOGE("[%s %d] VIDIOC_REQBUFS:%d mCameraHandle:%x", __FUNCTION__, __LINE__, ret, mCameraHandle); |
262 | return ret; |
263 | } |
264 | |
265 | for (int i = 0; i < mBufferCount; i++) { |
266 | memset (&mVideoInfo->buf, 0, sizeof (struct v4l2_buffer)); |
267 | |
268 | mVideoInfo->buf.index = i; |
269 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
270 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
271 | |
272 | ret = ioctl (mCameraHandle, VIDIOC_QUERYBUF, &mVideoInfo->buf); |
273 | if (ret < 0) { |
274 | ALOGE("[%s %d]VIDIOC_QUERYBUF %d failed", __FUNCTION__, __LINE__, i); |
275 | return ret; |
276 | } |
277 | mVideoInfo->canvas[i] = mVideoInfo->buf.reserved; |
278 | mVideoInfo->mem[i] = (long *)mmap (0, mVideoInfo->buf.length, PROT_READ | PROT_WRITE, |
279 | MAP_SHARED, mCameraHandle, mVideoInfo->buf.m.offset); |
280 | |
281 | if (mVideoInfo->mem[i] == MAP_FAILED) { |
282 | ALOGE("[%s %d] MAP_FAILED", __FUNCTION__, __LINE__); |
283 | return -1; |
284 | } |
285 | mVideoInfo->refcount[i] = 0; |
286 | mBufs.add(mVideoInfo->mem[i],i); |
287 | if (mFrameWidth %32 != 0) { |
288 | mTemp_Bufs.add(src_temp[i],i); |
289 | } |
290 | } |
291 | ALOGV("[%s %d] VIDIOC_QUERYBUF successful", __FUNCTION__, __LINE__); |
292 | |
293 | for (int i = 0; i < mBufferCount; i++) { |
294 | mVideoInfo->buf.index = i; |
295 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
296 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
297 | ret = ioctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf); |
298 | if (ret < 0) { |
299 | ALOGE("VIDIOC_QBUF Failed"); |
300 | return -1; |
301 | } |
302 | } |
303 | enum v4l2_buf_type bufType; |
304 | bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
305 | |
306 | ret = ioctl (mCameraHandle, VIDIOC_STREAMON, &bufType); |
307 | |
308 | ALOGV("[%s %d] VIDIOC_STREAMON:%x", __FUNCTION__, __LINE__, ret); |
309 | return ret; |
310 | } |
311 | |
312 | int vdin_screen_source::stop_v4l2_device() |
313 | { |
314 | ALOGE("%s %d", __FUNCTION__, __LINE__); |
315 | int ret; |
316 | enum v4l2_buf_type bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
317 | |
318 | ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType); |
319 | if (ret < 0) { |
320 | ALOGE("StopStreaming: Unable to stop capture: %s", strerror(errno)); |
321 | } |
322 | for (int i = 0; i < mBufferCount; i++) { |
323 | if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) { |
324 | ALOGE("Unmap failed"); |
325 | } |
326 | } |
327 | mBufs.clear(); |
328 | if (mFrameWidth %32 != 0) { |
329 | mTemp_Bufs.clear(); |
330 | for (int j = 0; j <mBufferCount; j++ ) { |
331 | free(src_temp[j]); |
332 | src_temp[j] = NULL; |
333 | } |
334 | } |
335 | return ret; |
336 | } |
337 | int vdin_screen_source::start() |
338 | { |
339 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
340 | int ret; |
341 | if(mOpen == true){ |
342 | ALOGI("already open"); |
343 | return NO_ERROR; |
344 | } |
345 | |
346 | ret = start_v4l2_device(); |
347 | if(ret != NO_ERROR){ |
348 | ALOGE("Start v4l2 device failed:%d",ret); |
349 | return ret; |
350 | } |
351 | if(mFrameType & NATIVE_WINDOW_DATA){ |
352 | ret = init_native_window(); |
353 | if(ret != NO_ERROR){ |
354 | ALOGE("Init Native Window Failed:%d",ret); |
355 | return ret; |
356 | } |
357 | } |
358 | if(mFrameType & NATIVE_WINDOW_DATA || mFrameType & CALL_BACK_DATA){ |
359 | ALOGD("Create Work Thread"); |
360 | mWorkThread = new WorkThread(this); |
361 | } |
362 | if(mSetStateCB != NULL) |
363 | mSetStateCB(START); |
364 | mState = START; |
365 | mOpen = true; |
366 | ALOGV("%s %d ret:%d", __FUNCTION__, __LINE__, ret); |
367 | return NO_ERROR; |
368 | } |
369 | |
370 | int vdin_screen_source::pause() |
371 | { |
372 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
373 | mState = PAUSE; |
374 | if(mSetStateCB != NULL) |
375 | mSetStateCB(PAUSE); |
376 | return NO_ERROR; |
377 | } |
378 | int vdin_screen_source::stop() |
379 | { |
380 | ALOGE("!!!!!!!!!%s %d", __FUNCTION__, __LINE__); |
381 | int ret; |
382 | mState = STOPING; |
383 | |
384 | if(mWorkThread != NULL){ |
385 | mWorkThread->requestExitAndWait(); |
386 | mWorkThread.clear(); |
387 | } |
388 | |
389 | enum v4l2_buf_type bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
390 | |
391 | ret = ioctl (mCameraHandle, VIDIOC_STREAMOFF, &bufType); |
392 | if (ret < 0) { |
393 | ALOGE("StopStreaming: Unable to stop capture: %s", strerror(errno)); |
394 | } |
395 | for (int i = 0; i < mBufferCount; i++){ |
396 | if (munmap(mVideoInfo->mem[i], mVideoInfo->buf.length) < 0) |
397 | ALOGE("Unmap failed"); |
398 | } |
399 | |
400 | mBufferCount = 0; |
401 | mState = STOP; |
402 | if(mSetStateCB != NULL) |
403 | mSetStateCB(STOP); |
404 | mOpen = false; |
405 | return ret; |
406 | } |
407 | |
408 | int vdin_screen_source::set_state_callback(olStateCB callback) |
409 | { |
410 | if (!callback){ |
411 | ALOGE("NULL state callback pointer"); |
412 | return BAD_VALUE; |
413 | } |
414 | mSetStateCB = callback; |
415 | return NO_ERROR; |
416 | } |
417 | |
418 | int vdin_screen_source::set_preview_window(ANativeWindow* window) |
419 | { |
420 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
421 | if(mOpen == true) |
422 | return NO_ERROR; |
423 | //can work without a valid window object ? |
424 | if (window == NULL){ |
425 | ALOGD("NULL window object passed to ScreenSource"); |
426 | if(mWorkThread != NULL){ |
427 | mWorkThread->requestExitAndWait(); |
428 | mWorkThread.clear(); |
429 | } |
430 | mFrameType &= ~NATIVE_WINDOW_DATA; |
431 | return NO_ERROR; |
432 | } |
433 | mFrameType |= NATIVE_WINDOW_DATA; |
434 | mANativeWindow = window; |
435 | return NO_ERROR; |
436 | } |
437 | |
438 | int vdin_screen_source::set_data_callback(app_data_callback callback, void* user) |
439 | { |
440 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
441 | if (callback == NULL){ |
442 | ALOGE("NULL data callback pointer"); |
443 | return BAD_VALUE; |
444 | } |
445 | mDataCB = callback; |
446 | mUser = user; |
447 | mFrameType |= CALL_BACK_DATA; |
448 | return NO_ERROR; |
449 | } |
450 | |
451 | int vdin_screen_source::get_format() |
452 | { |
453 | return mPixelFormat; |
454 | } |
455 | |
456 | int vdin_screen_source::set_format(int width, int height, int color_format) |
457 | { |
458 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
459 | if(mOpen == true) |
460 | return NO_ERROR; |
461 | int ret; |
462 | mVideoInfo->width = width; |
463 | mVideoInfo->height = height; |
464 | mVideoInfo->framesizeIn = (mVideoInfo->width * mVideoInfo->height << 3); //note color format |
465 | mVideoInfo->formatIn = color_format; |
466 | |
467 | mVideoInfo->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
468 | mVideoInfo->format.fmt.pix.width = width; |
469 | mVideoInfo->format.fmt.pix.height = height; |
470 | mVideoInfo->format.fmt.pix.pixelformat = color_format; |
471 | mPixelFormat = color_format; |
472 | mNativeWindowPixelFormat = getNativeWindowFormat(color_format); |
473 | mFrameWidth = width; |
474 | mFrameHeight = height; |
475 | mBufferSize = getBufSize(color_format, mFrameWidth, mFrameHeight); |
476 | if (mFrameWidth %32 != 0) { |
477 | for (int i = 0; i < mBufferCount; i++) { |
478 | src_temp[i] = (long*) malloc(mBufferSize); |
479 | if (!src_temp[i]) { |
480 | ALOGE("malloc src_temp buffer failed .\n"); |
481 | return NO_MEMORY; |
482 | } |
483 | } |
484 | } |
485 | ALOGD("mFrameWidth:%d,mFrameHeight:%d",mFrameWidth,mFrameHeight); |
486 | ALOGD("mPixelFormat:%x,mNativeWindowPixelFormat:%x,mBufferSize:%d",mPixelFormat,mNativeWindowPixelFormat,mBufferSize); |
487 | ret = ioctl(mCameraHandle, VIDIOC_S_FMT, &mVideoInfo->format); |
488 | if (ret < 0) { |
489 | ALOGE("[%s %d]VIDIOC_S_FMT %d", __FUNCTION__, __LINE__, ret); |
490 | return ret; |
491 | } |
492 | return ret; |
493 | } |
494 | |
495 | int vdin_screen_source::set_rotation(int degree) |
496 | { |
497 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
498 | |
499 | int ret = 0; |
500 | struct v4l2_control ctl; |
501 | |
502 | if(mCameraHandle<0) |
503 | return -1; |
504 | |
505 | if((degree!=0)&&(degree!=90)&&(degree!=180)&&(degree!=270)){ |
506 | ALOGE("Set rotate value invalid: %d.", degree); |
507 | return -1; |
508 | } |
509 | |
510 | memset( &ctl, 0, sizeof(ctl)); |
511 | ctl.value=degree; |
512 | ctl.id = V4L2_ROTATE_ID; |
513 | ret = ioctl(mCameraHandle, VIDIOC_S_CTRL, &ctl); |
514 | |
515 | if(ret<0){ |
516 | ALOGE("Set rotate value fail: %s. ret=%d", strerror(errno),ret); |
517 | } |
518 | return ret ; |
519 | } |
520 | |
521 | int vdin_screen_source::set_crop(int x, int y, int width, int height) |
522 | { |
523 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
524 | if (NULL == mANativeWindow.get()) |
525 | return BAD_VALUE; |
526 | |
527 | int err = NO_ERROR; |
528 | android_native_rect_t crop = { x, y, x + width - 1, y + height - 1 }; |
529 | err = native_window_set_crop(mANativeWindow.get(), &crop); |
530 | if (err != 0) { |
531 | ALOGW("Failed to set crop!"); |
532 | return err; |
533 | } |
534 | return NO_ERROR; |
535 | } |
536 | |
537 | int vdin_screen_source::set_frame_rate(int frameRate) |
538 | { |
539 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
540 | int ret = 0; |
541 | struct v4l2_control ctl; |
542 | |
543 | if(mCameraHandle<0) |
544 | return -1; |
545 | |
546 | struct v4l2_streamparm sparm; |
547 | memset(&sparm, 0, sizeof( sparm )); |
548 | sparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//stream_flag; |
549 | sparm.parm.output.timeperframe.denominator = frameRate; |
550 | sparm.parm.output.timeperframe.numerator = 1; |
551 | |
552 | ret = ioctl(mCameraHandle, VIDIOC_S_PARM, &sparm); |
553 | if(ret < 0){ |
554 | ALOGE("Set frame rate fail: %s. ret=%d", strerror(errno),ret); |
555 | } |
556 | return ret ; |
557 | } |
558 | |
559 | int vdin_screen_source::get_amlvideo2_crop(int *x, int *y, int *width, int *height) |
560 | { |
561 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
562 | int ret = 0; |
563 | |
564 | struct v4l2_crop crop; |
565 | memset(&crop, 0, sizeof(struct v4l2_crop)); |
566 | crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
567 | ret = ioctl(mCameraHandle, VIDIOC_S_CROP, &crop); |
568 | if (ret) { |
569 | ALOGE("get amlvideo2 crop fail: %s. ret=%d", strerror(errno),ret); |
570 | } |
571 | *x = crop.c.left; |
572 | *y = crop.c.top; |
573 | *width = crop.c.width; |
574 | *height = crop.c.height; |
575 | return ret ; |
576 | } |
577 | |
578 | int vdin_screen_source::set_amlvideo2_crop(int x, int y, int width, int height) |
579 | { |
580 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
581 | int ret = 0; |
582 | |
583 | struct v4l2_crop crop; |
584 | memset(&crop, 0, sizeof(struct v4l2_crop)); |
585 | |
586 | crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; |
587 | crop.c.left = x; |
588 | crop.c.top = y; |
589 | crop.c.width = width; |
590 | crop.c.height = height; |
591 | ret = ioctl(mCameraHandle, VIDIOC_S_CROP, &crop); |
592 | if (ret) { |
593 | ALOGE("Set amlvideo2 crop fail: %s. ret=%d", strerror(errno),ret); |
594 | } |
595 | |
596 | return ret ; |
597 | } |
598 | |
599 | int vdin_screen_source::set_source_type(int sourceType) |
600 | { |
601 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
602 | int ret = 0; |
603 | |
604 | ret = ioctl(mCameraHandle, VIDIOC_S_INPUT, &sourceType); |
605 | if(ret < 0){ |
606 | ALOGE("Set source type fail: %s. ret:%d", strerror(errno),ret); |
607 | } |
608 | return ret; |
609 | } |
610 | |
611 | int vdin_screen_source::set_port_type(int sourceType) |
612 | { |
613 | ALOGD("[%s %d]", __FUNCTION__, __LINE__); |
614 | int ret = 0; |
615 | unsigned int portType = (unsigned int)sourceType; |
616 | ALOGE("portType:%d",portType); |
617 | ret = ioctl(mCameraHandle, VIDIOC_S_INPUT, &portType); |
618 | if (ret < 0) { |
619 | ALOGE("Set port type fail: %s. ret:%d", strerror(errno),ret); |
620 | } |
621 | return ret; |
622 | } |
623 | int vdin_screen_source::get_source_type() |
624 | { |
625 | ALOGV("[%s %d]", __FUNCTION__, __LINE__); |
626 | int ret = -1; |
627 | int sourceType; |
628 | |
629 | ret = ioctl(mCameraHandle, VIDIOC_G_INPUT, &sourceType); |
630 | if(ret < 0){ |
631 | ALOGE("Set source type fail: %s. ret:%d", strerror(errno),ret); |
632 | return ret; |
633 | } |
634 | return sourceType; |
635 | } |
636 | |
637 | int vdin_screen_source::get_current_sourcesize(int *width, int *height) |
638 | { |
639 | int ret = NO_ERROR; |
640 | struct v4l2_format format; |
641 | memset(&format, 0,sizeof(struct v4l2_format)); |
642 | |
643 | format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
644 | ret = ioctl(mCameraHandle, VIDIOC_G_FMT, &format); |
645 | if (ret < 0) { |
646 | ALOGE("Open: VIDIOC_G_FMT Failed: %s", strerror(errno)); |
647 | return ret; |
648 | } |
649 | *width = format.fmt.pix.width; |
650 | *height = format.fmt.pix.height; |
651 | ALOGD("VIDIOC_G_FMT, w * h: %5d x %5d", *width, *height); |
652 | return ret; |
653 | } |
654 | |
655 | int vdin_screen_source::set_screen_mode(int mode) |
656 | { |
657 | int ret = NO_ERROR; |
658 | |
659 | ret = ioctl(mCameraHandle, VIDIOC_S_OUTPUT, &mode); |
660 | if (ret < 0) { |
661 | ALOGE("VIDIOC_S_OUTPUT Failed: %s", strerror(errno)); |
662 | return ret; |
663 | } |
664 | return ret; |
665 | } |
666 | |
667 | int vdin_screen_source::aquire_buffer(aml_screen_buffer_info_t *buff_info) |
668 | { |
669 | ALOGE("%s %d", __FUNCTION__, __LINE__); |
670 | int ret = -1; |
671 | mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
672 | mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; |
673 | |
674 | ret = ioctl(mCameraHandle, VIDIOC_DQBUF, &mVideoInfo->buf); |
675 | if (ret < 0) { |
676 | if(EAGAIN == errno){ |
677 | ret = -EAGAIN; |
678 | }else{ |
679 | ALOGE("[%s %d]aquire_buffer %d", __FUNCTION__, __LINE__, ret); |
680 | } |
681 | buff_info->buffer_mem = 0; |
682 | buff_info->buffer_canvas = 0; |
683 | ALOGE("aquire_buffer %d %d", ret ,__LINE__); |
684 | return ret; |
685 | } |
686 | |
687 | if (!(mFrameType & NATIVE_WINDOW_DATA || mFrameType & CALL_BACK_DATA)) |
688 | mVideoInfo->refcount[mVideoInfo->buf.index] += 1; |
689 | |
690 | if (mFrameWidth %32 != 0) { |
691 | switch (mVideoInfo->format.fmt.pix.pixelformat) { |
692 | case V4L2_PIX_FMT_YVU420: |
693 | yv12_memcpy_align32((unsigned char*)src_temp[mVideoInfo->buf.index], (unsigned char*)mVideoInfo->mem[mVideoInfo->buf.index], mFrameWidth, mFrameHeight); |
694 | break; |
695 | case V4L2_PIX_FMT_NV21: |
696 | nv21_memcpy_align32((unsigned char*)src_temp[mVideoInfo->buf.index], (unsigned char*)mVideoInfo->mem[mVideoInfo->buf.index], mFrameWidth, mFrameHeight); |
697 | break; |
698 | case V4L2_PIX_FMT_YUYV: |
699 | case V4L2_PIX_FMT_RGB565: |
700 | case V4L2_PIX_FMT_RGB565X: |
701 | two_bytes_per_pixel_memcpy_align32 ((unsigned char*)src_temp[mVideoInfo->buf.index], (unsigned char*)mVideoInfo->mem[mVideoInfo->buf.index], mFrameWidth, mFrameHeight); |
702 | break; |
703 | case V4L2_PIX_FMT_RGB24: |
704 | rgb24_memcpy_align32((unsigned char*)src_temp[mVideoInfo->buf.index], (unsigned char*)mVideoInfo->mem[mVideoInfo->buf.index], mFrameWidth, mFrameHeight); |
705 | break; |
706 | case V4L2_PIX_FMT_RGB32: |
707 | rgb32_memcpy_align32((unsigned char*)src_temp[mVideoInfo->buf.index], (unsigned char*)mVideoInfo->mem[mVideoInfo->buf.index], mFrameWidth, mFrameHeight); |
708 | break; |
709 | default: |
710 | ALOGE("Invalid format , %s %d " , __FUNCTION__, __LINE__); |
711 | } |
712 | buff_info->buffer_mem = src_temp[mVideoInfo->buf.index]; |
713 | buff_info->buffer_canvas = mVideoInfo->canvas[mVideoInfo->buf.index]; |
714 | buff_info->tv_sec = mVideoInfo->buf.timestamp.tv_sec; |
715 | buff_info->tv_usec = mVideoInfo->buf.timestamp.tv_usec; |
716 | } else { |
717 | buff_info->buffer_mem = mVideoInfo->mem[mVideoInfo->buf.index]; |
718 | buff_info->buffer_canvas = mVideoInfo->canvas[mVideoInfo->buf.index]; |
719 | buff_info->tv_sec = mVideoInfo->buf.timestamp.tv_sec; |
720 | buff_info->tv_usec = mVideoInfo->buf.timestamp.tv_usec; |
721 | } |
722 | |
723 | ALOGE("%s finish %d ", __FUNCTION__, __LINE__); |
724 | return ret; |
725 | } |
726 | |
727 | /* int vdin_screen_source::inc_buffer_refcount(int *ptr){ |
728 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
729 | int ret = -1; |
730 | int index; |
731 | index = mBufs.valueFor((unsigned int)ptr); |
732 | mVideoInfo->refcount[index] += 1; |
733 | return true; |
734 | } */ |
735 | |
736 | int vdin_screen_source::release_buffer(long* ptr) |
737 | { |
738 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
739 | int ret = -1; |
740 | int currentIndex; |
741 | v4l2_buffer hbuf_query; |
742 | |
743 | Mutex::Autolock autoLock(mLock); |
744 | if (mFrameWidth % 32 != 0) { |
745 | currentIndex = mTemp_Bufs.valueFor(ptr); |
746 | } else { |
747 | currentIndex = mBufs.valueFor(ptr); |
748 | } |
749 | if (mVideoInfo->refcount[currentIndex] > 0) { |
750 | mVideoInfo->refcount[currentIndex] -= 1; |
751 | } else { |
752 | ALOGE("return buffer when refcount already zero"); |
753 | return 0; |
754 | } |
755 | if (mVideoInfo->refcount[currentIndex] == 0) { |
756 | memset(&hbuf_query,0,sizeof(v4l2_buffer)); |
757 | hbuf_query.index = currentIndex; |
758 | hbuf_query.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
759 | hbuf_query.memory = V4L2_MEMORY_MMAP; |
760 | ALOGV("return buffer :%d",currentIndex); |
761 | ret = ioctl(mCameraHandle, VIDIOC_QBUF, &hbuf_query); |
762 | if (ret != 0) { |
763 | ALOGE("Return Buffer :%d failed", currentIndex); |
764 | } |
765 | } |
766 | return 0; |
767 | } |
768 | |
769 | int vdin_screen_source::init_native_window() |
770 | { |
771 | ALOGV("%s %d", __FUNCTION__, __LINE__); |
772 | int err = NO_ERROR; |
773 | |
774 | if(NULL == mANativeWindow.get()) |
775 | return BAD_VALUE; |
776 | |
777 | // Set gralloc usage bits for window. |
778 | err = native_window_set_usage(mANativeWindow.get(), SCREENSOURCE_GRALLOC_USAGE); |
779 | if (err != 0) { |
780 | ALOGE("native_window_set_usage failed: %s\n", strerror(-err)); |
781 | if(ENODEV == err ){ |
782 | ALOGE("Preview surface abandoned!"); |
783 | mANativeWindow = NULL; |
784 | } |
785 | return err; |
786 | } |
787 | |
788 | ALOGD("Number of buffers set to ANativeWindow %d", mBufferCount); |
789 | ///Set the number of buffers needed for camera preview |
790 | err = native_window_set_buffer_count(mANativeWindow.get(), mBufferCount); |
791 | if (err != 0) { |
792 | ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err), -err); |
793 | if(ENODEV == err){ |
794 | ALOGE("Preview surface abandoned!"); |
795 | mANativeWindow = NULL; |
796 | } |
797 | return err; |
798 | } |
799 | |
800 | ALOGD("native_window_set_buffers_geometry format:0x%x",mNativeWindowPixelFormat); |
801 | // Set window geometry |
802 | err = native_window_set_buffers_geometry( |
803 | mANativeWindow.get(), |
804 | mFrameWidth, |
805 | mFrameHeight, |
806 | mNativeWindowPixelFormat); |
807 | |
808 | if (err != 0) { |
809 | ALOGE("native_window_set_buffers_geometry failed: %s", strerror(-err)); |
810 | if ( ENODEV == err ) { |
811 | ALOGE("Surface abandoned!"); |
812 | mANativeWindow = NULL; |
813 | } |
814 | return err; |
815 | } |
816 | err = native_window_set_scaling_mode(mANativeWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); |
817 | if (err != 0) { |
818 | ALOGW("Failed to set scaling mode: %d", err); |
819 | return err; |
820 | } |
821 | return NO_ERROR; |
822 | } |
823 | |
824 | int vdin_screen_source::workThread() |
825 | { |
826 | bool buff_keep = false; |
827 | int index; |
828 | aml_screen_buffer_info_t buff_info; |
829 | int ret; |
830 | long *src = NULL; |
831 | unsigned char *dest = NULL; |
832 | uint8_t *handle = NULL; |
833 | ANativeWindowBuffer* buf; |
834 | if(mState == START){ |
835 | usleep(5000); |
836 | ret = aquire_buffer(&buff_info); |
837 | if (ret != 0 || (buff_info.buffer_mem == 0)) { |
838 | ALOGV("Get V4l2 buffer failed"); |
839 | return ret; |
840 | } |
841 | src = buff_info.buffer_mem; |
842 | index = mBufs.valueFor(src); |
843 | if(mFrameType & NATIVE_WINDOW_DATA){ |
844 | mVideoInfo->refcount[index] += 1; |
845 | if(mANativeWindow.get() == NULL){ |
846 | ALOGE("Null window"); |
847 | return BAD_VALUE; |
848 | } |
849 | ret = mANativeWindow->dequeueBuffer_DEPRECATED(mANativeWindow.get(), &buf); |
850 | if(ret != 0){ |
851 | ALOGE("dequeue buffer failed :%s (%d)",strerror(-ret), -ret); |
852 | return BAD_VALUE; |
853 | } |
854 | mANativeWindow->lockBuffer_DEPRECATED(mANativeWindow.get(), buf); |
855 | sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false)); |
856 | graphicBuffer->lock(SCREENSOURCE_GRALLOC_USAGE, (void **)&dest); |
857 | if(dest == NULL){ |
858 | ALOGE("Invalid Gralloc Handle"); |
859 | return BAD_VALUE; |
860 | } |
861 | memcpy(dest, src, mBufferSize); |
862 | graphicBuffer->unlock(); |
863 | mANativeWindow->queueBuffer_DEPRECATED(mANativeWindow.get(), buf); |
864 | graphicBuffer.clear(); |
865 | ALOGV("queue one buffer to native window"); |
866 | release_buffer(src); |
867 | } |
868 | if(mFrameType & CALL_BACK_DATA && mDataCB != NULL&& mState == START){ |
869 | mVideoInfo->refcount[index] += 1; |
870 | mDataCB(mUser, &buff_info); |
871 | } |
872 | } |
873 | return NO_ERROR; |
874 | } |
875 | |
876 | } |
877 |