r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / vdevicelml.C
blobcf56fced3a5814b3292a1d93b155f0b06b8b245a
1 #include "assets.h"
2 #include "file.inc"
3 #include "playbackconfig.h"
4 #include "preferences.h"
5 #include "recordconfig.h"
6 #include "strategies.inc"
7 #include "vdevicelml.h"
8 #include "vframe.h"
9 #include "videoconfig.h"
10 #include "videodevice.h"
12 #include <libintl.h>
13 #define _(String) gettext(String)
14 #define gettext_noop(String) String
15 #define N_(String) gettext_noop (String)
18 #define SOI 0xffd8
19 #define APP3 0xffe3
20 #define APP1 0xffe1
21 #define APP0 0xffe0
22 #define EOI  0xffd9
24 VDeviceLML::VDeviceLML(VideoDevice *device)
25  : VDeviceBase(device)
27         reset_parameters();
28         render_strategies.append(VRENDER_MJPG);
31 VDeviceLML::~VDeviceLML()
33         close_all();
36 int VDeviceLML::reset_parameters()
38         jvideo_fd = 0;
39         input_buffer = 0;
40         frame_buffer = 0;
41         frame_size = 0;
42         frame_allocated = 0;
43         input_error = 0;
44         input_position = INPUT_BUFFER_SIZE;
45         last_frame_no = 0;
48 int VDeviceLML::open_input()
50         jvideo_fd = fopen(device->in_config->lml_in_device, "rb");
51         if(jvideo_fd)
52         {
53                 return 0;
54         }
55         else
56         {
57                 perror("VDeviceLML::open_input");
58                 jvideo_fd = 0;
59                 return 1;
60         }
61         return 0;
64 int VDeviceLML::open_output()
66         jvideo_fd = fopen(device->out_config->lml_out_device, "wb");
67         if(jvideo_fd)
68         {
69                 return 0;
70         }
71         else
72         {
73                 perror("VDeviceLML::open_output");
74                 jvideo_fd = 0;
75                 return 1;
76         }
77         return 0;
80 int VDeviceLML::close_all()
82         if(device->r)
83         {
84                 if(jvideo_fd) fclose(jvideo_fd);
85         }
86         if(device->w)
87         {
88                 if(jvideo_fd) fclose(jvideo_fd);
89         }
90         if(input_buffer)
91         {
92                 delete input_buffer;
93         }
94         if(frame_buffer)
95         {
96                 delete frame_buffer;
97         }
98         reset_parameters();
99         return 0;
102 int VDeviceLML::read_buffer(VFrame *frame)
104         long first_field = 0, frame1_size = 0, frame2_size = 0, i;
105         int result = 0, frame_no = 0, retries = 0;
107         if(!jvideo_fd) return 1;
109         input_error = 0;
111 retry:
112         frame->set_compressed_size(0);
113         retries++;
114         if(retries > 5) return 1;
116 // Keep reading until the first field of a frame arrives.
117         while(!input_error && !first_field)
118         {
119 // Get the first marker of a frame
120                 while(!input_error && next_bytes(2) != SOI)
121                 {
122                         get_byte();
123                 }
125 // Store SOI marker
126                 frame_size = 0;
127                 write_byte(get_byte());
128                 write_byte(get_byte());
130 // Copy the first frame
131                 while(!input_error && next_bytes(2) != EOI)
132                 {
133 // Replace the LML header with a Quicktime header
134                         if(next_bytes(2) == APP3)
135                         {
136                                 first_field = 1;
137                                 write_fake_marker();
138                         
139                                 get_byte(); // APP3
140                                 get_byte();
141                                 get_byte(); // LEN
142                                 get_byte();
143                                 get_byte(); // COMMENT
144                                 get_byte();
145                                 get_byte();
146                                 get_byte();
147                                 get_byte(); // Frame no
148                                 get_byte();
149                                 get_byte(); // sec
150                                 get_byte();
151                                 get_byte();
152                                 get_byte();
153                                 get_byte(); // usec
154                                 get_byte();
155                                 get_byte();
156                                 get_byte();
157                                 get_byte(); // framesize (useless since we have to swap frames)
158                                 get_byte();
159                                 get_byte();
160                                 get_byte();
161                                 frame_no = get_byte(); // frame seq no
162                                 frame_no |= (long)get_byte() << 8;
163                                 frame_no |= (long)get_byte() << 16;
164                                 frame_no |= (long)get_byte() << 24;
166                                 if(frame_no <= last_frame_no)
167                                 {
168                                         input_error = reopen_input();
169                                         first_field = 0;
170                                         goto retry;
171                                 }
172                                 else
173                                 {
174 // Finish LML header
175                                         last_frame_no = frame_no;
176                                         while(next_bytes(2) != 0xffdb) get_byte();
177                                 }
178                         }
179                         else
180                         {
181                                 write_byte(get_byte());
182                         }
183                 }
185 // Store EOI marker
186                 write_byte(get_byte());
187                 write_byte(get_byte());
188         }
190         frame1_size = frame_size;
192 // Read the second field
193         if(first_field)
194         {
195 // Find next field
196                 while(!input_error && next_bytes(2) != SOI)
197                 {
198                         get_byte();
199                 }
201 // Store SOI marker
202                 write_byte(get_byte());
203                 write_byte(get_byte());
205 // Store Quicktime header
206                 write_fake_marker();
208 // Copy the second frame
209                 while(!input_error && next_bytes(2) != EOI)
210                 {
211                         write_byte(get_byte());
212                 }
214 // Store EOI marker
215                 write_byte(get_byte());
216                 write_byte(get_byte());
217         }
219         frame2_size = frame_size - frame1_size;
221 // Insert the required information
222         if(!input_error)
223         {
224 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer, frame1_size, !device->odd_field_first);
225 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer + frame1_size, frame2_size, device->odd_field_first);
227 // Store in the VFrame
228                 frame->allocate_compressed_data(frame_size);
230 // Quicktime expects the even field first
231                 if(device->odd_field_first)
232                 {
233                         memcpy(frame->get_data(), frame_buffer + frame1_size, frame2_size);
234                         memcpy(frame->get_data() + frame2_size, frame_buffer, frame1_size);
235                 }
236                 else
237                         memcpy(frame->get_data(), frame_buffer, frame_size);
239                 frame->set_compressed_size(frame_size);
240         }
241         else
242         {
243                 input_error = 0;
244                 reopen_input();
245                 goto retry;
246         }
248         return input_error;
251 int VDeviceLML::reopen_input()
253         int input_error = 0;
254         Timer timer;
255         fprintf(stderr, _("VDeviceLML::read_buffer: driver crash\n"));
256         fclose(jvideo_fd);
257         timer.delay(100);
258         input_error = open_input();
259         if(!input_error) fprintf(stderr, _("VDeviceLML::read_buffer: reopened\n"));
260         last_frame_no = 0;
261         input_position = INPUT_BUFFER_SIZE;
262         return input_error;
266 int VDeviceLML::write_fake_marker()
268 // Marker
269         write_byte(0xff);
270         write_byte(0xe1);
271 // Size
272         write_byte(0x00);
273         write_byte(0x2a);
274 // Blank space
275         for(int i = 0; i < 0x28; i++)
276         {
277                 write_byte(0x00);
278         }
279         return 0;
282 int VDeviceLML::refill_input()
284 // Shift remaining data up.
285         memcpy(input_buffer, input_buffer + input_position, INPUT_BUFFER_SIZE - input_position);
287 // Append new data
288         input_error = !fread(input_buffer + INPUT_BUFFER_SIZE - input_position, 
289                                         INPUT_BUFFER_SIZE - (INPUT_BUFFER_SIZE - input_position), 
290                                         1,
291                                         jvideo_fd);
293         input_position = 0;
294         return input_error;
298 int VDeviceLML::write_buffer(VFrame *frame, EDL *edl)
300         int result = 0, i, frame1size, j, size_qword, real_size, skip;
301         unsigned long size = frame->get_compressed_size();
302         unsigned char *data = frame->get_data();
303         unsigned char *data1;
304         int even_field_first = 1;
306 #if 0
307         if(!jvideo_fd || frame->get_color_model() != VFRAME_COMPRESSED) return 1;
308 #endif
310         if(frame_allocated < size * 2)
311         {
312                 delete frame_buffer;
313                 frame_buffer = 0;
314         }
315         
316         if(!frame_buffer)
317         {
318                 frame_buffer = new unsigned char[size * 2];
319         }
321         for(data1 = data + 1, i = 0; i < size - 1; i++)
322                 if(data[i] == ((EOI & 0xff00) >> 8) && data1[i] == (EOI & 0xff)) break;
324         i += 2;
325         frame1size = i;
326         j = 0;
327         if(even_field_first) i = 0;
329 // SOI
330         frame_buffer[j++] = data[i++];
331         frame_buffer[j++] = data[i++];
333 // APP3 for LML driver
334         frame_buffer[j++] = (APP3 & 0xff00) >> 8;
335         frame_buffer[j++] = APP3 & 0xff;
336         frame_buffer[j++] = 0;       // Marker size
337         frame_buffer[j++] = 0x2c;
338         frame_buffer[j++] = 'L';     // nm
339         frame_buffer[j++] = 'M';
340         frame_buffer[j++] = 'L';
341         frame_buffer[j++] = 0;
342         frame_buffer[j++] = 0;       // frameNo
343         frame_buffer[j++] = 0;
344         frame_buffer[j++] = 0;       // sec
345         frame_buffer[j++] = 0;
346         frame_buffer[j++] = 0;
347         frame_buffer[j++] = 0;
348         frame_buffer[j++] = 0;       // usec
349         frame_buffer[j++] = 0;
350         frame_buffer[j++] = 0;
351         frame_buffer[j++] = 0;
352 // Frame size eventually goes here
353         size_qword = j;      
354         frame_buffer[j++] = 0;           
355         frame_buffer[j++] = 0;
356         frame_buffer[j++] = 0;
357         frame_buffer[j++] = 0;
358 // Frame Seq No
359         frame_buffer[j++] = 0;           
360         frame_buffer[j++] = 0;
361         frame_buffer[j++] = 0;
362         frame_buffer[j++] = 0;
363 // Color Encoding
364         frame_buffer[j++] = 1;           
365         frame_buffer[j++] = 0;
366         frame_buffer[j++] = 0;
367         frame_buffer[j++] = 0;
368 // Video Stream
369         frame_buffer[j++] = 1;           
370         frame_buffer[j++] = 0;
371         frame_buffer[j++] = 0;
372         frame_buffer[j++] = 0;
373 // Time Decimation
374         frame_buffer[j++] = 1;           
375         frame_buffer[j++] = 0;
376 // Filler
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;
383         frame_buffer[j++] = 0;
384         frame_buffer[j++] = 0;
385         frame_buffer[j++] = 0;
386         frame_buffer[j++] = 0;
388 // Copy rest of first field
389         data1 = data + 1;
390         
391         while(i < size)
392         {
393                 frame_buffer[j++] = data[i++];
394         }
396 // Copy second field
397         if(!even_field_first)
398         {
399                 for(i = 0; i < frame1size; )
400                 {
401                         frame_buffer[j++] = data[i++];
402                 }
403         }
405         real_size = j;
406 // frameSize in little endian
407         frame_buffer[size_qword++] = (real_size & 0xff);
408         frame_buffer[size_qword++] = ((real_size & 0xff00) >> 8);
409         frame_buffer[size_qword++] = ((real_size & 0xff0000) >> 16);
410         frame_buffer[size_qword++] = ((real_size & 0xff000000) >> 24);
412 //fwrite(frame_buffer, real_size, 1, stdout);
413         result = !fwrite(frame_buffer, 
414                 real_size, 
415                 1, 
416                 jvideo_fd);
417         if(result) perror("VDeviceLML::write_buffer");
419         return result;
422 ArrayList<int>* VDeviceLML::get_render_strategies()
424         return &render_strategies;