r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / vdevicev4l2.C
blob1246ec18a2e720d24ce22b4ad35fe4eda4e8ff1f
1 #undef _FILE_OFFSET_BITS
2 #undef _LARGEFILE_SOURCE
3 #undef _LARGEFILE64_SOURCE
5 #include "assets.h"
6 #include "channel.h"
7 #include "chantables.h"
8 #include "clip.h"
9 #include "condition.h"
10 #include "file.h"
11 #include "picture.h"
12 #include "preferences.h"
13 #include "quicktime.h"
14 #include "recordconfig.h"
15 #include "vdevicev4l2.h"
16 #include "vframe.h"
17 #include "videodevice.h"
19 #ifdef HAVE_VIDEO4LINUX2
21 #include <unistd.h>
22 #include <sys/ioctl.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25 #include <string.h>
33 VDeviceV4L2Put::VDeviceV4L2Put(VDeviceV4L2Thread *thread)
34  : Thread(1, 0, 0)
36         this->thread = thread;
37         done = 0;
38         lock = new Mutex("VDeviceV4L2Put::lock");
39         more_buffers = new Condition(0, "VDeviceV4L2Put::more_buffers");
40         putbuffers = new int[0xff];
41         total = 0;
44 VDeviceV4L2Put::~VDeviceV4L2Put()
46         if(Thread::running())
47         {
48                 done = 1;
49                 more_buffers->unlock();
50                 Thread::cancel();
51                 Thread::join();
52         }
53         delete lock;
54         delete more_buffers;
55         delete [] putbuffers;
58 void VDeviceV4L2Put::run()
60         while(!done)
61         {
62                 more_buffers->lock("VDeviceV4L2Put::run");
63                 if(done) break;
64                 lock->lock("VDeviceV4L2Put::run");
65                 int buffer = -1;
66                 if(total)
67                 {
68                         buffer = putbuffers[0];
69                         for(int i = 0; i < total - 1; i++)
70                                 putbuffers[i] = putbuffers[i + 1];
71                         total--;
72                 }
73                 lock->unlock();
75                 if(buffer >= 0)
76                 {
77                         struct v4l2_buffer arg;
78                         bzero(&arg, sizeof(arg));
79                         arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
80                         arg.index = buffer;
81                         arg.memory = V4L2_MEMORY_MMAP;
83                         Thread::enable_cancel();
84                         thread->ioctl_lock->lock("VDeviceV4L2Put::run");
85 // This locks up if there's no signal.
86                         if(ioctl(thread->input_fd, VIDIOC_QBUF, &arg) < 0)
87                                 perror("VDeviceV4L2Put::run 1 VIDIOC_QBUF");
88                         thread->ioctl_lock->unlock();
89 // Delay to keep mutexes from getting stuck
90                         usleep(1000000 * 1001 / 60000);
91                         Thread::disable_cancel();
92                 }
93         }
96 void VDeviceV4L2Put::put_buffer(int number)
98         lock->lock("VDeviceV4L2Put::put_buffer");
99         putbuffers[total++] = number;
100         lock->unlock();
101         more_buffers->unlock();
114 VDeviceV4L2Thread::VDeviceV4L2Thread(VideoDevice *device, int color_model)
115  : Thread(1, 0, 0)
117         this->device = device;
118         this->color_model = color_model;
120         video_lock = new Condition(0, "VDeviceV4L2Thread::video_lock");
121         buffer_lock = new Mutex("VDeviceV4L2Thread::buffer_lock");
122         ioctl_lock = new Mutex("VDeviceV4L2Thread::ioctl_lock");
123         device_buffers = 0;
124         buffer_valid = 0;
125         current_inbuffer = 0;
126         current_outbuffer = 0;
127         total_buffers = 0;
128         first_frame = 1;
129         done = 0;
130         input_fd = 0;
131         total_valid = 0;
132         put_thread = 0;
135 VDeviceV4L2Thread::~VDeviceV4L2Thread()
137         if(Thread::running())
138         {
139                 done = 1;
140                 Thread::cancel();
141                 Thread::join();
142         }
144         if(put_thread) delete put_thread;
146         if(buffer_valid)
147         {
148                 delete [] buffer_valid;
149         }
151 // Buffers are not unmapped by close.
152         if(device_buffers)
153         {
154                 for(int i = 0; i < total_buffers; i++)
155                 {
156                         if(color_model == BC_COMPRESSED)
157                         {
158                                 if(device_buffers[i]->get_data()) 
159                                         munmap(device_buffers[i]->get_data(),
160                                                 device_buffers[i]->get_compressed_allocated());
161                         }
162                         else
163                         {
164                                 if(device_buffers[i]->get_data()) 
165                                         munmap(device_buffers[i]->get_data(),
166                                                 device_buffers[i]->get_data_size());
167                         }
168                         delete device_buffers[i];
169                 }
170                 delete [] device_buffers;
171         }
173         if(input_fd > 0) 
174         {
175                 int streamoff_arg = V4L2_BUF_TYPE_VIDEO_CAPTURE;
176                 if(ioctl(input_fd, VIDIOC_STREAMOFF, &streamoff_arg) < 0)
177                         perror("VDeviceV4L2Thread::~VDeviceV4L2Thread VIDIOC_STREAMOFF");
178                 close(input_fd);
179         }
181         delete video_lock;
182         delete buffer_lock;
183         delete ioctl_lock;
186 void VDeviceV4L2Thread::start()
188         total_buffers = device->in_config->capture_length;
189         total_buffers = MAX(total_buffers, 2);
190         total_buffers = MIN(total_buffers, 0xff);
191         put_thread = new VDeviceV4L2Put(this);
192         put_thread->start();
193         Thread::start();
196 // Allocate user space buffers
197 void VDeviceV4L2Thread::allocate_buffers(int number)
199         if(number != total_buffers)
200         {
201                 if(buffer_valid) delete [] buffer_valid;
202                 if(device_buffers)
203                 {
204                         for(int i = 0; i < total_buffers; i++)
205                         {
206                                 delete device_buffers[i];
207                         }
208                         delete [] device_buffers;
209                 }
210         }
212         total_buffers = number;
213         buffer_valid = new int[total_buffers];
214         device_buffers = new VFrame*[total_buffers];
215         for(int i = 0; i < total_buffers; i++)
216         {
217                 device_buffers[i] = new VFrame;
218         }
219         bzero(buffer_valid, sizeof(int) * total_buffers);
222 void VDeviceV4L2Thread::run()
224 // Set up the device
225         int error = 0;
226         Thread::enable_cancel();
230         if((input_fd = open(device->in_config->v4l2jpeg_in_device, 
231                 O_RDWR)) < 0)
232         {
233                 perror("VDeviceV4L2Thread::run");
234                 error = 1;
235         }
237         if(!error)
238         {
239                 device->set_cloexec_flag(input_fd, 1);
242                 struct v4l2_capability cap;
243                 if(ioctl(input_fd, VIDIOC_QUERYCAP, &cap))
244                         perror("VDeviceV4L2Thread::run VIDIOC_QUERYCAP");
246 // printf("VDeviceV4L2Thread::run input_fd=%d driver=%s card=%s bus_info=%s version=%d\n",
247 // input_fd,
248 // cap.driver,
249 // cap.card,
250 // cap.bus_info,
251 // cap.version);
252 // printf("    %s%s%s%s%s%s%s%s%s%s%s%s\n", 
253 // (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ? "V4L2_CAP_VIDEO_CAPTURE " : "",
254 // (cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) ? "V4L2_CAP_VIDEO_OUTPUT " : "",
255 // (cap.capabilities & V4L2_CAP_VIDEO_OVERLAY) ? "V4L2_CAP_VIDEO_OVERLAY " : "",
256 // (cap.capabilities & V4L2_CAP_VBI_CAPTURE) ? "V4L2_CAP_VBI_CAPTURE " : "",
257 // (cap.capabilities & V4L2_CAP_VBI_OUTPUT) ? "V4L2_CAP_VBI_OUTPUT " : "",
258 // (cap.capabilities & V4L2_CAP_RDS_CAPTURE) ? "V4L2_CAP_RDS_CAPTURE " : "",
259 // (cap.capabilities & V4L2_CAP_TUNER) ? "V4L2_CAP_TUNER " : "",
260 // (cap.capabilities & V4L2_CAP_AUDIO) ? "V4L2_CAP_AUDIO " : "",
261 // (cap.capabilities & V4L2_CAP_RADIO) ? "V4L2_CAP_RADIO " : "",
262 // (cap.capabilities & V4L2_CAP_READWRITE) ? "V4L2_CAP_READWRITE " : "",
263 // (cap.capabilities & V4L2_CAP_ASYNCIO) ? "V4L2_CAP_ASYNCIO " : "",
264 // (cap.capabilities & V4L2_CAP_STREAMING) ? "V4L2_CAP_STREAMING " : "");
267 // Set up frame rate
268                 struct v4l2_streamparm v4l2_parm;
269                 v4l2_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
270                 if(ioctl(input_fd, VIDIOC_G_PARM, &v4l2_parm) < 0)
271                         perror("VDeviceV4L2Thread::run VIDIOC_G_PARM");
272                 if(v4l2_parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
273                 {
274                         v4l2_parm.parm.capture.capturemode |= V4L2_CAP_TIMEPERFRAME;
277                         v4l2_parm.parm.capture.timeperframe.numerator = 1;
278                         v4l2_parm.parm.capture.timeperframe.denominator = 
279                                 (unsigned long)((float)1 / 
280                                 device->frame_rate * 
281                                 10000000);
282                         if(ioctl(input_fd, VIDIOC_S_PARM, &v4l2_parm) < 0)
283                                 perror("VDeviceV4L2Thread::run VIDIOC_S_PARM");
285                         if(ioctl(input_fd, VIDIOC_G_PARM, &v4l2_parm) < 0)
286                                 perror("VDeviceV4L2Thread::run VIDIOC_G_PARM");
287                 }
290 // Set up data format
291                 struct v4l2_format v4l2_params;
292                 v4l2_params.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
293                 if(ioctl(input_fd, VIDIOC_G_FMT, &v4l2_params) < 0)
294                         perror("VDeviceV4L2Thread::run VIDIOC_G_FMT");
295                 v4l2_params.fmt.pix.width = device->in_config->w;
296                 v4l2_params.fmt.pix.height = device->in_config->h;
298                 if(color_model == BC_COMPRESSED)
299                         v4l2_params.fmt.pix.pixelformat = 
300                                 V4L2_PIX_FMT_MJPEG;
301                 else
302                         v4l2_params.fmt.pix.pixelformat = 
303                                 VDeviceV4L2::cmodel_to_device(color_model);
306                 if(ioctl(input_fd, VIDIOC_S_FMT, &v4l2_params) < 0)
307                         perror("VDeviceV4L2Thread::run VIDIOC_S_FMT");
308                 if(ioctl(input_fd, VIDIOC_G_FMT, &v4l2_params) < 0)
309                         perror("VDeviceV4L2Thread::run VIDIOC_G_FMT");
311 // Set input
312                 Channel *device_channel = 0;
313                 if(device->channel->input >= 0 &&
314                         device->channel->input < device->get_inputs()->total)
315                 {
316                         device_channel = device->get_inputs()->values[
317                                 device->channel->input];
318                 }
320 // Try first input
321                 if(!device_channel)
322                 {
323                         if(device->get_inputs()->total)
324                         {
325                                 device_channel = device->get_inputs()->values[0];
326                                 printf("VDeviceV4L2Thread::run user channel not found.  Using %s\n",
327                                         device_channel->device_name);
328                         }
329                         else
330                         {
331                                 printf("VDeviceV4L2Thread::run channel \"%s\" not found.\n",
332                                         device->channel->title);
333                         }
334                 }
336 // Translate input to API structures
337                 struct v4l2_tuner tuner;
338                 int input = 0;
339                 if(device_channel)
340                 {
341                         tuner.index = device_channel->device_index;
342                         input = device_channel->device_index;
343                 }
344                 else
345                 {
346                         tuner.index = 0;
347                         input = 0;
348                 }
350                 tuner.type = V4L2_TUNER_ANALOG_TV;
353                 if(ioctl(input_fd, VIDIOC_S_INPUT, &input) < 0)
354                         perror("VDeviceV4L2Thread::run VIDIOC_S_INPUT");
356                 if(cap.capabilities & V4L2_CAP_TUNER)
357                 {
358                         if(ioctl(input_fd, VIDIOC_S_TUNER, &tuner) < 0)
359                                 perror("VDeviceV4L2Thread::run VIDIOC_S_TUNER");
360 // Set frequency
361                         struct v4l2_frequency frequency;
362                         frequency.tuner = device->channel->tuner;
363                         frequency.type = V4L2_TUNER_ANALOG_TV;
364                         frequency.frequency = chanlists[
365                                 device->channel->freqtable].list[
366                                         device->channel->entry].freq;
367                         if(ioctl(input_fd, VIDIOC_S_FREQUENCY, &frequency) < 0)
368                                 perror("VDeviceV4L2Thread::run VIDIOC_S_FREQUENCY");
369                 }
371 // Set norm
372                 v4l2_std_id std_id;
373                 switch(device->channel->norm)
374                 {
375                         case NTSC: std_id = V4L2_STD_NTSC; break;
376                         case PAL: std_id = V4L2_STD_PAL; break;
377                         case SECAM: std_id = V4L2_STD_SECAM; break;
378                         default: std_id = V4L2_STD_NTSC_M; break;
379                 }
381                 if(ioctl(input_fd, VIDIOC_S_STD, &std_id))
382                         perror("VDeviceV4L2Thread::run VIDIOC_S_STD");
385 // printf("VDeviceV4L2Thread::run input=%d norm=%d\n",
386 // device->channel->input,
387 // device->channel->norm);
389 // Set picture controls
390                 Picture *picture = device->picture;
391                 for(int i = 0; i < picture->controls.total; i++)
392                 {
393                         struct v4l2_control ctrl_arg;
394                         PictureItem *item = picture->controls.values[i];
395 //printf("VDeviceV4L2Thread::run %x %d\n", item->device_id, item->value);
396                         ctrl_arg.id = item->device_id;
397                         ctrl_arg.value = item->value;
398                         if(ioctl(input_fd, VIDIOC_S_CTRL, &ctrl_arg) < 0)
399                                 perror("VDeviceV4L2Thread::run VIDIOC_S_CTRL");
400                 }
402 // Set compression
403                 if(color_model == BC_COMPRESSED)
404                 {
405                         struct v4l2_jpegcompression jpeg_arg;
406                         if(ioctl(input_fd, VIDIOC_G_JPEGCOMP, &jpeg_arg) < 0)
407                                 perror("VDeviceV4L2Thread::run VIDIOC_G_JPEGCOMP");
408                         jpeg_arg.quality = device->quality / 2;
409                         if(ioctl(input_fd, VIDIOC_S_JPEGCOMP, &jpeg_arg) < 0)
410                                 perror("VDeviceV4L2Thread::run VIDIOC_S_JPEGCOMP");
411                 }
413 // Allocate buffers.  Errors here are fatal.
414                 Thread::disable_cancel();
415                 struct v4l2_requestbuffers requestbuffers;
417 printf("VDeviceV4L2Thread::run requested %d buffers\n", total_buffers);
418                 requestbuffers.count = total_buffers;
419                 requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
420                 requestbuffers.memory = V4L2_MEMORY_MMAP;
421                 if(ioctl(input_fd, VIDIOC_REQBUFS, &requestbuffers) < 0)
422                 {
423                         perror("VDeviceV4L2Thread::run VIDIOC_REQBUFS");
424                         error = 1;
425                 }
426                 else
427                 {
428 // The requestbuffers.count changes in the 2.6.5 version of the API
429                         allocate_buffers(requestbuffers.count);
430 printf("VDeviceV4L2Thread::run got %d buffers\n", total_buffers);
431                         for(int i = 0; i < total_buffers; i++)
432                         {
433                                 struct v4l2_buffer buffer;
434                                 buffer.type = requestbuffers.type;
435                                 buffer.index = i;
436                                 if(ioctl(input_fd, VIDIOC_QUERYBUF, &buffer) < 0)
437                                 {
438                                         perror("VDeviceV4L2Thread::run VIDIOC_QUERYBUF");
439                                         error = 1;
440                                         break;
441                                 }
443                                 unsigned char *data = (unsigned char*)mmap(NULL,
444                                         buffer.length,
445                                         PROT_READ | PROT_WRITE,
446                                         MAP_SHARED,
447                                         input_fd,
448                                         buffer.m.offset);
449                                 if(data == MAP_FAILED)
450                                 {
451                                         perror("VDeviceV4L2Thread::run mmap");
452                                         error = 1;
453                                         break;
454                                 }
456                                 VFrame *frame = device_buffers[i];
457                                 if(color_model == BC_COMPRESSED)
458                                 {
459                                         frame->set_compressed_memory(data,
460                                                 0,
461                                                 buffer.length);
462                                 }
463                                 else
464                                 {
465                                         int y_offset = 0;
466                                         int u_offset = 0;
467                                         int v_offset = 0;
469                                         switch(color_model)
470                                         {
471                                                 case BC_YUV422P:
472                                                         u_offset = device->in_config->w * device->in_config->h;
473                                                         v_offset = device->in_config->w * device->in_config->h + device->in_config->w * device->in_config->h / 2;
474                                                         break;
475                                                 case BC_YUV420P:
476                                                 case BC_YUV411P:
477 // In 2.6.7, the v and u are inverted for 420 but not 422
478                                                         v_offset = device->in_config->w * device->in_config->h;
479                                                         u_offset = device->in_config->w * device->in_config->h + device->in_config->w * device->in_config->h / 4;
480                                                         break;
481                                         }
483                                         frame->reallocate(data,
484                                                 y_offset,
485                                                 u_offset,
486                                                 v_offset,
487                                                 device->in_config->w,
488                                                 device->in_config->h,
489                                                 color_model,
490                                                 VFrame::calculate_bytes_per_pixel(color_model) *
491                                                         device->in_config->w);
492                                 }
493                         }
494                 }
495                 Thread::enable_cancel();
496         }
499 // Start capturing
500         if(!error)
501         {
502                 for(int i = 0; i < total_buffers; i++)
503                 {
504                         struct v4l2_buffer buffer;
505                         buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
506                         buffer.index = i;
507                         if(ioctl(input_fd, VIDIOC_QBUF, &buffer) < 0)
508                         {
509                                 perror("VDeviceV4L2Thread::run VIDIOC_QBUF");
510                                 break;
511                         }
512                 }
515                 int streamon_arg = V4L2_BUF_TYPE_VIDEO_CAPTURE;
516                 if(ioctl(input_fd, VIDIOC_STREAMON, &streamon_arg) < 0)
517                         perror("VDeviceV4L2Thread::run VIDIOC_STREAMON");
518         }
520         Thread::disable_cancel();
523 // Read buffers continuously
524         first_frame = 0;
525         while(!done && !error)
526         {
527                 struct v4l2_buffer buffer;
528                 bzero(&buffer, sizeof(buffer));
529                 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
530                 buffer.memory = V4L2_MEMORY_MMAP;
532 // The driver returns the first buffer not queued, so only one buffer
533 // can be unqueued at a time.
534                 Thread::enable_cancel();
535                 ioctl_lock->lock("VDeviceV4L2Thread::run");
536                 int result = ioctl(input_fd, VIDIOC_DQBUF, &buffer);
537                 ioctl_lock->unlock();
538 // Delay so the mutexes don't get stuck
539                 usleep(1000000 * 1001 / 60000);
540                 Thread::disable_cancel();
543                 if(result < 0)
544                 {
545                         perror("VDeviceV4L2Thread::run VIDIOC_DQBUF");
546                         Thread::enable_cancel();
547                         usleep(100000);
548                         Thread::disable_cancel();
549                 }
550                 else
551                 {
552                         buffer_lock->lock("VDeviceV4L2Thread::run");
554 // Set output frame as valid and set data size
555                         current_inbuffer = buffer.index;
556                         if(color_model == BC_COMPRESSED)
557                         {
558                                 device_buffers[current_inbuffer]->set_compressed_size(
559                                         buffer.bytesused);
560                         }
562                         if(!buffer_valid[current_inbuffer])
563                         {
564 // Increase valid total only if current is invalid
565                                 buffer_valid[current_inbuffer] = 1;
566                                 total_valid++;
567                                 buffer_lock->unlock();
568                                 video_lock->unlock();
569                         }
570                         else
571                         {
572 // Driver won't block on the next QBUF call because we're not requeueing the buffer.
573                                 buffer_lock->unlock();
574                                 video_lock->unlock();
575                                 usleep(33000);
576                         }
577                 }
578 //printf("VDeviceV4L2::run 100 %lld\n", timer.get_difference());
579         }
582 VFrame* VDeviceV4L2Thread::get_buffer(int *timed_out)
584         VFrame *result = 0;
585         *timed_out = 0;
587 // Acquire buffer table
588         buffer_lock->lock("VDeviceV4L2Thread::get_buffer 1");
591 // Test for buffer availability
592         while(total_valid < 2 && !*timed_out && !first_frame)
593         {
594                 buffer_lock->unlock();
595                 *timed_out = video_lock->timed_lock(BUFFER_TIMEOUT, 
596                         "VDeviceV4L2Thread::read_frame 2");
597                 buffer_lock->lock("VDeviceV4L2Thread::get_buffer 3");
598         }
600 // Copy frame
601         if(total_valid >= 2)
602         {
603                 result = device_buffers[current_outbuffer];
604         }
606         buffer_lock->unlock();
608         return result;
611 void VDeviceV4L2Thread::put_buffer()
613         buffer_lock->lock("VDeviceV4L2Thread::put_buffer");
614         buffer_valid[current_outbuffer] = 0;
616 // Release buffer for capturing.
617         put_thread->put_buffer(current_outbuffer);
619         current_outbuffer++;
620         total_valid--;
621         if(current_outbuffer >= total_buffers)
622                 current_outbuffer = 0;
623         buffer_lock->unlock();
643 VDeviceV4L2::VDeviceV4L2(VideoDevice *device)
644  : VDeviceBase(device)
646         initialize();
649 VDeviceV4L2::~VDeviceV4L2()
651         close_all();
654 int VDeviceV4L2::close_all()
656         if(thread) delete thread;
657         thread = 0;
658         return 0;
662 int VDeviceV4L2::initialize()
664         thread = 0;
665         return 0;
670 int VDeviceV4L2::open_input()
672         int result = get_sources(device,
673                 device->in_config->v4l2_in_device);
674         device->channel->use_frequency = 1;
675         device->channel->use_fine = 1;
676         return result;
679 int VDeviceV4L2::get_sources(VideoDevice *device,
680         char *path)
682         int input_fd = -1;
684         device->channel->use_norm = 1;
685         device->channel->use_input = 1;
687         if((input_fd = open(path, O_RDWR)) < 0)
688         {
689                 perror("VDeviceV4L::open_input");
690                 return 1;
691         }
692         else
693         {
694 // Get the inputs
695                 int i = 0;
696                 int done = 0;
697                 char *new_source;
699                 while(!done && i < 20)
700                 {
701                         struct v4l2_input arg;
702                         bzero(&arg, sizeof(arg));
703                         arg.index = i;
704                         
705                         if(ioctl(input_fd, VIDIOC_ENUMINPUT, &arg) < 0)
706                         {
707 // Finished
708                                 done = 1;
709                         }
710                         else
711                         {
712                                 Channel *channel = device->new_input_source((char*)arg.name);
713                                 channel->device_index = i;
714                                 channel->tuner = arg.tuner;
715                         }
716                         i++;
717                 }
719 // Get the picture controls
720                 for(i = V4L2_CID_BASE; i < V4L2_CID_LASTP1; i++)
721                 {
722                         struct v4l2_queryctrl arg;
723                         bzero(&arg, sizeof(arg));
724                         arg.id = i;
725 // This returns errors for unsupported controls which is what we want.
726                         if(!ioctl(input_fd, VIDIOC_QUERYCTRL, &arg))
727                         {
728                                 PictureItem *item = device->picture->new_item((char*)arg.name);
729                                 item->device_id = arg.id;
730                                 item->min = arg.minimum;
731                                 item->max = arg.maximum;
732                                 item->step = arg.step;
733                                 item->default_ = arg.default_value;
734                                 item->type = arg.type;
735                                 item->value = arg.default_value;
736                         }
737                 }
739                 close(input_fd);
740         }
741         return 0;
744 int VDeviceV4L2::cmodel_to_device(int color_model)
746         switch(color_model)
747         {
748                 case BC_YUV422:
749                         return V4L2_PIX_FMT_YUYV;
750                         break;
751                 case BC_YUV411P:
752                         return V4L2_PIX_FMT_Y41P;
753                         break;
754                 case BC_YUV420P:
755                         return V4L2_PIX_FMT_YVU420;
756                         break;
757                 case BC_YUV422P:
758                         return V4L2_PIX_FMT_YUV422P;
759                         break;
760                 case BC_RGB888:
761                         return V4L2_PIX_FMT_RGB24;
762                         break;
763         }
764         return 0;
767 int VDeviceV4L2::get_best_colormodel(Asset *asset)
769         int result = BC_RGB888;
770         result = File::get_best_colormodel(asset, device->in_config->driver);
771         return result;
775 int VDeviceV4L2::read_buffer(VFrame *frame)
777         int result = 0;
779         if((device->channel_changed || device->picture_changed) && thread)
780         {
781                 delete thread;
782                 thread = 0;
783         }
785         if(!thread)
786         {
787                 device->channel_changed = 0;
788                 device->picture_changed = 0;
789                 thread = new VDeviceV4L2Thread(device, frame->get_color_model());
790                 thread->start();
791         }
794 // Get buffer from thread
795         int timed_out;
796         VFrame *buffer = thread->get_buffer(&timed_out);
797         if(buffer)
798         {
799                 frame->copy_from(buffer);
800                 thread->put_buffer();
801         }
802         else
803         {
804 // Driver in 2.6.4 needs to be restarted when it loses sync.
805                 if(timed_out)
806                 {
807                         delete thread;
808                         thread = 0;
809                 }
810                 result = 1;
811         }
814         return result;
817 #endif