1 // ALPHA C++ can't compile 64 bit headers
2 #undef _LARGEFILE_SOURCE
3 #undef _LARGEFILE64_SOURCE
4 #undef _FILE_OFFSET_BITS
8 #include "chantables.h"
10 #include "playbackconfig.h"
11 #include "preferences.h"
12 #include "recordconfig.h"
13 #include "strategies.inc"
14 #include "vdevicebuz.h"
16 #include "videoconfig.h"
17 #include "videodevice.h"
21 #include <linux/kernel.h>
22 //#include "videodev2.h"
23 #include <linux/videodev.h>
25 #include <sys/ioctl.h>
31 VDeviceBUZInput::VDeviceBUZInput(VDeviceBUZ *device)
34 this->device = device;
39 current_outbuffer = 0;
44 VDeviceBUZInput::~VDeviceBUZInput()
50 //printf("VDeviceBUZInput::~VDeviceBUZInput 1\n");
52 //printf("VDeviceBUZInput::~VDeviceBUZInput 100\n");
57 for(int i = 0; i < total_buffers; i++)
62 delete [] buffer_size;
66 void VDeviceBUZInput::start()
69 total_buffers = device->device->in_config->capture_length;
70 buffer = new char*[total_buffers];
71 buffer_size = new int[total_buffers];
72 bzero(buffer_size, sizeof(int) * total_buffers);
73 for(int i = 0; i < total_buffers; i++)
75 buffer[i] = new char[INPUT_BUFFER_SIZE];
81 void VDeviceBUZInput::run()
83 struct buz_sync bsync;
88 Thread::enable_cancel();
89 if(ioctl(device->jvideo_fd, BUZIOC_SYNC, &bsync) < 0)
91 perror("VDeviceBUZInput::run BUZIOC_SYNC");
93 Thread::disable_cancel();
97 Thread::disable_cancel();
103 // Save only if the current buffer is free.
104 if(!buffer_size[current_inbuffer])
107 // Copy to input buffer
108 memcpy(buffer[current_inbuffer],
109 device->input_buffer + bsync.frame * device->breq.size,
112 // Advance input buffer number and decrease semaphore.
113 buffer_size[current_inbuffer] = bsync.length;
114 increment_counter(¤t_inbuffer);
117 buffer_lock.unlock();
119 if(ioctl(device->jvideo_fd, BUZIOC_QBUF_CAPT, &bsync.frame))
120 perror("VDeviceBUZInput::run BUZIOC_QBUF_CAPT");
122 if(new_buffer) output_lock.unlock();
127 void VDeviceBUZInput::get_buffer(char **ptr, int *size)
129 // Increase semaphore to wait for buffer.
132 // Take over buffer table
134 *ptr = buffer[current_outbuffer];
135 *size = buffer_size[current_outbuffer];
136 buffer_lock.unlock();
139 void VDeviceBUZInput::put_buffer()
142 buffer_size[current_outbuffer] = 0;
143 buffer_lock.unlock();
144 increment_counter(¤t_outbuffer);
147 void VDeviceBUZInput::increment_counter(int *counter)
150 if(*counter >= total_buffers) *counter = 0;
153 void VDeviceBUZInput::decrement_counter(int *counter)
156 if(*counter < 0) *counter = total_buffers - 1;
162 VDeviceBUZ::VDeviceBUZ(VideoDevice *device)
163 : VDeviceBase(device)
166 render_strategies.append(VRENDER_MJPG);
169 VDeviceBUZ::~VDeviceBUZ()
171 //printf("VDeviceBUZ::~VDeviceBUZ 1\n");
173 //printf("VDeviceBUZ::~VDeviceBUZ 2\n");
176 int VDeviceBUZ::reset_parameters()
194 int VDeviceBUZ::close_input_core()
196 //printf("VDeviceBUZ::close_input_core 1\n");
206 if(jvideo_fd) close(jvideo_fd);
213 munmap(input_buffer, breq.count * breq.size);
217 //printf("VDeviceBUZ::close_input_core 2\n");
220 int VDeviceBUZ::close_output_core()
222 //printf("VDeviceBUZ::close_output_core 1\n");
226 // if(ioctl(jvideo_fd, BUZIOC_QBUF_PLAY, &n) < 0)
227 // perror("VDeviceBUZ::close_output_core BUZIOC_QBUF_PLAY");
228 if(jvideo_fd) close(jvideo_fd);
233 if(output_buffer > 0)
234 munmap(output_buffer, breq.count * breq.size);
252 //printf("VDeviceBUZ::close_output_core 2\n");
257 int VDeviceBUZ::close_all()
259 //printf("VDeviceBUZ::close_all 1\n");
261 //printf("VDeviceBUZ::close_all 1\n");
263 //printf("VDeviceBUZ::close_all 1\n");
264 if(frame_buffer) delete frame_buffer;
265 //printf("VDeviceBUZ::close_all 1\n");
267 //printf("VDeviceBUZ::close_all 2\n");
271 #define COMPOSITE_TEXT "Composite"
272 #define SVIDEO_TEXT "S-Video"
273 #define BUZ_COMPOSITE 0
276 void VDeviceBUZ::get_inputs(ArrayList<char *> *input_sources)
279 input_sources->append(new_source = new char[strlen(COMPOSITE_TEXT) + 1]);
280 strcpy(new_source, COMPOSITE_TEXT);
281 input_sources->append(new_source = new char[strlen(SVIDEO_TEXT) + 1]);
282 strcpy(new_source, SVIDEO_TEXT);
285 int VDeviceBUZ::open_input()
287 // Can't open input until after the channel is set
291 int VDeviceBUZ::open_output()
293 // Can't open output until after the channel is set
297 int VDeviceBUZ::set_channel(Channel *channel)
299 //printf("VDeviceBUZ::set_channel 1\n");
300 if(!channel) return 0;
306 open_input_core(channel);
311 open_output_core(channel);
314 //printf("VDeviceBUZ::set_channel 2\n");
320 void VDeviceBUZ::create_channeldb(ArrayList<Channel*> *channeldb)
325 int VDeviceBUZ::set_picture(int brightness,
333 struct video_picture picture_params;
334 brightness = (int)((float)brightness / 100 * 32767 + 32768);
335 hue = (int)((float)hue / 100 * 32767 + 32768);
336 color = (int)((float)color / 100 * 32767 + 32768);
337 contrast = (int)((float)contrast / 100 * 32767 + 32768);
338 whiteness = (int)((float)whiteness / 100 * 32767 + 32768);
339 if(ioctl(jvideo_fd, VIDIOCGPICT, &picture_params) < 0)
340 perror("VDeviceBUZ::set_picture VIDIOCGPICT");
341 picture_params.brightness = brightness;
342 picture_params.hue = hue;
343 picture_params.colour = color;
344 picture_params.contrast = contrast;
345 picture_params.whiteness = whiteness;
346 if(ioctl(jvideo_fd, VIDIOCSPICT, &picture_params) < 0)
347 perror("VDeviceBUZ::set_picture VIDIOCSPICT");
348 if(ioctl(jvideo_fd, VIDIOCGPICT, &picture_params) < 0)
349 perror("VDeviceBUZ::set_picture VIDIOCGPICT");
358 int VDeviceBUZ::get_norm(int norm)
362 case NTSC: return VIDEO_MODE_NTSC; break;
363 case PAL: return VIDEO_MODE_PAL; break;
364 case SECAM: return VIDEO_MODE_SECAM; break;
368 int VDeviceBUZ::read_buffer(VFrame *frame)
371 if(!jvideo_fd) open_input_core(0);
373 // Get buffer from thread
376 input_thread->get_buffer(&buffer, &buffer_size);
379 frame->allocate_compressed_data(buffer_size);
380 frame->set_compressed_size(buffer_size);
382 // Transfer fields to frame
383 if(device->odd_field_first)
385 long field2_offset = mjpeg_get_field2((unsigned char*)buffer, buffer_size);
386 long field1_len = field2_offset;
387 long field2_len = buffer_size - field2_offset;
389 memcpy(frame->get_data(), buffer + field2_offset, field2_len);
390 memcpy(frame->get_data() + field2_len, buffer, field1_len);
394 bcopy(buffer, frame->get_data(), buffer_size);
397 input_thread->put_buffer();
403 int VDeviceBUZ::open_input_core(Channel *channel)
405 //printf("VDeviceBUZ::open_input_core 1\n");
406 jvideo_fd = open(device->in_config->buz_in_device, O_RDONLY);
410 fprintf(stderr, "VDeviceBUZ::open_input %s: %s\n",
411 device->in_config->buz_in_device,
417 // Create input sources
418 get_inputs(&device->input_sources);
420 // Set current input source
423 for(int i = 0; i < 2; i++)
425 struct video_channel vch;
426 vch.channel = channel->input;
427 vch.norm = get_norm(channel->norm);
429 //printf("VDeviceBUZ::open_input_core 2 %d %d\n", vch.channel, vch.norm);
430 if(ioctl(jvideo_fd, VIDIOCSCHAN, &vch) < 0)
431 perror("VDeviceBUZ::open_input_core VIDIOCSCHAN ");
437 struct video_capability vc;
438 if(ioctl(jvideo_fd, VIDIOCGCAP, &vc) < 0)
439 perror("VDeviceBUZ::open_input VIDIOCGCAP");
441 // API dependant initialization
442 if(ioctl(jvideo_fd, BUZIOC_G_PARAMS, &bparm) < 0)
443 perror("VDeviceBUZ::open_input BUZIOC_G_PARAMS");
448 bparm.field_per_buff = 2;
449 bparm.img_width = device->in_config->w;
450 bparm.img_height = device->in_config->h / bparm.field_per_buff;
454 // bparm.APP_len = 14;
457 bparm.decimation = 0;
458 bparm.quality = device->quality;
459 bzero(bparm.APP_data, sizeof(bparm.APP_data));
461 if(ioctl(jvideo_fd, BUZIOC_S_PARAMS, &bparm) < 0)
462 perror("VDeviceBUZ::open_input BUZIOC_S_PARAMS");
464 // printf("open_input %d %d %d %d %d %d %d %d %d %d %d %d\n",
468 // bparm.field_per_buff,
478 breq.count = device->in_config->capture_length;
479 breq.size = INPUT_BUFFER_SIZE;
480 if(ioctl(jvideo_fd, BUZIOC_REQBUFS, &breq) < 0)
481 perror("VDeviceBUZ::open_input BUZIOC_REQBUFS");
483 //printf("open_input %s %d %d %d %d\n", device->in_config->buz_in_device, breq.count, breq.size, bparm.img_width, bparm.img_height);
484 if((input_buffer = (char*)mmap(0,
485 breq.count * breq.size,
490 perror("VDeviceBUZ::open_input mmap");
493 for(int i = 0; i < breq.count; i++)
495 if(ioctl(jvideo_fd, BUZIOC_QBUF_CAPT, &i) < 0)
496 perror("VDeviceBUZ::open_input BUZIOC_QBUF_CAPT");
500 input_thread = new VDeviceBUZInput(this);
501 input_thread->start();
502 //printf("VDeviceBUZ::open_input_core 2\n");
506 int VDeviceBUZ::open_output_core(Channel *channel)
508 //printf("VDeviceBUZ::open_output 1\n");
511 jvideo_fd = open(device->out_config->buz_out_device, O_RDWR);
514 perror("VDeviceBUZ::open_output");
519 // Set current input source
522 struct video_channel vch;
523 vch.channel = channel->input;
524 vch.norm = get_norm(channel->norm);
526 if(ioctl(jvideo_fd, VIDIOCSCHAN, &vch) < 0)
527 perror("VDeviceBUZ::open_output_core VIDIOCSCHAN ");
531 breq.size = INPUT_BUFFER_SIZE;
532 if(ioctl(jvideo_fd, BUZIOC_REQBUFS, &breq) < 0)
533 perror("VDeviceBUZ::open_output BUZIOC_REQBUFS");
534 if((output_buffer = (char*)mmap(0,
535 breq.count * breq.size,
536 PROT_READ | PROT_WRITE,
540 perror("VDeviceBUZ::open_output mmap");
542 if(ioctl(jvideo_fd, BUZIOC_G_PARAMS, &bparm) < 0)
543 perror("VDeviceBUZ::open_output BUZIOC_G_PARAMS");
545 bparm.decimation = 1;
547 bparm.field_per_buff = 2;
550 bparm.img_width = device->out_w;
551 bparm.img_height = device->out_h / bparm.field_per_buff;
556 if(ioctl(jvideo_fd, BUZIOC_S_PARAMS, &bparm) < 0)
557 perror("VDeviceBUZ::open_output BUZIOC_S_PARAMS");
558 //printf("VDeviceBUZ::open_output 2\n");
564 int VDeviceBUZ::write_buffer(VFrame **frames, EDL *edl)
566 //printf("VDeviceBUZ::write_buffer 1\n");
569 if(!jvideo_fd) open_output_core(0);
572 if(frames[0]->get_color_model() != BC_COMPRESSED)
574 if(!temp_frame) temp_frame = new VFrame;
577 mjpeg = mjpeg_new(device->out_w, device->out_h, 2);
578 mjpeg_set_quality(mjpeg, device->quality);
579 mjpeg_set_float(mjpeg, 0);
582 mjpeg_compress(mjpeg,
583 frames[0]->get_rows(),
587 frames[0]->get_color_model(),
589 temp_frame->allocate_compressed_data(mjpeg_output_size(mjpeg));
590 temp_frame->set_compressed_size(mjpeg_output_size(mjpeg));
591 bcopy(mjpeg_output_buffer(mjpeg), temp_frame->get_data(), mjpeg_output_size(mjpeg));
596 // Wait for frame to become available
597 // Caused close_output_core to lock up.
598 // if(total_loops >= 1)
600 // if(ioctl(jvideo_fd, BUZIOC_SYNC, &output_number) < 0)
601 // perror("VDeviceBUZ::write_buffer BUZIOC_SYNC");
604 if(device->out_config->buz_swap_fields)
606 long field2_offset = mjpeg_get_field2((unsigned char*)ptr->get_data(),
607 ptr->get_compressed_size());
608 long field2_len = ptr->get_compressed_size() - field2_offset;
609 memcpy(output_buffer + output_number * breq.size,
610 ptr->get_data() + field2_offset,
612 memcpy(output_buffer + output_number * breq.size +field2_len,
618 bcopy(ptr->get_data(),
619 output_buffer + output_number * breq.size,
620 ptr->get_compressed_size());
623 if(ioctl(jvideo_fd, BUZIOC_QBUF_PLAY, &output_number) < 0)
624 perror("VDeviceBUZ::write_buffer BUZIOC_QBUF_PLAY");
627 if(output_number >= breq.count)
633 //printf("VDeviceBUZ::write_buffer 2\n");
638 void VDeviceBUZ::new_output_buffer(VFrame **outputs,
641 //printf("VDeviceBUZ::new_output_buffer 1 %d\n", colormodel);
644 if(colormodel != user_frame->get_color_model())
656 user_frame = new VFrame;
659 user_frame = new VFrame(0,
667 user_frame->set_shm_offset(0);
668 outputs[0] = user_frame;
669 //printf("VDeviceBUZ::new_output_buffer 2\n");
673 ArrayList<int>* VDeviceBUZ::get_render_strategies()
675 return &render_strategies;