Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / cinelerra / vdevicelml.C
blob340a6dcc108437d5b6ea088252d44f5d1177148d
1 #include "assets.h"
2 #include "file.inc"
3 #include "language.h"
4 #include "playbackconfig.h"
5 #include "preferences.h"
6 #include "recordconfig.h"
7 #include "strategies.inc"
8 #include "vdevicelml.h"
9 #include "vframe.h"
10 #include "videoconfig.h"
11 #include "videodevice.h"
14 #define SOI 0xffd8
15 #define APP3 0xffe3
16 #define APP1 0xffe1
17 #define APP0 0xffe0
18 #define EOI  0xffd9
20 VDeviceLML::VDeviceLML(VideoDevice *device)
21  : VDeviceBase(device)
23         reset_parameters();
24         render_strategies.append(VRENDER_MJPG);
27 VDeviceLML::~VDeviceLML()
29         close_all();
32 int VDeviceLML::reset_parameters()
34         jvideo_fd = 0;
35         input_buffer = 0;
36         frame_buffer = 0;
37         frame_size = 0;
38         frame_allocated = 0;
39         input_error = 0;
40         input_position = INPUT_BUFFER_SIZE;
41         last_frame_no = 0;
44 int VDeviceLML::open_input()
46         jvideo_fd = fopen(device->in_config->lml_in_device, "rb");
47         if(jvideo_fd)
48         {
49                 return 0;
50         }
51         else
52         {
53                 perror("VDeviceLML::open_input");
54                 jvideo_fd = 0;
55                 return 1;
56         }
57         return 0;
60 int VDeviceLML::open_output()
62         jvideo_fd = fopen(device->out_config->lml_out_device, "wb");
63         if(jvideo_fd)
64         {
65                 return 0;
66         }
67         else
68         {
69                 perror("VDeviceLML::open_output");
70                 jvideo_fd = 0;
71                 return 1;
72         }
73         return 0;
76 int VDeviceLML::close_all()
78         if(device->r)
79         {
80                 if(jvideo_fd) fclose(jvideo_fd);
81         }
82         if(device->w)
83         {
84                 if(jvideo_fd) fclose(jvideo_fd);
85         }
86         if(input_buffer)
87         {
88                 delete input_buffer;
89         }
90         if(frame_buffer)
91         {
92                 delete frame_buffer;
93         }
94         reset_parameters();
95         return 0;
98 int VDeviceLML::read_buffer(VFrame *frame)
100         long first_field = 0, frame1_size = 0, frame2_size = 0, i;
101         int result = 0, frame_no = 0, retries = 0;
103         if(!jvideo_fd) return 1;
105         input_error = 0;
107 retry:
108         frame->set_compressed_size(0);
109         retries++;
110         if(retries > 5) return 1;
112 // Keep reading until the first field of a frame arrives.
113         while(!input_error && !first_field)
114         {
115 // Get the first marker of a frame
116                 while(!input_error && next_bytes(2) != SOI)
117                 {
118                         get_byte();
119                 }
121 // Store SOI marker
122                 frame_size = 0;
123                 write_byte(get_byte());
124                 write_byte(get_byte());
126 // Copy the first frame
127                 while(!input_error && next_bytes(2) != EOI)
128                 {
129 // Replace the LML header with a Quicktime header
130                         if(next_bytes(2) == APP3)
131                         {
132                                 first_field = 1;
133                                 write_fake_marker();
134                         
135                                 get_byte(); // APP3
136                                 get_byte();
137                                 get_byte(); // LEN
138                                 get_byte();
139                                 get_byte(); // COMMENT
140                                 get_byte();
141                                 get_byte();
142                                 get_byte();
143                                 get_byte(); // Frame no
144                                 get_byte();
145                                 get_byte(); // sec
146                                 get_byte();
147                                 get_byte();
148                                 get_byte();
149                                 get_byte(); // usec
150                                 get_byte();
151                                 get_byte();
152                                 get_byte();
153                                 get_byte(); // framesize (useless since we have to swap frames)
154                                 get_byte();
155                                 get_byte();
156                                 get_byte();
157                                 frame_no = get_byte(); // frame seq no
158                                 frame_no |= (long)get_byte() << 8;
159                                 frame_no |= (long)get_byte() << 16;
160                                 frame_no |= (long)get_byte() << 24;
162                                 if(frame_no <= last_frame_no)
163                                 {
164                                         input_error = reopen_input();
165                                         first_field = 0;
166                                         goto retry;
167                                 }
168                                 else
169                                 {
170 // Finish LML header
171                                         last_frame_no = frame_no;
172                                         while(next_bytes(2) != 0xffdb) get_byte();
173                                 }
174                         }
175                         else
176                         {
177                                 write_byte(get_byte());
178                         }
179                 }
181 // Store EOI marker
182                 write_byte(get_byte());
183                 write_byte(get_byte());
184         }
186         frame1_size = frame_size;
188 // Read the second field
189         if(first_field)
190         {
191 // Find next field
192                 while(!input_error && next_bytes(2) != SOI)
193                 {
194                         get_byte();
195                 }
197 // Store SOI marker
198                 write_byte(get_byte());
199                 write_byte(get_byte());
201 // Store Quicktime header
202                 write_fake_marker();
204 // Copy the second frame
205                 while(!input_error && next_bytes(2) != EOI)
206                 {
207                         write_byte(get_byte());
208                 }
210 // Store EOI marker
211                 write_byte(get_byte());
212                 write_byte(get_byte());
213         }
215         frame2_size = frame_size - frame1_size;
217 // Insert the required information
218         if(!input_error)
219         {
220 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer, frame1_size, !device->odd_field_first);
221 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer + frame1_size, frame2_size, device->odd_field_first);
223 // Store in the VFrame
224                 frame->allocate_compressed_data(frame_size);
226 // Quicktime expects the even field first
227                 if(device->odd_field_first)
228                 {
229                         memcpy(frame->get_data(), frame_buffer + frame1_size, frame2_size);
230                         memcpy(frame->get_data() + frame2_size, frame_buffer, frame1_size);
231                 }
232                 else
233                         memcpy(frame->get_data(), frame_buffer, frame_size);
235                 frame->set_compressed_size(frame_size);
236         }
237         else
238         {
239                 input_error = 0;
240                 reopen_input();
241                 goto retry;
242         }
244         return input_error;
247 int VDeviceLML::reopen_input()
249         int input_error = 0;
250         Timer timer;
251         fprintf(stderr, _("VDeviceLML::read_buffer: driver crash\n"));
252         fclose(jvideo_fd);
253         timer.delay(100);
254         input_error = open_input();
255         if(!input_error) fprintf(stderr, _("VDeviceLML::read_buffer: reopened\n"));
256         last_frame_no = 0;
257         input_position = INPUT_BUFFER_SIZE;
258         return input_error;
262 int VDeviceLML::write_fake_marker()
264 // Marker
265         write_byte(0xff);
266         write_byte(0xe1);
267 // Size
268         write_byte(0x00);
269         write_byte(0x2a);
270 // Blank space
271         for(int i = 0; i < 0x28; i++)
272         {
273                 write_byte(0x00);
274         }
275         return 0;
278 int VDeviceLML::refill_input()
280 // Shift remaining data up.
281         memcpy(input_buffer, input_buffer + input_position, INPUT_BUFFER_SIZE - input_position);
283 // Append new data
284         input_error = !fread(input_buffer + INPUT_BUFFER_SIZE - input_position, 
285                                         INPUT_BUFFER_SIZE - (INPUT_BUFFER_SIZE - input_position), 
286                                         1,
287                                         jvideo_fd);
289         input_position = 0;
290         return input_error;
294 int VDeviceLML::write_buffer(VFrame *frame, EDL *edl)
296         int result = 0, i, frame1size, j, size_qword, real_size, skip;
297         unsigned long size = frame->get_compressed_size();
298         unsigned char *data = frame->get_data();
299         unsigned char *data1;
300         int even_field_first = 1;
302 #if 0
303         if(!jvideo_fd || frame->get_color_model() != VFRAME_COMPRESSED) return 1;
304 #endif
306         if(frame_allocated < size * 2)
307         {
308                 delete frame_buffer;
309                 frame_buffer = 0;
310         }
311         
312         if(!frame_buffer)
313         {
314                 frame_buffer = new unsigned char[size * 2];
315         }
317         for(data1 = data + 1, i = 0; i < size - 1; i++)
318                 if(data[i] == ((EOI & 0xff00) >> 8) && data1[i] == (EOI & 0xff)) break;
320         i += 2;
321         frame1size = i;
322         j = 0;
323         if(even_field_first) i = 0;
325 // SOI
326         frame_buffer[j++] = data[i++];
327         frame_buffer[j++] = data[i++];
329 // APP3 for LML driver
330         frame_buffer[j++] = (APP3 & 0xff00) >> 8;
331         frame_buffer[j++] = APP3 & 0xff;
332         frame_buffer[j++] = 0;       // Marker size
333         frame_buffer[j++] = 0x2c;
334         frame_buffer[j++] = 'L';     // nm
335         frame_buffer[j++] = 'M';
336         frame_buffer[j++] = 'L';
337         frame_buffer[j++] = 0;
338         frame_buffer[j++] = 0;       // frameNo
339         frame_buffer[j++] = 0;
340         frame_buffer[j++] = 0;       // sec
341         frame_buffer[j++] = 0;
342         frame_buffer[j++] = 0;
343         frame_buffer[j++] = 0;
344         frame_buffer[j++] = 0;       // usec
345         frame_buffer[j++] = 0;
346         frame_buffer[j++] = 0;
347         frame_buffer[j++] = 0;
348 // Frame size eventually goes here
349         size_qword = j;      
350         frame_buffer[j++] = 0;           
351         frame_buffer[j++] = 0;
352         frame_buffer[j++] = 0;
353         frame_buffer[j++] = 0;
354 // Frame Seq No
355         frame_buffer[j++] = 0;           
356         frame_buffer[j++] = 0;
357         frame_buffer[j++] = 0;
358         frame_buffer[j++] = 0;
359 // Color Encoding
360         frame_buffer[j++] = 1;           
361         frame_buffer[j++] = 0;
362         frame_buffer[j++] = 0;
363         frame_buffer[j++] = 0;
364 // Video Stream
365         frame_buffer[j++] = 1;           
366         frame_buffer[j++] = 0;
367         frame_buffer[j++] = 0;
368         frame_buffer[j++] = 0;
369 // Time Decimation
370         frame_buffer[j++] = 1;           
371         frame_buffer[j++] = 0;
372 // Filler
373         frame_buffer[j++] = 0;           
374         frame_buffer[j++] = 0;
375         frame_buffer[j++] = 0;
376         frame_buffer[j++] = 0;
377         frame_buffer[j++] = 0;           
378         frame_buffer[j++] = 0;
379         frame_buffer[j++] = 0;
380         frame_buffer[j++] = 0;
381         frame_buffer[j++] = 0;
382         frame_buffer[j++] = 0;
384 // Copy rest of first field
385         data1 = data + 1;
386         
387         while(i < size)
388         {
389                 frame_buffer[j++] = data[i++];
390         }
392 // Copy second field
393         if(!even_field_first)
394         {
395                 for(i = 0; i < frame1size; )
396                 {
397                         frame_buffer[j++] = data[i++];
398                 }
399         }
401         real_size = j;
402 // frameSize in little endian
403         frame_buffer[size_qword++] = (real_size & 0xff);
404         frame_buffer[size_qword++] = ((real_size & 0xff00) >> 8);
405         frame_buffer[size_qword++] = ((real_size & 0xff0000) >> 16);
406         frame_buffer[size_qword++] = ((real_size & 0xff000000) >> 24);
408 //fwrite(frame_buffer, real_size, 1, stdout);
409         result = !fwrite(frame_buffer, 
410                 real_size, 
411                 1, 
412                 jvideo_fd);
413         if(result) perror("VDeviceLML::write_buffer");
415         return result;
418 ArrayList<int>* VDeviceLML::get_render_strategies()
420         return &render_strategies;
423 //      Local Variables:
424 //      mode: C++
425 //      c-file-style: "linux"
426 //      End: