Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

vdevicelml.C

Go to the documentation of this file.
00001 #include "assets.h"
00002 #include "file.inc"
00003 #include "language.h"
00004 #include "playbackconfig.h"
00005 #include "preferences.h"
00006 #include "recordconfig.h"
00007 #include "strategies.inc"
00008 #include "vdevicelml.h"
00009 #include "vframe.h"
00010 #include "videoconfig.h"
00011 #include "videodevice.h"
00012 
00013 
00014 #define SOI 0xffd8
00015 #define APP3 0xffe3
00016 #define APP1 0xffe1
00017 #define APP0 0xffe0
00018 #define EOI  0xffd9
00019 
00020 VDeviceLML::VDeviceLML(VideoDevice *device)
00021  : VDeviceBase(device)
00022 {
00023         reset_parameters();
00024         render_strategies.append(VRENDER_MJPG);
00025 }
00026 
00027 VDeviceLML::~VDeviceLML()
00028 {
00029         close_all();
00030 }
00031 
00032 int VDeviceLML::reset_parameters()
00033 {
00034         jvideo_fd = 0;
00035         input_buffer = 0;
00036         frame_buffer = 0;
00037         frame_size = 0;
00038         frame_allocated = 0;
00039         input_error = 0;
00040         input_position = INPUT_BUFFER_SIZE;
00041         last_frame_no = 0;
00042 }
00043 
00044 int VDeviceLML::open_input()
00045 {
00046         jvideo_fd = fopen(device->in_config->lml_in_device, "rb");
00047         if(jvideo_fd)
00048         {
00049                 return 0;
00050         }
00051         else
00052         {
00053                 perror("VDeviceLML::open_input");
00054                 jvideo_fd = 0;
00055                 return 1;
00056         }
00057         return 0;
00058 }
00059 
00060 int VDeviceLML::open_output()
00061 {
00062         jvideo_fd = fopen(device->out_config->lml_out_device, "wb");
00063         if(jvideo_fd)
00064         {
00065                 return 0;
00066         }
00067         else
00068         {
00069                 perror("VDeviceLML::open_output");
00070                 jvideo_fd = 0;
00071                 return 1;
00072         }
00073         return 0;
00074 }
00075 
00076 int VDeviceLML::close_all()
00077 {
00078         if(device->r)
00079         {
00080                 if(jvideo_fd) fclose(jvideo_fd);
00081         }
00082         if(device->w)
00083         {
00084                 if(jvideo_fd) fclose(jvideo_fd);
00085         }
00086         if(input_buffer)
00087         {
00088                 delete input_buffer;
00089         }
00090         if(frame_buffer)
00091         {
00092                 delete frame_buffer;
00093         }
00094         reset_parameters();
00095         return 0;
00096 }
00097 
00098 int VDeviceLML::read_buffer(VFrame *frame)
00099 {
00100         long first_field = 0, frame1_size = 0, frame2_size = 0, i;
00101         int result = 0, frame_no = 0, retries = 0;
00102 
00103         if(!jvideo_fd) return 1;
00104 
00105         input_error = 0;
00106 
00107 retry:
00108         frame->set_compressed_size(0);
00109         retries++;
00110         if(retries > 5) return 1;
00111 
00112 // Keep reading until the first field of a frame arrives.
00113         while(!input_error && !first_field)
00114         {
00115 // Get the first marker of a frame
00116                 while(!input_error && next_bytes(2) != SOI)
00117                 {
00118                         get_byte();
00119                 }
00120 
00121 // Store SOI marker
00122                 frame_size = 0;
00123                 write_byte(get_byte());
00124                 write_byte(get_byte());
00125 
00126 // Copy the first frame
00127                 while(!input_error && next_bytes(2) != EOI)
00128                 {
00129 // Replace the LML header with a Quicktime header
00130                         if(next_bytes(2) == APP3)
00131                         {
00132                                 first_field = 1;
00133                                 write_fake_marker();
00134                         
00135                                 get_byte(); // APP3
00136                                 get_byte();
00137                                 get_byte(); // LEN
00138                                 get_byte();
00139                                 get_byte(); // COMMENT
00140                                 get_byte();
00141                                 get_byte();
00142                                 get_byte();
00143                                 get_byte(); // Frame no
00144                                 get_byte();
00145                                 get_byte(); // sec
00146                                 get_byte();
00147                                 get_byte();
00148                                 get_byte();
00149                                 get_byte(); // usec
00150                                 get_byte();
00151                                 get_byte();
00152                                 get_byte();
00153                                 get_byte(); // framesize (useless since we have to swap frames)
00154                                 get_byte();
00155                                 get_byte();
00156                                 get_byte();
00157                                 frame_no = get_byte(); // frame seq no
00158                                 frame_no |= (long)get_byte() << 8;
00159                                 frame_no |= (long)get_byte() << 16;
00160                                 frame_no |= (long)get_byte() << 24;
00161 
00162                                 if(frame_no <= last_frame_no)
00163                                 {
00164                                         input_error = reopen_input();
00165                                         first_field = 0;
00166                                         goto retry;
00167                                 }
00168                                 else
00169                                 {
00170 // Finish LML header
00171                                         last_frame_no = frame_no;
00172                                         while(next_bytes(2) != 0xffdb) get_byte();
00173                                 }
00174                         }
00175                         else
00176                         {
00177                                 write_byte(get_byte());
00178                         }
00179                 }
00180 
00181 // Store EOI marker
00182                 write_byte(get_byte());
00183                 write_byte(get_byte());
00184         }
00185 
00186         frame1_size = frame_size;
00187 
00188 // Read the second field
00189         if(first_field)
00190         {
00191 // Find next field
00192                 while(!input_error && next_bytes(2) != SOI)
00193                 {
00194                         get_byte();
00195                 }
00196 
00197 // Store SOI marker
00198                 write_byte(get_byte());
00199                 write_byte(get_byte());
00200 
00201 // Store Quicktime header
00202                 write_fake_marker();
00203 
00204 // Copy the second frame
00205                 while(!input_error && next_bytes(2) != EOI)
00206                 {
00207                         write_byte(get_byte());
00208                 }
00209 
00210 // Store EOI marker
00211                 write_byte(get_byte());
00212                 write_byte(get_byte());
00213         }
00214 
00215         frame2_size = frame_size - frame1_size;
00216 
00217 // Insert the required information
00218         if(!input_error)
00219         {
00220 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer, frame1_size, !device->odd_field_first);
00221 //              quicktime_fixmarker_jpeg(&jpeg_header, (char*)frame_buffer + frame1_size, frame2_size, device->odd_field_first);
00222 
00223 // Store in the VFrame
00224                 frame->allocate_compressed_data(frame_size);
00225 
00226 // Quicktime expects the even field first
00227                 if(device->odd_field_first)
00228                 {
00229                         memcpy(frame->get_data(), frame_buffer + frame1_size, frame2_size);
00230                         memcpy(frame->get_data() + frame2_size, frame_buffer, frame1_size);
00231                 }
00232                 else
00233                         memcpy(frame->get_data(), frame_buffer, frame_size);
00234 
00235                 frame->set_compressed_size(frame_size);
00236         }
00237         else
00238         {
00239                 input_error = 0;
00240                 reopen_input();
00241                 goto retry;
00242         }
00243 
00244         return input_error;
00245 }
00246 
00247 int VDeviceLML::reopen_input()
00248 {
00249         int input_error = 0;
00250         Timer timer;
00251         fprintf(stderr, _("VDeviceLML::read_buffer: driver crash\n"));
00252         fclose(jvideo_fd);
00253         timer.delay(100);
00254         input_error = open_input();
00255         if(!input_error) fprintf(stderr, _("VDeviceLML::read_buffer: reopened\n"));
00256         last_frame_no = 0;
00257         input_position = INPUT_BUFFER_SIZE;
00258         return input_error;
00259 }
00260 
00261 
00262 int VDeviceLML::write_fake_marker()
00263 {
00264 // Marker
00265         write_byte(0xff);
00266         write_byte(0xe1);
00267 // Size
00268         write_byte(0x00);
00269         write_byte(0x2a);
00270 // Blank space
00271         for(int i = 0; i < 0x28; i++)
00272         {
00273                 write_byte(0x00);
00274         }
00275         return 0;
00276 }
00277 
00278 int VDeviceLML::refill_input()
00279 {
00280 // Shift remaining data up.
00281         memcpy(input_buffer, input_buffer + input_position, INPUT_BUFFER_SIZE - input_position);
00282 
00283 // Append new data
00284         input_error = !fread(input_buffer + INPUT_BUFFER_SIZE - input_position, 
00285                                         INPUT_BUFFER_SIZE - (INPUT_BUFFER_SIZE - input_position), 
00286                                         1,
00287                                         jvideo_fd);
00288 
00289         input_position = 0;
00290         return input_error;
00291 }
00292 
00293 
00294 int VDeviceLML::write_buffer(VFrame *frame, EDL *edl)
00295 {
00296         int result = 0, i, frame1size, j, size_qword, real_size, skip;
00297         unsigned long size = frame->get_compressed_size();
00298         unsigned char *data = frame->get_data();
00299         unsigned char *data1;
00300         int even_field_first = 1;
00301 
00302 #if 0
00303         if(!jvideo_fd || frame->get_color_model() != VFRAME_COMPRESSED) return 1;
00304 #endif
00305 
00306         if(frame_allocated < size * 2)
00307         {
00308                 delete frame_buffer;
00309                 frame_buffer = 0;
00310         }
00311         
00312         if(!frame_buffer)
00313         {
00314                 frame_buffer = new unsigned char[size * 2];
00315         }
00316 
00317         for(data1 = data + 1, i = 0; i < size - 1; i++)
00318                 if(data[i] == ((EOI & 0xff00) >> 8) && data1[i] == (EOI & 0xff)) break;
00319 
00320         i += 2;
00321         frame1size = i;
00322         j = 0;
00323         if(even_field_first) i = 0;
00324 
00325 // SOI
00326         frame_buffer[j++] = data[i++];
00327         frame_buffer[j++] = data[i++];
00328 
00329 // APP3 for LML driver
00330         frame_buffer[j++] = (APP3 & 0xff00) >> 8;
00331         frame_buffer[j++] = APP3 & 0xff;
00332         frame_buffer[j++] = 0;       // Marker size
00333         frame_buffer[j++] = 0x2c;
00334         frame_buffer[j++] = 'L';     // nm
00335         frame_buffer[j++] = 'M';
00336         frame_buffer[j++] = 'L';
00337         frame_buffer[j++] = 0;
00338         frame_buffer[j++] = 0;       // frameNo
00339         frame_buffer[j++] = 0;
00340         frame_buffer[j++] = 0;       // sec
00341         frame_buffer[j++] = 0;
00342         frame_buffer[j++] = 0;
00343         frame_buffer[j++] = 0;
00344         frame_buffer[j++] = 0;       // usec
00345         frame_buffer[j++] = 0;
00346         frame_buffer[j++] = 0;
00347         frame_buffer[j++] = 0;
00348 // Frame size eventually goes here
00349         size_qword = j;      
00350         frame_buffer[j++] = 0;           
00351         frame_buffer[j++] = 0;
00352         frame_buffer[j++] = 0;
00353         frame_buffer[j++] = 0;
00354 // Frame Seq No
00355         frame_buffer[j++] = 0;           
00356         frame_buffer[j++] = 0;
00357         frame_buffer[j++] = 0;
00358         frame_buffer[j++] = 0;
00359 // Color Encoding
00360         frame_buffer[j++] = 1;           
00361         frame_buffer[j++] = 0;
00362         frame_buffer[j++] = 0;
00363         frame_buffer[j++] = 0;
00364 // Video Stream
00365         frame_buffer[j++] = 1;           
00366         frame_buffer[j++] = 0;
00367         frame_buffer[j++] = 0;
00368         frame_buffer[j++] = 0;
00369 // Time Decimation
00370         frame_buffer[j++] = 1;           
00371         frame_buffer[j++] = 0;
00372 // Filler
00373         frame_buffer[j++] = 0;           
00374         frame_buffer[j++] = 0;
00375         frame_buffer[j++] = 0;
00376         frame_buffer[j++] = 0;
00377         frame_buffer[j++] = 0;           
00378         frame_buffer[j++] = 0;
00379         frame_buffer[j++] = 0;
00380         frame_buffer[j++] = 0;
00381         frame_buffer[j++] = 0;
00382         frame_buffer[j++] = 0;
00383 
00384 // Copy rest of first field
00385         data1 = data + 1;
00386         
00387         while(i < size)
00388         {
00389                 frame_buffer[j++] = data[i++];
00390         }
00391 
00392 // Copy second field
00393         if(!even_field_first)
00394         {
00395                 for(i = 0; i < frame1size; )
00396                 {
00397                         frame_buffer[j++] = data[i++];
00398                 }
00399         }
00400 
00401         real_size = j;
00402 // frameSize in little endian
00403         frame_buffer[size_qword++] = (real_size & 0xff);
00404         frame_buffer[size_qword++] = ((real_size & 0xff00) >> 8);
00405         frame_buffer[size_qword++] = ((real_size & 0xff0000) >> 16);
00406         frame_buffer[size_qword++] = ((real_size & 0xff000000) >> 24);
00407 
00408 //fwrite(frame_buffer, real_size, 1, stdout);
00409         result = !fwrite(frame_buffer, 
00410                 real_size, 
00411                 1, 
00412                 jvideo_fd);
00413         if(result) perror("VDeviceLML::write_buffer");
00414 
00415         return result;
00416 }
00417 
00418 ArrayList<int>* VDeviceLML::get_render_strategies()
00419 {
00420         return &render_strategies;
00421 }

Generated on Sun Jan 8 13:39:01 2006 for Cinelerra-svn by  doxygen 1.4.4