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