00001 #undef _FILE_OFFSET_BITS
00002 #undef _LARGEFILE_SOURCE
00003 #undef _LARGEFILE64_SOURCE
00004
00005 #include "assets.h"
00006 #include "channel.h"
00007 #include "chantables.h"
00008 #include "clip.h"
00009 #include "condition.h"
00010 #include "file.h"
00011 #include "picture.h"
00012 #include "preferences.h"
00013 #include "quicktime.h"
00014 #include "recordconfig.h"
00015 #include "vdevicev4l2.h"
00016 #include "vframe.h"
00017 #include "videodevice.h"
00018
00019 #ifdef HAVE_VIDEO4LINUX2
00020
00021 #include <unistd.h>
00022 #include <sys/ioctl.h>
00023 #include <fcntl.h>
00024 #include <sys/mman.h>
00025 #include <string.h>
00026
00027
00028
00029
00030
00031
00032
00033 VDeviceV4L2Put::VDeviceV4L2Put(VDeviceV4L2Thread *thread)
00034 : Thread(1, 0, 0)
00035 {
00036 this->thread = thread;
00037 done = 0;
00038 lock = new Mutex("VDeviceV4L2Put::lock");
00039 more_buffers = new Condition(0, "VDeviceV4L2Put::more_buffers");
00040 putbuffers = new int[0xff];
00041 total = 0;
00042 }
00043
00044 VDeviceV4L2Put::~VDeviceV4L2Put()
00045 {
00046 if(Thread::running())
00047 {
00048 done = 1;
00049 more_buffers->unlock();
00050 Thread::cancel();
00051 Thread::join();
00052 }
00053 delete lock;
00054 delete more_buffers;
00055 delete [] putbuffers;
00056 }
00057
00058 void VDeviceV4L2Put::run()
00059 {
00060 while(!done)
00061 {
00062 more_buffers->lock("VDeviceV4L2Put::run");
00063 if(done) break;
00064 lock->lock("VDeviceV4L2Put::run");
00065 int buffer = -1;
00066 if(total)
00067 {
00068 buffer = putbuffers[0];
00069 for(int i = 0; i < total - 1; i++)
00070 putbuffers[i] = putbuffers[i + 1];
00071 total--;
00072 }
00073 lock->unlock();
00074
00075 if(buffer >= 0)
00076 {
00077 struct v4l2_buffer arg;
00078 bzero(&arg, sizeof(arg));
00079 arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00080 arg.index = buffer;
00081 arg.memory = V4L2_MEMORY_MMAP;
00082
00083 Thread::enable_cancel();
00084 thread->ioctl_lock->lock("VDeviceV4L2Put::run");
00085
00086 if(ioctl(thread->input_fd, VIDIOC_QBUF, &arg) < 0)
00087 perror("VDeviceV4L2Put::run 1 VIDIOC_QBUF");
00088 thread->ioctl_lock->unlock();
00089
00090 usleep(1000000 * 1001 / 60000);
00091 Thread::disable_cancel();
00092 }
00093 }
00094 }
00095
00096 void VDeviceV4L2Put::put_buffer(int number)
00097 {
00098 lock->lock("VDeviceV4L2Put::put_buffer");
00099 putbuffers[total++] = number;
00100 lock->unlock();
00101 more_buffers->unlock();
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 VDeviceV4L2Thread::VDeviceV4L2Thread(VideoDevice *device, int color_model)
00115 : Thread(1, 0, 0)
00116 {
00117 this->device = device;
00118 this->color_model = color_model;
00119
00120 video_lock = new Condition(0, "VDeviceV4L2Thread::video_lock");
00121 buffer_lock = new Mutex("VDeviceV4L2Thread::buffer_lock");
00122 ioctl_lock = new Mutex("VDeviceV4L2Thread::ioctl_lock");
00123 device_buffers = 0;
00124 buffer_valid = 0;
00125 current_inbuffer = 0;
00126 current_outbuffer = 0;
00127 total_buffers = 0;
00128 first_frame = 1;
00129 done = 0;
00130 input_fd = 0;
00131 total_valid = 0;
00132 put_thread = 0;
00133 }
00134
00135 VDeviceV4L2Thread::~VDeviceV4L2Thread()
00136 {
00137 if(Thread::running())
00138 {
00139 done = 1;
00140 Thread::cancel();
00141 Thread::join();
00142 }
00143
00144 if(put_thread) delete put_thread;
00145
00146 if(buffer_valid)
00147 {
00148 delete [] buffer_valid;
00149 }
00150
00151
00152 if(device_buffers)
00153 {
00154 for(int i = 0; i < total_buffers; i++)
00155 {
00156 if(color_model == BC_COMPRESSED)
00157 {
00158 if(device_buffers[i]->get_data())
00159 munmap(device_buffers[i]->get_data(),
00160 device_buffers[i]->get_compressed_allocated());
00161 }
00162 else
00163 {
00164 if(device_buffers[i]->get_data())
00165 munmap(device_buffers[i]->get_data(),
00166 device_buffers[i]->get_data_size());
00167 }
00168 delete device_buffers[i];
00169 }
00170 delete [] device_buffers;
00171 }
00172
00173 if(input_fd > 0)
00174 {
00175 int streamoff_arg = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00176 if(ioctl(input_fd, VIDIOC_STREAMOFF, &streamoff_arg) < 0)
00177 perror("VDeviceV4L2Thread::~VDeviceV4L2Thread VIDIOC_STREAMOFF");
00178 close(input_fd);
00179 }
00180
00181 delete video_lock;
00182 delete buffer_lock;
00183 delete ioctl_lock;
00184 }
00185
00186 void VDeviceV4L2Thread::start()
00187 {
00188 total_buffers = device->in_config->capture_length;
00189 total_buffers = MAX(total_buffers, 2);
00190 total_buffers = MIN(total_buffers, 0xff);
00191 put_thread = new VDeviceV4L2Put(this);
00192 put_thread->start();
00193 Thread::start();
00194 }
00195
00196
00197 void VDeviceV4L2Thread::allocate_buffers(int number)
00198 {
00199 if(number != total_buffers)
00200 {
00201 if(buffer_valid) delete [] buffer_valid;
00202 if(device_buffers)
00203 {
00204 for(int i = 0; i < total_buffers; i++)
00205 {
00206 delete device_buffers[i];
00207 }
00208 delete [] device_buffers;
00209 }
00210 }
00211
00212 total_buffers = number;
00213 buffer_valid = new int[total_buffers];
00214 device_buffers = new VFrame*[total_buffers];
00215 for(int i = 0; i < total_buffers; i++)
00216 {
00217 device_buffers[i] = new VFrame;
00218 }
00219 bzero(buffer_valid, sizeof(int) * total_buffers);
00220 }
00221
00222 void VDeviceV4L2Thread::run()
00223 {
00224
00225 int error = 0;
00226 Thread::enable_cancel();
00227
00228
00229
00230 if((input_fd = open(device->in_config->v4l2jpeg_in_device,
00231 O_RDWR)) < 0)
00232 {
00233 perror("VDeviceV4L2Thread::run");
00234 error = 1;
00235 }
00236
00237 if(!error)
00238 {
00239 device->set_cloexec_flag(input_fd, 1);
00240
00241
00242 struct v4l2_capability cap;
00243 if(ioctl(input_fd, VIDIOC_QUERYCAP, &cap))
00244 perror("VDeviceV4L2Thread::run VIDIOC_QUERYCAP");
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 struct v4l2_streamparm v4l2_parm;
00269 v4l2_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00270 if(ioctl(input_fd, VIDIOC_G_PARM, &v4l2_parm) < 0)
00271 perror("VDeviceV4L2Thread::run VIDIOC_G_PARM");
00272 if(v4l2_parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
00273 {
00274 v4l2_parm.parm.capture.capturemode |= V4L2_CAP_TIMEPERFRAME;
00275
00276
00277 v4l2_parm.parm.capture.timeperframe.numerator = 1;
00278 v4l2_parm.parm.capture.timeperframe.denominator =
00279 (unsigned long)((float)1 /
00280 device->frame_rate *
00281 10000000);
00282 if(ioctl(input_fd, VIDIOC_S_PARM, &v4l2_parm) < 0)
00283 perror("VDeviceV4L2Thread::run VIDIOC_S_PARM");
00284
00285 if(ioctl(input_fd, VIDIOC_G_PARM, &v4l2_parm) < 0)
00286 perror("VDeviceV4L2Thread::run VIDIOC_G_PARM");
00287 }
00288
00289
00290
00291 struct v4l2_format v4l2_params;
00292 v4l2_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00293 if(ioctl(input_fd, VIDIOC_G_FMT, &v4l2_params) < 0)
00294 perror("VDeviceV4L2Thread::run VIDIOC_G_FMT");
00295 v4l2_params.fmt.pix.width = device->in_config->w;
00296 v4l2_params.fmt.pix.height = device->in_config->h;
00297
00298 if(color_model == BC_COMPRESSED)
00299 v4l2_params.fmt.pix.pixelformat =
00300 V4L2_PIX_FMT_MJPEG;
00301 else
00302 v4l2_params.fmt.pix.pixelformat =
00303 VDeviceV4L2::cmodel_to_device(color_model);
00304
00305
00306 if(ioctl(input_fd, VIDIOC_S_FMT, &v4l2_params) < 0)
00307 perror("VDeviceV4L2Thread::run VIDIOC_S_FMT");
00308 if(ioctl(input_fd, VIDIOC_G_FMT, &v4l2_params) < 0)
00309 perror("VDeviceV4L2Thread::run VIDIOC_G_FMT");
00310
00311
00312 Channel *device_channel = 0;
00313 if(device->channel->input >= 0 &&
00314 device->channel->input < device->get_inputs()->total)
00315 {
00316 device_channel = device->get_inputs()->values[
00317 device->channel->input];
00318 }
00319
00320
00321 if(!device_channel)
00322 {
00323 if(device->get_inputs()->total)
00324 {
00325 device_channel = device->get_inputs()->values[0];
00326 printf("VDeviceV4L2Thread::run user channel not found. Using %s\n",
00327 device_channel->device_name);
00328 }
00329 else
00330 {
00331 printf("VDeviceV4L2Thread::run channel \"%s\" not found.\n",
00332 device->channel->title);
00333 }
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 PictureConfig *picture = device->picture;
00343 for(int i = 0; i < picture->controls.total; i++)
00344 {
00345 struct v4l2_control ctrl_arg;
00346 struct v4l2_queryctrl arg;
00347 PictureItem *item = picture->controls.values[i];
00348 arg.id = item->device_id;
00349 if(!ioctl(input_fd, VIDIOC_QUERYCTRL, &arg))
00350 {
00351 ctrl_arg.id = item->device_id;
00352 ctrl_arg.value = 0;
00353 if(ioctl(input_fd, VIDIOC_S_CTRL, &ctrl_arg) < 0)
00354 perror("VDeviceV4L2Thread::run VIDIOC_S_CTRL");
00355 }
00356 else
00357 {
00358 printf("VDeviceV4L2Thread::run VIDIOC_S_CTRL 1 id %d failed\n",
00359 item->device_id);
00360 }
00361 }
00362
00363 for(int i = 0; i < picture->controls.total; i++)
00364 {
00365 struct v4l2_control ctrl_arg;
00366 struct v4l2_queryctrl arg;
00367 PictureItem *item = picture->controls.values[i];
00368 arg.id = item->device_id;
00369 if(!ioctl(input_fd, VIDIOC_QUERYCTRL, &arg))
00370 {
00371 ctrl_arg.id = item->device_id;
00372 ctrl_arg.value = item->value;
00373 if(ioctl(input_fd, VIDIOC_S_CTRL, &ctrl_arg) < 0)
00374 perror("VDeviceV4L2Thread::run VIDIOC_S_CTRL");
00375 }
00376 else
00377 {
00378 printf("VDeviceV4L2Thread::run VIDIOC_S_CTRL 2 id %d failed\n",
00379 item->device_id);
00380 }
00381 }
00382
00383
00384
00385 struct v4l2_tuner tuner;
00386 int input = 0;
00387
00388 if(ioctl(input_fd, VIDIOC_G_TUNER, &tuner) < 0)
00389 perror("VDeviceV4L2Thread::run VIDIOC_G_INPUT");
00390
00391
00392
00393
00394 if(device_channel)
00395 {
00396 tuner.index = device_channel->device_index;
00397 input = device_channel->device_index;
00398 }
00399 else
00400 {
00401 tuner.index = 0;
00402 input = 0;
00403 }
00404
00405 tuner.type = V4L2_TUNER_ANALOG_TV;
00406 tuner.audmode = V4L2_TUNER_MODE_STEREO;
00407 tuner.rxsubchans = V4L2_TUNER_SUB_STEREO;
00408
00409 if(ioctl(input_fd, VIDIOC_S_INPUT, &input) < 0)
00410 perror("VDeviceV4L2Thread::run VIDIOC_S_INPUT");
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 v4l2_std_id std_id;
00421 switch(device->channel->norm)
00422 {
00423 case NTSC: std_id = V4L2_STD_NTSC; break;
00424 case PAL: std_id = V4L2_STD_PAL; break;
00425 case SECAM: std_id = V4L2_STD_SECAM; break;
00426 default: std_id = V4L2_STD_NTSC_M; break;
00427 }
00428
00429 if(ioctl(input_fd, VIDIOC_S_STD, &std_id))
00430 perror("VDeviceV4L2Thread::run VIDIOC_S_STD");
00431
00432
00433 if(cap.capabilities & V4L2_CAP_TUNER)
00434 {
00435 if(ioctl(input_fd, VIDIOC_S_TUNER, &tuner) < 0)
00436 perror("VDeviceV4L2Thread::run VIDIOC_S_TUNER");
00437
00438 struct v4l2_frequency frequency;
00439 frequency.tuner = device->channel->tuner;
00440 frequency.type = V4L2_TUNER_ANALOG_TV;
00441 frequency.frequency = (int)(chanlists[
00442 device->channel->freqtable].list[
00443 device->channel->entry].freq * 0.016);
00444
00445
00446
00447
00448 if(ioctl(input_fd, VIDIOC_S_FREQUENCY, &frequency) < 0)
00449 perror("VDeviceV4L2Thread::run VIDIOC_S_FREQUENCY");
00450 }
00451
00452
00453
00454
00455 if(color_model == BC_COMPRESSED)
00456 {
00457 struct v4l2_jpegcompression jpeg_arg;
00458 if(ioctl(input_fd, VIDIOC_G_JPEGCOMP, &jpeg_arg) < 0)
00459 perror("VDeviceV4L2Thread::run VIDIOC_G_JPEGCOMP");
00460 jpeg_arg.quality = device->quality / 2;
00461 if(ioctl(input_fd, VIDIOC_S_JPEGCOMP, &jpeg_arg) < 0)
00462 perror("VDeviceV4L2Thread::run VIDIOC_S_JPEGCOMP");
00463 }
00464
00465
00466 Thread::disable_cancel();
00467 struct v4l2_requestbuffers requestbuffers;
00468
00469 printf("VDeviceV4L2Thread::run requested %d buffers\n", total_buffers);
00470 requestbuffers.count = total_buffers;
00471 requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00472 requestbuffers.memory = V4L2_MEMORY_MMAP;
00473 if(ioctl(input_fd, VIDIOC_REQBUFS, &requestbuffers) < 0)
00474 {
00475 perror("VDeviceV4L2Thread::run VIDIOC_REQBUFS");
00476 error = 1;
00477 }
00478 else
00479 {
00480
00481 allocate_buffers(requestbuffers.count);
00482 printf("VDeviceV4L2Thread::run got %d buffers\n", total_buffers);
00483 for(int i = 0; i < total_buffers; i++)
00484 {
00485 struct v4l2_buffer buffer;
00486 buffer.type = requestbuffers.type;
00487 buffer.index = i;
00488 if(ioctl(input_fd, VIDIOC_QUERYBUF, &buffer) < 0)
00489 {
00490 perror("VDeviceV4L2Thread::run VIDIOC_QUERYBUF");
00491 error = 1;
00492 break;
00493 }
00494
00495 unsigned char *data = (unsigned char*)mmap(NULL,
00496 buffer.length,
00497 PROT_READ | PROT_WRITE,
00498 MAP_SHARED,
00499 input_fd,
00500 buffer.m.offset);
00501 if(data == MAP_FAILED)
00502 {
00503 perror("VDeviceV4L2Thread::run mmap");
00504 error = 1;
00505 break;
00506 }
00507
00508 VFrame *frame = device_buffers[i];
00509 if(color_model == BC_COMPRESSED)
00510 {
00511 frame->set_compressed_memory(data,
00512 0,
00513 buffer.length);
00514 }
00515 else
00516 {
00517 int y_offset = 0;
00518 int u_offset = 0;
00519 int v_offset = 0;
00520
00521 switch(color_model)
00522 {
00523 case BC_YUV422P:
00524 u_offset = device->in_config->w * device->in_config->h;
00525 v_offset = device->in_config->w * device->in_config->h + device->in_config->w * device->in_config->h / 2;
00526 break;
00527 case BC_YUV420P:
00528 case BC_YUV411P:
00529
00530 v_offset = device->in_config->w * device->in_config->h;
00531 u_offset = device->in_config->w * device->in_config->h + device->in_config->w * device->in_config->h / 4;
00532 break;
00533 }
00534
00535 frame->reallocate(data,
00536 y_offset,
00537 u_offset,
00538 v_offset,
00539 device->in_config->w,
00540 device->in_config->h,
00541 color_model,
00542 VFrame::calculate_bytes_per_pixel(color_model) *
00543 device->in_config->w);
00544 }
00545 }
00546 }
00547 Thread::enable_cancel();
00548 }
00549
00550
00551
00552
00553 if(!error)
00554 {
00555 for(int i = 0; i < total_buffers; i++)
00556 {
00557 struct v4l2_buffer buffer;
00558 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00559 buffer.index = i;
00560 if(ioctl(input_fd, VIDIOC_QBUF, &buffer) < 0)
00561 {
00562 perror("VDeviceV4L2Thread::run VIDIOC_QBUF");
00563 break;
00564 }
00565 }
00566
00567
00568 int streamon_arg = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00569 if(ioctl(input_fd, VIDIOC_STREAMON, &streamon_arg) < 0)
00570 perror("VDeviceV4L2Thread::run VIDIOC_STREAMON");
00571 }
00572
00573 Thread::disable_cancel();
00574
00575
00576
00577 first_frame = 0;
00578 while(!done && !error)
00579 {
00580 struct v4l2_buffer buffer;
00581 bzero(&buffer, sizeof(buffer));
00582 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00583 buffer.memory = V4L2_MEMORY_MMAP;
00584
00585
00586
00587 Thread::enable_cancel();
00588 ioctl_lock->lock("VDeviceV4L2Thread::run");
00589 int result = ioctl(input_fd, VIDIOC_DQBUF, &buffer);
00590 ioctl_lock->unlock();
00591
00592 usleep(1000000 * 1001 / 60000);
00593 Thread::disable_cancel();
00594
00595
00596 if(result < 0)
00597 {
00598 perror("VDeviceV4L2Thread::run VIDIOC_DQBUF");
00599 Thread::enable_cancel();
00600 usleep(100000);
00601 Thread::disable_cancel();
00602 }
00603 else
00604 {
00605 buffer_lock->lock("VDeviceV4L2Thread::run");
00606
00607
00608 current_inbuffer = buffer.index;
00609 if(color_model == BC_COMPRESSED)
00610 {
00611 device_buffers[current_inbuffer]->set_compressed_size(
00612 buffer.bytesused);
00613 }
00614
00615 if(!buffer_valid[current_inbuffer])
00616 {
00617
00618 buffer_valid[current_inbuffer] = 1;
00619 total_valid++;
00620 buffer_lock->unlock();
00621 video_lock->unlock();
00622 }
00623 else
00624 {
00625
00626 buffer_lock->unlock();
00627 video_lock->unlock();
00628 usleep(33000);
00629 }
00630 }
00631
00632 }
00633 }
00634
00635 VFrame* VDeviceV4L2Thread::get_buffer(int *timed_out)
00636 {
00637 VFrame *result = 0;
00638 *timed_out = 0;
00639
00640
00641 buffer_lock->lock("VDeviceV4L2Thread::get_buffer 1");
00642
00643
00644
00645 while(total_valid < 2 && !*timed_out && !first_frame)
00646 {
00647 buffer_lock->unlock();
00648 *timed_out = video_lock->timed_lock(BUFFER_TIMEOUT,
00649 "VDeviceV4L2Thread::read_frame 2");
00650 buffer_lock->lock("VDeviceV4L2Thread::get_buffer 3");
00651 }
00652
00653
00654 if(total_valid >= 2)
00655 {
00656 result = device_buffers[current_outbuffer];
00657 }
00658
00659 buffer_lock->unlock();
00660
00661 return result;
00662 }
00663
00664 void VDeviceV4L2Thread::put_buffer()
00665 {
00666 buffer_lock->lock("VDeviceV4L2Thread::put_buffer");
00667 buffer_valid[current_outbuffer] = 0;
00668
00669
00670 put_thread->put_buffer(current_outbuffer);
00671
00672 current_outbuffer++;
00673 total_valid--;
00674 if(current_outbuffer >= total_buffers)
00675 current_outbuffer = 0;
00676 buffer_lock->unlock();
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 VDeviceV4L2::VDeviceV4L2(VideoDevice *device)
00697 : VDeviceBase(device)
00698 {
00699 initialize();
00700 }
00701
00702 VDeviceV4L2::~VDeviceV4L2()
00703 {
00704 close_all();
00705 }
00706
00707 int VDeviceV4L2::close_all()
00708 {
00709 if(thread) delete thread;
00710 thread = 0;
00711 return 0;
00712 }
00713
00714
00715 int VDeviceV4L2::initialize()
00716 {
00717 thread = 0;
00718 return 0;
00719 }
00720
00721
00722
00723 int VDeviceV4L2::open_input()
00724 {
00725 int result = get_sources(device,
00726 device->in_config->v4l2_in_device);
00727 device->channel->use_frequency = 1;
00728 device->channel->use_fine = 1;
00729 return result;
00730 }
00731
00732 int VDeviceV4L2::get_sources(VideoDevice *device,
00733 char *path)
00734 {
00735 int input_fd = -1;
00736
00737
00738 device->channel->use_norm = 1;
00739 device->channel->use_input = 1;
00740 if(device->in_config->driver != VIDEO4LINUX2JPEG)
00741 device->channel->has_scanning = 1;
00742 else
00743 device->channel->has_scanning = 0;
00744
00745 if((input_fd = open(path, O_RDWR)) < 0)
00746 {
00747 perror("VDeviceV4L::open_input");
00748 return 1;
00749 }
00750 else
00751 {
00752
00753 int i = 0;
00754 int done = 0;
00755 char *new_source;
00756
00757 while(!done && i < 20)
00758 {
00759 struct v4l2_input arg;
00760 bzero(&arg, sizeof(arg));
00761 arg.index = i;
00762
00763 if(ioctl(input_fd, VIDIOC_ENUMINPUT, &arg) < 0)
00764 {
00765
00766 done = 1;
00767 }
00768 else
00769 {
00770 Channel *channel = device->new_input_source((char*)arg.name);
00771 channel->device_index = i;
00772 channel->tuner = arg.tuner;
00773 }
00774 i++;
00775 }
00776
00777
00778 for(i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++)
00779 {
00780 struct v4l2_queryctrl arg;
00781 bzero(&arg, sizeof(arg));
00782 arg.id = i;
00783
00784 if(!ioctl(input_fd, VIDIOC_QUERYCTRL, &arg))
00785 {
00786
00787 if(!device->picture->get_item((const char*)arg.name, arg.id))
00788 {
00789
00790 PictureItem *item = device->picture->new_item((const char*)arg.name);
00791 item->device_id = arg.id;
00792 item->min = arg.minimum;
00793 item->max = arg.maximum;
00794 item->step = arg.step;
00795 item->default_ = arg.default_value;
00796 item->type = arg.type;
00797 item->value = arg.default_value;
00798 }
00799 }
00800 }
00801
00802
00803 device->picture->load_defaults();
00804
00805 close(input_fd);
00806 }
00807 return 0;
00808 }
00809
00810 int VDeviceV4L2::cmodel_to_device(int color_model)
00811 {
00812 switch(color_model)
00813 {
00814 case BC_YUV422:
00815 return V4L2_PIX_FMT_YUYV;
00816 break;
00817 case BC_YUV411P:
00818 return V4L2_PIX_FMT_Y41P;
00819 break;
00820 case BC_YUV420P:
00821 return V4L2_PIX_FMT_YVU420;
00822 break;
00823 case BC_YUV422P:
00824 return V4L2_PIX_FMT_YUV422P;
00825 break;
00826 case BC_RGB888:
00827 return V4L2_PIX_FMT_RGB24;
00828 break;
00829 }
00830 return 0;
00831 }
00832
00833 int VDeviceV4L2::get_best_colormodel(Asset *asset)
00834 {
00835 int result = BC_RGB888;
00836 result = File::get_best_colormodel(asset, device->in_config->driver);
00837 return result;
00838 }
00839
00840 int VDeviceV4L2::has_signal()
00841 {
00842 if(thread)
00843 {
00844 struct v4l2_tuner tuner;
00845 if(ioctl(thread->input_fd, VIDIOC_G_TUNER, &tuner) < 0)
00846 perror("VDeviceV4L2::has_signal VIDIOC_S_TUNER");
00847 return tuner.signal;
00848 }
00849 return 0;
00850 }
00851
00852 int VDeviceV4L2::read_buffer(VFrame *frame)
00853 {
00854 int result = 0;
00855
00856 if((device->channel_changed || device->picture_changed) && thread)
00857 {
00858 delete thread;
00859 thread = 0;
00860 }
00861
00862 if(!thread)
00863 {
00864 device->channel_changed = 0;
00865 device->picture_changed = 0;
00866 thread = new VDeviceV4L2Thread(device, frame->get_color_model());
00867 thread->start();
00868 }
00869
00870
00871
00872 int timed_out;
00873 VFrame *buffer = thread->get_buffer(&timed_out);
00874 if(buffer)
00875 {
00876 frame->copy_from(buffer);
00877 thread->put_buffer();
00878 }
00879 else
00880 {
00881
00882 if(timed_out)
00883 {
00884 delete thread;
00885 thread = 0;
00886 }
00887 result = 1;
00888 }
00889
00890
00891 return result;
00892 }
00893
00894 #endif