4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "playbackconfig.h"
26 #include "preferences.h"
27 #include "recordconfig.h"
28 #include "strategies.inc"
29 #include "vdevicelml.h"
31 #include "videoconfig.h"
32 #include "videodevice.h"
41 VDeviceLML::VDeviceLML(VideoDevice *device)
45 render_strategies.append(VRENDER_MJPG);
48 VDeviceLML::~VDeviceLML()
53 int VDeviceLML::reset_parameters()
61 input_position = INPUT_BUFFER_SIZE;
65 int VDeviceLML::open_input()
67 jvideo_fd = fopen(device->in_config->lml_in_device, "rb");
74 perror("VDeviceLML::open_input");
81 int VDeviceLML::open_output()
83 jvideo_fd = fopen(device->out_config->lml_out_device, "wb");
90 perror("VDeviceLML::open_output");
97 int VDeviceLML::close_all()
101 if(jvideo_fd) fclose(jvideo_fd);
105 if(jvideo_fd) fclose(jvideo_fd);
119 int VDeviceLML::read_buffer(VFrame *frame)
121 long first_field = 0, frame1_size = 0, frame2_size = 0, i;
122 int result = 0, frame_no = 0, retries = 0;
124 if(!jvideo_fd) return 1;
129 frame->set_compressed_size(0);
131 if(retries > 5) return 1;
133 // Keep reading until the first field of a frame arrives.
134 while(!input_error && !first_field)
136 // Get the first marker of a frame
137 while(!input_error && next_bytes(2) != SOI)
144 write_byte(get_byte());
145 write_byte(get_byte());
147 // Copy the first frame
148 while(!input_error && next_bytes(2) != EOI)
150 // Replace the LML header with a Quicktime header
151 if(next_bytes(2) == APP3)
160 get_byte(); // COMMENT
164 get_byte(); // Frame no
174 get_byte(); // framesize (useless since we have to swap frames)
178 frame_no = get_byte(); // frame seq no
179 frame_no |= (long)get_byte() << 8;
180 frame_no |= (long)get_byte() << 16;
181 frame_no |= (long)get_byte() << 24;
183 if(frame_no <= last_frame_no)
185 input_error = reopen_input();
192 last_frame_no = frame_no;
193 while(next_bytes(2) != 0xffdb) get_byte();
198 write_byte(get_byte());
203 write_byte(get_byte());
204 write_byte(get_byte());
207 frame1_size = frame_size;
209 // Read the second field
213 while(!input_error && next_bytes(2) != SOI)
219 write_byte(get_byte());
220 write_byte(get_byte());
222 // Store Quicktime header
225 // Copy the second frame
226 while(!input_error && next_bytes(2) != EOI)
228 write_byte(get_byte());
232 write_byte(get_byte());
233 write_byte(get_byte());
236 frame2_size = frame_size - frame1_size;
238 // Insert the required information
241 // Store in the VFrame
242 frame->allocate_compressed_data(frame_size);
244 // Quicktime expects the even field first
245 if(device->odd_field_first)
247 memcpy(frame->get_data(), frame_buffer + frame1_size, frame2_size);
248 memcpy(frame->get_data() + frame2_size, frame_buffer, frame1_size);
251 memcpy(frame->get_data(), frame_buffer, frame_size);
253 frame->set_compressed_size(frame_size);
265 int VDeviceLML::reopen_input()
269 fprintf(stderr, _("VDeviceLML::read_buffer: driver crash\n"));
272 input_error = open_input();
273 if(!input_error) fprintf(stderr, _("VDeviceLML::read_buffer: reopened\n"));
275 input_position = INPUT_BUFFER_SIZE;
280 int VDeviceLML::write_fake_marker()
289 for(int i = 0; i < 0x28; i++)
296 int VDeviceLML::refill_input()
298 // Shift remaining data up.
299 memcpy(input_buffer, input_buffer + input_position, INPUT_BUFFER_SIZE - input_position);
302 input_error = !fread(input_buffer + INPUT_BUFFER_SIZE - input_position,
303 INPUT_BUFFER_SIZE - (INPUT_BUFFER_SIZE - input_position),
312 int VDeviceLML::write_buffer(VFrame *frame, EDL *edl)
314 int result = 0, i, frame1size, j, size_qword, real_size, skip;
315 unsigned long size = frame->get_compressed_size();
316 unsigned char *data = frame->get_data();
317 unsigned char *data1;
318 int even_field_first = 1;
321 if(!jvideo_fd || frame->get_color_model() != VFRAME_COMPRESSED) return 1;
324 if(frame_allocated < size * 2)
332 frame_buffer = new unsigned char[size * 2];
335 for(data1 = data + 1, i = 0; i < size - 1; i++)
336 if(data[i] == ((EOI & 0xff00) >> 8) && data1[i] == (EOI & 0xff)) break;
341 if(even_field_first) i = 0;
344 frame_buffer[j++] = data[i++];
345 frame_buffer[j++] = data[i++];
347 // APP3 for LML driver
348 frame_buffer[j++] = (APP3 & 0xff00) >> 8;
349 frame_buffer[j++] = APP3 & 0xff;
350 frame_buffer[j++] = 0; // Marker size
351 frame_buffer[j++] = 0x2c;
352 frame_buffer[j++] = 'L'; // nm
353 frame_buffer[j++] = 'M';
354 frame_buffer[j++] = 'L';
355 frame_buffer[j++] = 0;
356 frame_buffer[j++] = 0; // frameNo
357 frame_buffer[j++] = 0;
358 frame_buffer[j++] = 0; // sec
359 frame_buffer[j++] = 0;
360 frame_buffer[j++] = 0;
361 frame_buffer[j++] = 0;
362 frame_buffer[j++] = 0; // usec
363 frame_buffer[j++] = 0;
364 frame_buffer[j++] = 0;
365 frame_buffer[j++] = 0;
366 // Frame size eventually goes here
368 frame_buffer[j++] = 0;
369 frame_buffer[j++] = 0;
370 frame_buffer[j++] = 0;
371 frame_buffer[j++] = 0;
373 frame_buffer[j++] = 0;
374 frame_buffer[j++] = 0;
375 frame_buffer[j++] = 0;
376 frame_buffer[j++] = 0;
378 frame_buffer[j++] = 1;
379 frame_buffer[j++] = 0;
380 frame_buffer[j++] = 0;
381 frame_buffer[j++] = 0;
383 frame_buffer[j++] = 1;
384 frame_buffer[j++] = 0;
385 frame_buffer[j++] = 0;
386 frame_buffer[j++] = 0;
388 frame_buffer[j++] = 1;
389 frame_buffer[j++] = 0;
391 frame_buffer[j++] = 0;
392 frame_buffer[j++] = 0;
393 frame_buffer[j++] = 0;
394 frame_buffer[j++] = 0;
395 frame_buffer[j++] = 0;
396 frame_buffer[j++] = 0;
397 frame_buffer[j++] = 0;
398 frame_buffer[j++] = 0;
399 frame_buffer[j++] = 0;
400 frame_buffer[j++] = 0;
402 // Copy rest of first field
407 frame_buffer[j++] = data[i++];
411 if(!even_field_first)
413 for(i = 0; i < frame1size; )
415 frame_buffer[j++] = data[i++];
420 // frameSize in little endian
421 frame_buffer[size_qword++] = (real_size & 0xff);
422 frame_buffer[size_qword++] = ((real_size & 0xff00) >> 8);
423 frame_buffer[size_qword++] = ((real_size & 0xff0000) >> 16);
424 frame_buffer[size_qword++] = ((real_size & 0xff000000) >> 24);
426 //fwrite(frame_buffer, real_size, 1, stdout);
427 result = !fwrite(frame_buffer,
431 if(result) perror("VDeviceLML::write_buffer");
436 ArrayList<int>* VDeviceLML::get_render_strategies()
438 return &render_strategies;