summaryrefslogtreecommitdiff
path: root/v4l2_vdin.cpp (plain)
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
46namespace 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))
57static 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
83static 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
95static 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
107static 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
128static 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
140static 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
152static 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
182static ANativeWindowBuffer* handle_to_buffer(buffer_handle_t *handle)
183{
184 return container_of(handle, ANativeWindowBuffer, handle);
185}
186
187vdin_screen_source::vdin_screen_source()
188 : mCameraHandle(-1),
189 mVideoInfo(NULL)
190{
191 ALOGV("%s %d", __FUNCTION__, __LINE__);
192}
193
194int 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
235vdin_screen_source::~vdin_screen_source()
236{
237 if (mVideoInfo)
238 free (mVideoInfo);
239 if (mCameraHandle >= 0)
240 close(mCameraHandle);
241}
242
243int 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
308int 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}
333int 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
366int 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}
374int 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
404int 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
414int 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
434int 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
447int vdin_screen_source::get_format()
448{
449 return mPixelFormat;
450}
451
452int 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
460int 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
517int 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
540int 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
556int 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
578int 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
597int 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 */
626int 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}
638int 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
653int 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
671int 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
682int 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
751int 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
784int 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
839int 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}
930int 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