allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / recover.c
1 #include "funcprotos.h"
2 #include "quicktime.h"
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/stat.h>
8 #include <sys/time.h>
9 #include <stdint.h>
10
11
12
13
14
15
16
17
18
19 #define FSEEK fseeko64
20
21
22 //#define WIDTH 720
23 //#define HEIGHT 480
24 #define WIDTH 960
25 #define HEIGHT 540
26 #define FRAMERATE (double)30000/1001
27 //#define FRAMERATE (double)30
28 #define STARTING_OFFSET 0x28
29
30 #define CHANNELS 1
31 #define SAMPLERATE 48000
32 #define AUDIO_CHUNK 2048
33 #define BITS 24
34 #define TEMP_FILE "/tmp/temp.mov"
35
36 // Output files
37 #define AUDIO_FILE "/tmp/audio.pcm"
38 #define VIDEO_FILE "/tmp/video.mov"
39 //#define VCODEC QUICKTIME_MJPA
40 //#define VCODEC QUICKTIME_JPEG
41
42
43 // Only 1 variation of this, recorded by 1 camcorder
44 #define VCODEC QUICKTIME_H264
45 // H264 rendered by Cinelerra
46 #define USE_X264
47
48 #define ACODEC QUICKTIME_MP4A
49
50 //#define READ_ONLY
51
52
53 #define SEARCH_FRAGMENT (int64_t)0x100000
54 //#define SEARCH_PAD 8
55 #define SEARCH_PAD 16
56
57
58 #define GOT_NOTHING 0
59 #define IN_FIELD1   1
60 #define GOT_FIELD1  2
61 #define IN_FIELD2   3
62 #define GOT_FIELD2  4
63 #define GOT_AUDIO   5
64 #define GOT_IMAGE_START 6
65 #define GOT_IMAGE_END   7
66
67
68
69 #ifdef USE_X264
70 unsigned char h264_desc[] = 
71 {
72
73         0x01, 0x4d, 0x40, 0x1f, 0xff, 0xe1, 0x00, 0x16, 0x67, 0x4d, 0x40, 0x33, 0x9a,
74         0x74, 0x07, 0x80, 0x8b, 0xf7, 0x08, 0x00, 0x00, 0x1f, 0x48, 0x00, 0x07, 0x53, 0x04,
75         0x78, 0xc1, 0x95, 0x01, 0x00, 0x04, 0x68, 0xee, 0x1f, 0x20
76
77 };
78
79 #else
80
81 // H264 description for cheap camcorder format
82 unsigned char h264_desc[] = 
83 {
84         0x01, 0x4d, 0x00, 0x28, 0xff, 0xe1, 0x00, 0x30, 0x27, 0x4d, 0x00, 0x28,
85         0x9a, 0x62, 0x80, 0xa0, 0x0b, 0x76, 0x02, 0x20, 0x00, 0x00, 0x7d, 0x20,
86         0x00, 0x1d, 0x4c, 0x1d, 0x0c, 0x00, 0x26, 0x26, 0x00, 0x02, 0xae, 0xa9,
87         0x77, 0x97, 0x1a, 0x18, 0x00, 0x4c, 0x4c, 0x00, 0x05, 0x5d, 0x52, 0xef,
88         0x2e, 0x1f, 0x08, 0x84, 0x51, 0xe0, 0x00, 0x00, 0x01, 0x00, 0x04, 0x28,
89         0xee, 0x3c, 0x80 
90 };
91
92 #endif
93
94 // Table utilities
95 #define NEW_TABLE(ptr, size, allocation) \
96 { \
97         (ptr) = 0; \
98         (size) = 0; \
99         (allocation) = 0; \
100 }
101
102 #define APPEND_TABLE(ptr, size, allocation, value) \
103 { \
104         if((allocation) <= (size)) \
105         { \
106                 if(!(allocation)) \
107                         (allocation) = 1024; \
108                 else \
109                         (allocation) *= 2; \
110                 int64_t *new_table = calloc(1, sizeof(int64_t) * (allocation)); \
111                 memcpy(new_table, (ptr), sizeof(int64_t) * (size)); \
112                 free((ptr)); \
113                 (ptr) = new_table; \
114         } \
115         (ptr)[(size)] = (value); \
116         (size)++; \
117 }
118
119 int get_h264_size(unsigned char *frame_buffer, int frame_size)
120 {
121         int result = frame_size;
122         int offset = 0;
123
124 // walk NAL codes
125         while(offset < frame_size)
126         {
127                 int nal_size = ((frame_buffer[offset + 0] << 24) |
128                         (frame_buffer[offset + 1] << 16) |
129                         (frame_buffer[offset + 2] << 8) |
130                         (frame_buffer[offset + 3])) + 4;
131 //printf("get_h264_size %d %d %d\n", __LINE__, offset, nal_size);
132                 if(nal_size <= 0 || nal_size + offset >= frame_size)
133                 {
134                         return offset;
135                 }
136                 
137                 offset += nal_size;
138         }
139         
140         return result;
141 }
142
143
144 int main(int argc, char *argv[])
145 {
146         FILE *in = 0;
147         FILE *temp = 0;
148         FILE *audio_out = 0;
149 //      quicktime_t *out;
150         quicktime_t *video_out;
151         int64_t current_byte, ftell_byte;
152         int64_t jpeg_end;
153         int64_t audio_start = 0, audio_end = 0;
154         unsigned char *search_buffer = calloc(1, SEARCH_FRAGMENT);
155         unsigned char *frame_buffer = calloc(1, SEARCH_FRAGMENT);
156         unsigned char *copy_buffer = 0;
157         int i;
158         int64_t file_size;
159         struct stat status;
160         unsigned char data[8];
161         struct stat ostat;
162         int fields = 1;
163         int is_h264 = 0;
164         int is_keyframe = 0;
165         int next_is_keyframe = 0;
166         time_t current_time = time(0);
167         time_t prev_time = 0;
168         int jpeg_header_offset;
169         int64_t field1_offset = 0;
170         int64_t field2_offset = 0;
171         int64_t image_start = STARTING_OFFSET;
172         int64_t image_end = STARTING_OFFSET;
173         int update_time = 0;
174         int state = GOT_NOTHING;
175         char *in_path;
176         int audio_frame;
177         int total_samples;
178         int field;
179
180 // Value taken from Cinelerra preferences
181         int audio_chunk = AUDIO_CHUNK;
182
183
184         int64_t *start_table;
185         int start_size;
186         int start_allocation;
187         int64_t *end_table;
188         int end_size;
189         int end_allocation;
190         int64_t *field_table;
191         int64_t field_size;
192         int64_t field_allocation;
193
194 // Dump codec settings
195         printf("Codec settings:\n"
196                 "   WIDTH=%d HEIGHT=%d\n"
197                 "   FRAMERATE=%.2f\n"
198                 "   CHANNELS=%d\n"
199                 "   SAMPLERATE=%d\n"
200                 "   BITS=%d\n"
201                 "   AUDIO CHUNK=%d\n"
202                 "   VCODEC=\"%s\"\n"
203                 "   ACODEC=\"%s\"\n",
204                 WIDTH,
205                 HEIGHT,
206                 FRAMERATE,
207                 CHANNELS,
208                 SAMPLERATE,
209                 BITS,
210                 audio_chunk,
211                 VCODEC,
212                 ACODEC);
213 #ifdef READ_ONLY
214         printf("   READ ONLY\n");
215 #endif
216
217         if(argc < 2)
218         {
219                 printf("Recover JPEG and PCM audio in a corrupted movie.\n"
220                         "Usage: recover [options] <input>\n"
221                         "Options:\n"
222                         " -b samples     number of samples in an audio chunk (%d)\n"
223                         "\n",
224                         audio_chunk);
225                 exit(1);
226         }
227
228         for(i = 1; i < argc; i++)
229         {
230                 if(!strcmp(argv[i], "-b"))
231                 {
232                         if(i + 1 < argc)
233                         {
234                                 audio_chunk = atol(argv[i + 1]);
235                                 i++;
236                                 if(audio_chunk <= 0)
237                                 {
238                                         printf("Sample count for -b is out of range.\n");
239                                         exit(1);
240                                 }
241                         }
242                         else
243                         {
244                                 printf("-b needs a sample count.\n");
245                                 exit(1);
246                         }
247                 }
248                 else
249                 {
250                         in_path = argv[i];
251                 }
252         }
253
254
255 // Get the field count
256         if(!memcmp(VCODEC, QUICKTIME_MJPA, 4))
257         {
258                 fields = 2;
259         }
260         else
261         {
262                 fields = 1;
263         }
264
265         if(!memcmp(VCODEC, QUICKTIME_H264, 4))
266         {
267
268 #ifdef USE_X264
269                 printf("   X264\n");
270 #endif
271                 is_h264 = 1;
272         }
273
274
275
276         in = fopen(in_path, "rb+");
277         if(!in)
278         {
279                 perror("open input");
280                 exit(1);
281         }
282         
283         fseek(in, STARTING_OFFSET, SEEK_SET);
284         
285
286
287 #ifndef READ_ONLY
288 //      out = quicktime_open(TEMP_FILE, 0, 1);
289 //      if(!out)
290 //      {
291 //              perror("open temp");
292 //              exit(1);
293 //      }
294
295 //      quicktime_set_audio(out, 
296 //              CHANNELS, 
297 //              SAMPLERATE, 
298 //              BITS, 
299 //              QUICKTIME_TWOS);
300 //      quicktime_set_video(out, 
301 //              1, 
302 //              WIDTH, 
303 //              HEIGHT, 
304 //              FRAMERATE, 
305 //              VCODEC);
306
307         audio_out = fopen(AUDIO_FILE, "w");
308         if(!audio_out)
309         {
310                 perror("open audio output");
311                 exit(1);
312         }
313
314         video_out = quicktime_open(VIDEO_FILE, 0, 1);
315                 
316         if(!video_out)
317         {
318                 perror("open video out");
319                 exit(1);
320         }
321
322         quicktime_set_video(video_out, 
323                 1, 
324                 WIDTH, 
325                 HEIGHT, 
326                 FRAMERATE, 
327                 VCODEC);
328         quicktime_set_audio(video_out, 
329                 CHANNELS, 
330                 SAMPLERATE, 
331                 BITS, 
332                 ACODEC);
333
334
335         if(is_h264)
336         {
337                 quicktime_video_map_t *vtrack = &(video_out->vtracks[0]);
338                 quicktime_trak_t *trak = vtrack->track;
339                 quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc;
340                 quicktime_set_avcc_header(avcc,
341                         h264_desc, 
342                         sizeof(h264_desc));
343         }
344         
345 #endif
346
347         audio_start = (int64_t)0x10;
348         ftell_byte = STARTING_OFFSET;
349
350         if(fstat(fileno(in), &status))
351                 perror("get_file_length fstat:");
352         file_size = status.st_size;
353
354
355         NEW_TABLE(start_table, start_size, start_allocation)
356         NEW_TABLE(end_table, end_size, end_allocation)
357         NEW_TABLE(field_table, field_size, field_allocation)
358
359
360
361         audio_frame = BITS * CHANNELS / 8;
362
363 // Tabulate the start and end of all the JPEG images.
364 // This search is intended to be as simple as possible, reserving more
365 // complicated operations for a table pass.
366 //printf("Pass 1 video only.\n");
367         while(ftell_byte < file_size)
368         {
369                 current_byte = ftell_byte;
370                 fread(search_buffer, SEARCH_FRAGMENT, 1, in);
371                 ftell_byte = current_byte + SEARCH_FRAGMENT - SEARCH_PAD;
372                 FSEEK(in, ftell_byte, SEEK_SET);
373
374                 for(i = 0; i < SEARCH_FRAGMENT - SEARCH_PAD; i++)
375                 {
376 // Search for image start
377                         if(state == GOT_NOTHING)
378                         {
379                                 if(is_h264)
380                                 {
381 #ifdef USE_X264
382                                         if(search_buffer[i] == 0x00 &&
383                                                 search_buffer[i + 1] == 0x00 &&
384                                                 search_buffer[i + 4] == 0x06 &&
385                                                 search_buffer[i + 5] == 0x05)
386                                         {
387 //printf("main %d\n", __LINE__);
388                                                 state = GOT_IMAGE_START;
389                                                 image_end = current_byte + i;
390                                                 is_keyframe = next_is_keyframe;
391                                                 next_is_keyframe = 1;
392                                         }
393                                         else
394                                         if(search_buffer[i] == 0x00 &&
395                                                 search_buffer[i + 1] == 0x00 &&
396                                                 search_buffer[i + 4] == 0x41 &&
397                                                 search_buffer[i + 5] == 0x9a)
398                                         {
399 //printf("main %d\n", __LINE__);
400                                                 state = GOT_IMAGE_START;
401                                                 image_end = current_byte + i;
402                                                 is_keyframe = next_is_keyframe;
403                                                 next_is_keyframe = 0;
404                                         }
405
406                                         if(state == GOT_IMAGE_START)
407                                         {
408 // end of previous frame
409                                                 if(start_size > 0) 
410                                                 {
411                                                         APPEND_TABLE(end_table, end_size, end_allocation, image_end)
412 // Copy frame
413                                                         int frame_size = image_end - image_start;
414                                                         FSEEK(in, image_start, SEEK_SET);
415                                                         fread(frame_buffer, frame_size, 1, in);
416                                                         FSEEK(in, ftell_byte, SEEK_SET);
417                                                         quicktime_write_frame(video_out, 
418                                                                 frame_buffer, 
419                                                                 frame_size, 
420                                                                 0);
421                                                         if(is_keyframe)
422                                                         {
423                                                                 quicktime_video_map_t *vtrack = &(video_out->vtracks[0]);
424                                                                 quicktime_insert_keyframe(video_out, 
425                                                                         vtrack->current_position - 1, 
426                                                                         0);
427                                                         }
428                                                         image_start = image_end;
429                                                 }
430 // start of next frame
431                                                 APPEND_TABLE(start_table, start_size, start_allocation, image_start)
432                                                 state = GOT_NOTHING;
433
434
435                                         }
436                                         
437 #else // USE_X264
438                                         if(search_buffer[i] == 0x00 &&
439                                                 search_buffer[i + 1] == 0x00 &&
440                                                 search_buffer[i + 2] == 0x00 &&
441                                                 search_buffer[i + 3] == 0x02 &&
442                                                 search_buffer[i + 4] == 0x09)
443                                         {
444                                                 state = GOT_IMAGE_START;
445                                                 image_start = current_byte + i;
446                                                 if(search_buffer[i + 5] == 0x10)
447                                                         is_keyframe = 1;
448                                                 else
449                                                         is_keyframe = 0;
450                                         }
451 #endif // !USE_X264
452                                 }
453                                 else
454                                 if(search_buffer[i] == 0xff &&
455                                         search_buffer[i + 1] == 0xd8 &&
456                                         search_buffer[i + 2] == 0xff &&
457                                         search_buffer[i + 3] == 0xe1 &&
458                                         search_buffer[i + 10] == 'm' &&
459                                         search_buffer[i + 11] == 'j' &&
460                                         search_buffer[i + 12] == 'p' &&
461                                         search_buffer[i + 13] == 'g')
462                                 {
463                                         state = GOT_IMAGE_START;
464                                         image_start = current_byte + i;
465
466 // Determine the field
467                                         if(fields == 2)
468                                         {
469 // Next field offset is nonzero in first field
470                                                 if(search_buffer[i + 22] != 0 ||
471                                                         search_buffer[i + 23] != 0 ||
472                                                         search_buffer[i + 24] != 0 ||
473                                                         search_buffer[i + 25] != 0)
474                                                 {
475                                                         field = 0;
476                                                 }
477                                                 else
478                                                 {
479                                                         field = 1;
480                                                 }
481                                                 APPEND_TABLE(field_table, field_size, field_allocation, field)
482                                         }
483                                 }
484                                 else
485                                 if(search_buffer[i] == 0xff &&
486                                         search_buffer[i + 1] == 0xd8 &&
487                                         search_buffer[i + 2] == 0xff &&
488                                         search_buffer[i + 3] == 0xe0 &&
489                                         search_buffer[i + 6] == 'J' &&
490                                         search_buffer[i + 7] == 'F' &&
491                                         search_buffer[i + 8] == 'I' &&
492                                         search_buffer[i + 9] == 'F')
493                                 {
494                                         state = GOT_IMAGE_START;
495                                         image_start = current_byte + i;
496                                 }
497                         }
498                         else
499 // Search for image end
500                         if(state == GOT_IMAGE_START)
501                         {
502                                 if(is_h264)
503                                 {
504 // got next frame & end of previous frame or previous audio
505 // search 1 byte ahead so the loop doesn't skip the next frame
506                                         if(search_buffer[i + 1] == 0x00 &&
507                                                 search_buffer[i + 2] == 0x00 &&
508                                                 search_buffer[i + 3] == 0x00 &&
509                                                 search_buffer[i + 4] == 0x02 &&
510                                                 search_buffer[i + 5] == 0x09)
511                                         {
512                                                 state = GOT_NOTHING;
513                                                 image_end = current_byte + i + 1;
514
515 // Read entire frame & get length from NAL codes
516                                                 if(image_end - image_start <= SEARCH_FRAGMENT)
517                                                 {
518                                                         int frame_size = image_end - image_start;
519                                                         FSEEK(in, image_start, SEEK_SET);
520                                                         fread(frame_buffer, frame_size, 1, in);
521                                                         FSEEK(in, ftell_byte, SEEK_SET);
522
523                                                         int new_frame_size = get_h264_size(frame_buffer, frame_size);
524 /*
525  * printf("%d: image_start=%lx image_end=%lx new_frame_size=%x\n",
526  * __LINE__,
527  * image_start,
528  * image_end,
529  * new_frame_size);
530  */
531
532                                                         image_end = image_start + new_frame_size;
533
534 //printf("%d: image_start=0x%lx image_size=0x%x\n", __LINE__, image_start, new_frame_size);
535                                                 }
536                                                 else
537                                                 {
538                                                         printf("%d: Possibly lost image between %llx and %llx\n", 
539                                                                 __LINE__,
540                                                                 image_start,
541                                                                 image_end);
542                                                 }
543
544
545                                                 APPEND_TABLE(start_table, start_size, start_allocation, image_start)
546                                                 APPEND_TABLE(end_table, end_size, end_allocation, image_end)
547
548 #ifndef READ_ONLY
549 // Write frame
550                                                 quicktime_write_frame(video_out, 
551                                                         frame_buffer, 
552                                                         image_end - image_start, 
553                                                         0);
554                                                 if(is_keyframe)
555                                                 {
556                                                         quicktime_video_map_t *vtrack = &(video_out->vtracks[0]);
557                                                         quicktime_insert_keyframe(video_out, 
558                                                                 vtrack->current_position - 1, 
559                                                                 0);
560                                                 }
561
562 // Write audio
563                                                 if(start_size > 1)
564                                                 {
565                                                         int64_t next_frame_start = start_table[start_size - 1];
566                                                         int64_t prev_frame_end = end_table[start_size - 2];
567                                                         int audio_size = next_frame_start - prev_frame_end;
568                                                         if(audio_size > SEARCH_FRAGMENT)
569                                                                 audio_size = SEARCH_FRAGMENT;
570                                                         FSEEK(in, prev_frame_end, SEEK_SET);
571                                                         fread(frame_buffer, audio_size, 1, in);
572                                                         FSEEK(in, ftell_byte, SEEK_SET);
573 //                                                      fwrite(frame_buffer, audio_size, 1, audio_out);
574
575                                                         quicktime_write_vbr_frame(video_out, 
576                                                                 0,
577                                                                 frame_buffer,
578                                                                 audio_size,
579                                                                 audio_chunk);
580                                                 }
581 #endif
582                                         }
583                                 }
584                                 else
585                                 if(search_buffer[i] == 0xff &&
586                                         search_buffer[i + 1] == 0xd9)
587                                 {
588 // ffd9 sometimes occurs inside the mjpg tag
589                                         if(current_byte + i - image_start > 0x2a)
590                                         {
591                                                 state = GOT_NOTHING;
592 // Put it in the table
593                                                 image_end = current_byte + i + 2;
594
595 // An image may have been lost due to encoding errors but we can't do anything
596 // because the audio may by misaligned.  Use the extract utility to get the audio.
597                                                 if(image_end - image_start > audio_chunk * audio_frame)
598                                                 {
599                                                         printf("%d: Possibly lost image between %llx and %llx\n", 
600                                                                 __LINE__,
601                                                                 image_start,
602                                                                 image_end);
603 // Put in fake image
604 /*
605  *                                                      APPEND_TABLE(start_table, start_size, start_allocation, image_start)
606  *                                                      APPEND_TABLE(end_table, end_size, end_allocation, image_start + 1024)
607  *                                                      APPEND_TABLE(start_table, start_size, start_allocation, image_end - 1024)
608  *                                                      APPEND_TABLE(end_table, end_size, end_allocation, image_end)
609  */
610                                                 }
611
612                                                 APPEND_TABLE(start_table, start_size, start_allocation, image_start)
613                                                 APPEND_TABLE(end_table, end_size, end_allocation, image_end)
614
615                                                 int frame_size = image_end - image_start;
616                                                 FSEEK(in, image_start, SEEK_SET);
617                                                 fread(frame_buffer, frame_size, 1, in);
618                                                 FSEEK(in, ftell_byte, SEEK_SET);
619                                                 quicktime_write_frame(video_out, 
620                                                         frame_buffer, 
621                                                         image_end - image_start, 
622                                                         0);
623                 
624
625 //printf("%d %llx - %llx\n", start_size, image_start, image_end - image_start);
626
627 if(!(start_size % 100))
628 {
629 printf("Got %d frames. %d%%\r", 
630 start_size, 
631 current_byte * (int64_t)100 / file_size);
632 fflush(stdout);
633 }
634                                         }
635                                 }
636                         }
637                 }
638         }
639
640
641
642
643 // With the image table complete, 
644 // write chunk table from the gaps in the image table
645 // printf("Pass 2 audio table.\n");
646 //      total_samples = 0;
647 //      for(i = 1; i < start_size; i++)
648 //      {
649 //              int64_t next_image_start = start_table[i];
650 //              int64_t prev_image_end = end_table[i - 1];
651 // 
652 // // Got a chunk
653 //              if(next_image_start - prev_image_end >= audio_chunk * audio_frame)
654 //              {
655 //                      long samples = (next_image_start - prev_image_end) / audio_frame;
656 //                      quicktime_atom_t chunk_atom;
657 // 
658 //                      quicktime_set_position(out, prev_image_end);
659 //                      quicktime_write_chunk_header(out, 
660 //                              out->atracks[0].track, 
661 //                              &chunk_atom);
662 //                      quicktime_set_position(out, next_image_start);
663 //                      quicktime_write_chunk_footer(out,
664 //                              out->atracks[0].track, 
665 //                              out->atracks[0].current_chunk, 
666 //                              &chunk_atom,
667 //                              samples);
668 //                      out->atracks[0].current_position += samples;
669 //                      out->atracks[0].current_chunk++;
670 //                      total_samples += samples;
671 //              }
672 //      }
673 // 
674 // 
675 // 
676 // 
677 // 
678 // // Put image table in movie
679 // printf("Got %d frames %d samples total.\n", start_size, total_samples);
680 //      for(i = 0; i < start_size - fields; i += fields)
681 //      {
682 // // Got a field out of order.  Skip just 1 image instead of 2.
683 //              if(fields == 2 && field_table[i] != 0)
684 //              {
685 //                      printf("Got field out of order at 0x%llx\n", start_table[i]);
686 //                      i--;
687 //              }
688 //              else
689 //              {
690 //                      quicktime_atom_t chunk_atom;
691 //                      quicktime_set_position(out, start_table[i]);
692 //                      quicktime_write_chunk_header(out, 
693 //                              out->vtracks[0].track,
694 //                              &chunk_atom);
695 //                      quicktime_set_position(out, end_table[i + fields - 1]);
696 //                      quicktime_write_chunk_footer(out,
697 //                              out->vtracks[0].track, 
698 //                              out->vtracks[0].current_chunk, 
699 //                              &chunk_atom,
700 //                              1);
701 //                      out->vtracks[0].current_position++;
702 //                      out->vtracks[0].current_chunk++;
703 //              }
704 //      }
705 // 
706 // 
707 // 
708 // 
709 // 
710 // 
711 // 
712 // // Force header out at beginning of temp file
713 //      quicktime_set_position(out, 0x10);
714 //      quicktime_close(out);
715 // 
716 // // Transfer header
717 //      FSEEK(in, 0x8, SEEK_SET);
718 // 
719 //      data[0] = (ftell_byte & 0xff00000000000000LL) >> 56;
720 //      data[1] = (ftell_byte & 0xff000000000000LL) >> 48;
721 //      data[2] = (ftell_byte & 0xff0000000000LL) >> 40;
722 //      data[3] = (ftell_byte & 0xff00000000LL) >> 32;
723 //      data[4] = (ftell_byte & 0xff000000LL) >> 24;
724 //      data[5] = (ftell_byte & 0xff0000LL) >> 16;
725 //      data[6] = (ftell_byte & 0xff00LL) >> 8;
726 //      data[7] = ftell_byte & 0xff;
727 //      fwrite(data, 8, 1, in);
728 // 
729 //      FSEEK(in, ftell_byte, SEEK_SET);
730 //      stat(TEMP_FILE, &ostat);
731 // 
732 //      temp = fopen(TEMP_FILE, "rb");
733 //      FSEEK(temp, 0x10, SEEK_SET);
734 // 
735 //      copy_buffer = calloc(1, ostat.st_size);
736 //      fread(copy_buffer, ostat.st_size, 1, temp);
737 //      fclose(temp);
738 // 
739 // // Enable to alter the original file
740 //      printf("%d: writing header to file\n", __LINE__);
741 //      fwrite(copy_buffer, ostat.st_size, 1, in);
742
743
744         fclose(in);
745
746 #ifndef READ_ONLY
747         quicktime_close(video_out);
748         fclose(audio_out);
749 #endif
750
751 }
752
753
754
755