static int merger(avi_t *out, char *file) { avi_t *in; long frames, n, bytes; int key, j, aud_tracks; static int init = 0; static int vid_chunks = 0; double fps; static double vid_ms; static double aud_ms[AVI_MAX_TRACKS]; int have_printed=0; int do_drop_video=0; if (!init) { for (j=0; j<AVI_MAX_TRACKS; j++) aud_ms[j] = 0.0; vid_ms = 0; vid_chunks = 0; init = 1; } if(indexfile) { if (NULL == (in = AVI_open_input_indexfile(file, 0, indexfile))) { AVI_print_error("AVI open with indexfile"); return(-1); } } else if(NULL == (in = AVI_open_input_file(file,1))) { AVI_print_error("AVI open"); return(-1); } AVI_seek_start(in); fps = AVI_frame_rate(in); frames = AVI_video_frames(in); aud_tracks = AVI_audio_tracks(in); for (n=0; n<frames; ++n) { ++vid_chunks; vid_ms = vid_chunks*1000.0/fps; // audio for(j=0; j<aud_tracks; ++j) { int ret; double old_ms = aud_ms[j]; AVI_set_audio_track(in, j); AVI_set_audio_track(out, j); ret = sync_audio_video_avi2avi (vid_ms, &aud_ms[j], in, out); if (ret<0) { if (ret==-2) { if (aud_ms[j] == old_ms) { do_drop_video = 1; if (!have_printed) { fprintf(stderr, "\nNo audiodata left for track %d->%d (%.2f=%.2f) %s ..\n", AVI_get_audio_track(in), AVI_get_audio_track(out), old_ms, aud_ms[j], (do_drop_video && drop_video)?"breaking (-c)":"continuing"); have_printed++; } } } else { fprintf(stderr, "\nAn error happend at frame %ld track %d\n", n, j); } } } if (do_drop_video && drop_video) { fprintf(stderr, "\n[avimerge] Dropping %ld frames\n", frames-n-1); goto out; } // video bytes = AVI_read_frame(in, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(out, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } // progress fprintf(stderr, "[%s] (%06ld-%06ld) (%.2f <-> %.2f)\r", file, sum_frames, sum_frames + n, vid_ms, aud_ms[0]); } out: fprintf(stderr, "\n"); AVI_close(in); sum_frames += n; return(0); }
/* * avi2raw * required arg1 should be the input AVI file * required arg2 should be the output RAW file */ int main(int argc, char** argv) { /* configurable variables from command line */ bool extractVideo = TRUE; /* FALSE implies extract audio */ u_int32_t start = 0; /* secs, start offset */ u_int32_t duration = 0; /* secs, 0 implies entire file */ bool quiet = FALSE; /* internal variables */ char* aviFileName = NULL; char* rawFileName = NULL; avi_t* aviFile = NULL; FILE* rawFile = NULL; int verbose = FALSE; u_int32_t numBytes, totBytes = 0; bool eliminate_short_frames = FALSE; uint32_t short_frames_len; /* begin process command line */ progName = argv[0]; while (1) { int c = -1; int option_index = 0; static struct option long_options[] = { { "audio", 0, 0, 'a' }, { "eliminate-short-frames", optional_argument, 0, 'e'}, { "length", 1, 0, 'l' }, { "quiet", 0, 0, 'q' }, { "start", 1, 0, 's' }, { "video", 0, 0, 'v' }, { "version", 0, 0, 'V'}, { "verbose", 0, 0, 'R'}, { "help", 0, 0, 'h'}, { NULL, 0, 0, 0 } }; c = getopt_long_only(argc, argv, "ael:qs:vVh", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': fprintf(stderr, "%s - %s version %s\n", progName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); fprintf(stderr, "options:\n"); fprintf(stderr, " --audio - extract audio track\n"); fprintf(stderr, " --length <length> - extract <length> secs\n"); fprintf(stderr, " --quiet - quiet mode\n"); fprintf(stderr, " --start <time> - extract from <start> time\n"); fprintf(stderr, " --video - extract video track\n"); fprintf(stderr, " --eliminate-short-frames <bytes> - eliminate short frames of bytes or less - default 4\n"); return 0; case 'a': { extractVideo = FALSE; break; } case 'e': eliminate_short_frames = TRUE; if (optarg) { if (optarg[0] == '=') optarg[0] = ' '; if (sscanf(optarg, "%u", &short_frames_len) != 1) { fprintf(stderr, "%s:bad eliminate length %s\n", progName, optarg); } } else { short_frames_len = 4; } break; case 'l': { /* --length=<secs> */ u_int i; if (sscanf(optarg, "%u", &i) < 1) { fprintf(stderr, "%s: bad length specified: %s\n", progName, optarg); } else { duration = i; } break; } case 'q': { quiet = TRUE; break; } case 's': { /* --start=<secs> */ u_int i; if (sscanf(optarg, "%u", &i) < 1) { fprintf(stderr, "%s: bad start specified: %s\n", progName, optarg); } else { start = i; } break; } case 'v': { extractVideo = TRUE; break; } case '?': break; case 'R': verbose = TRUE; quiet = FALSE; break; case 'V': fprintf(stderr, "%s - %s version %s\n", progName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); return(0); default: fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", progName, c); } } /* check that we have at least two non-option arguments */ if ((argc - optind) < 2) { fprintf(stderr, "usage: %s <avi-file> <raw-file>\n", progName); exit(1); } /* point to the specified file names */ aviFileName = argv[optind++]; rawFileName = argv[optind++]; /* warn about extraneous non-option arguments */ if (optind < argc) { fprintf(stderr, "%s: unknown options specified, ignoring: ", progName); while (optind < argc) { fprintf(stderr, "%s ", argv[optind++]); } fprintf(stderr, "\n"); } /* end processing of command line */ /* open the AVI file */ aviFile = AVI_open_input_file(aviFileName, TRUE); if (aviFile == NULL) { fprintf(stderr, "%s: error %s: %s\n", progName, aviFileName, AVI_strerror()); exit(4); } if (!quiet) { fprintf(stderr, "%s - %s version %s\n", progName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); } /* open the RAW file */ rawFile = fopen(rawFileName, "wb"); if (rawFile == NULL) { fprintf(stderr, "%s: error opening %s: %s\n", progName, rawFileName, strerror(errno)); exit(5); } if (extractVideo) { double videoFrameRate = AVI_video_frame_rate(aviFile); u_int32_t numVideoFrames = AVI_video_frames(aviFile); u_int32_t fileDuration = ceil(numVideoFrames / videoFrameRate); u_int32_t numDesiredVideoFrames; u_int32_t videoFramesRead = 0; u_int32_t emptyFramesRead = 0; /* get a buffer large enough to handle a frame of raw SDTV */ u_char* buf = (u_char*)malloc(768 * 576 * 4); if (duration) { numDesiredVideoFrames = duration * videoFrameRate; } else { numDesiredVideoFrames = numVideoFrames; } if (buf == NULL) { fprintf(stderr, "%s: error allocating memory: %s\n", progName, strerror(errno)); exit(6); } /* check that start offset is valid */ if (start > fileDuration) { fprintf(stderr, "%s: specified start is past the end of the file\n", progName); exit(7); } if (AVI_seek_start(aviFile)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(8); } if (AVI_set_video_position(aviFile, (long) ROUND(start * videoFrameRate), NULL)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(9); } #ifdef DEBUG_H264 h264_decode_t dec; #endif while (TRUE) { numBytes = AVI_read_frame(aviFile, (char *)buf); /* read error */ if (numBytes < 0) { break; } totBytes += numBytes; videoFramesRead++; if (verbose) { printf("frame %d - len %u total %u\n", videoFramesRead, numBytes, totBytes); } /* * note some capture programs * insert a zero length frame occasionally * hence numBytes == 0, but we're not a EOF */ if ((eliminate_short_frames && numBytes > short_frames_len) || (eliminate_short_frames == FALSE && numBytes)) { // test #ifdef DEBUG_H264 uint32_t offset = 0, read; do { if (h264_is_start_code(buf + offset)) { int ret = h264_detect_boundary(buf + offset, numBytes - offset, &dec); printf(" frame offset %d nal type %d slice %d %d\n", offset, dec.nal_unit_type, dec.slice_type, ret); } read = h264_find_next_start_code(buf + offset, numBytes - offset); offset += read; } while (read != 0 && offset < numBytes); #endif if (fwrite(buf, 1, numBytes, rawFile) != numBytes) { fprintf(stderr, "%s: error writing %s: %s\n", progName, rawFileName, strerror(errno)); break; } } else { emptyFramesRead++; } if (videoFramesRead >= numDesiredVideoFrames) { break; } } if (verbose) { printf("read %u video bytes\n", totBytes); } if (numBytes < 0) { printf("%s: error reading %s, frame %d, %s\n", progName, aviFileName, videoFramesRead + 1, AVI_strerror()); } if (videoFramesRead < numDesiredVideoFrames) { fprintf(stderr, "%s: warning: could only extract %u seconds of video (%u of %u frames)\n", progName, (unsigned int)ceil(videoFramesRead / videoFrameRate), videoFramesRead, numDesiredVideoFrames); } if (emptyFramesRead) { fprintf(stderr, "%s: warning: %u zero length frames ignored\n", progName, emptyFramesRead); } if (!quiet) { printf("%u video frames written\n", videoFramesRead - emptyFramesRead); } /* cleanup */ free(buf); } else { /* extract audio */ u_int32_t audioBytesRead = 0; u_char *buf = (u_char*) malloc(8*1024); u_int32_t numDesiredAudioBytes = AVI_audio_bytes(aviFile); u_int32_t audioBytesPerSec = 0; if (start != 0) { u_int32_t numAudioBytes = numDesiredAudioBytes; u_int32_t fileDuration; audioBytesPerSec = AVI_audio_rate(aviFile) * ((AVI_audio_bits(aviFile) + 7) / 8) * AVI_audio_channels(aviFile); fileDuration = ceil(numAudioBytes / audioBytesPerSec); numDesiredAudioBytes = duration * audioBytesPerSec; /* check that start offset is valid */ if (start > fileDuration) { fprintf(stderr, "%s: specified start is past the end of the file\n", progName); exit(7); } if (AVI_seek_start(aviFile)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(8); } if (AVI_set_audio_position(aviFile, start * audioBytesPerSec)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(9); } } else { if (AVI_seek_start(aviFile)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(8); } if (AVI_set_audio_position(aviFile, 0)) { fprintf(stderr, "%s: bad seek: %s\n", progName, AVI_strerror()); exit(9); } } while ((numBytes = AVI_read_audio(aviFile, (char *)buf, sizeof(buf))) > 0) { if (fwrite(buf, 1, numBytes, rawFile) != numBytes) { fprintf(stderr, "%s: error writing %s: %s\n", progName, rawFileName, strerror(errno)); break; } audioBytesRead += numBytes; if (numDesiredAudioBytes && audioBytesRead >= numDesiredAudioBytes) { break; } } if (verbose) { printf("read %u audio bytes\n", audioBytesRead); } if (duration && audioBytesRead < numDesiredAudioBytes) { fprintf(stderr, "%s: warning: could only extract %u seconds of audio\n", progName, audioBytesPerSec == 0 ? audioBytesRead : audioBytesRead / audioBytesPerSec); } if (!quiet && AVI_audio_bits(aviFile) != 0) { printf("%u audio samples written\n", audioBytesRead / ((AVI_audio_bits(aviFile) + 7) / 8)); } } /* cleanup */ AVI_close(aviFile); fclose(rawFile); return(0); }
int main(int argc, char *argv[]) { avi_t *avifile, *avifile1, *avifile2; char *outfile=NULL, *infile=NULL, *audfile=NULL; long rate, mp3rate; int j, ch, cc=0, track_num=0, out_track_num=-1; int width, height, format=0, format_add, chan, bits, aud_error=0; double fps; char *codec; long offset, frames, n, bytes, aud_offset=0; int key; int aud_tracks; // for mp3 audio FILE *f=NULL; int len, headlen, chan_i, rate_i, mp3rate_i; unsigned long vid_chunks=0; char head[8]; off_t pos; double aud_ms = 0.0, vid_ms = 0.0; double aud_ms_w[AVI_MAX_TRACKS]; ac_init(AC_ALL); if(argc==1) usage(EXIT_FAILURE); while ((ch = getopt(argc, argv, "A:a:b:ci:o:p:f:x:?hv")) != -1) { switch (ch) { case 'i': if(optarg[0]=='-') usage(EXIT_FAILURE); infile = optarg; break; case 'A': if(optarg[0]=='-') usage(EXIT_FAILURE); out_track_num = atoi(optarg); if(out_track_num<-1) usage(EXIT_FAILURE); break; case 'a': if(optarg[0]=='-') usage(EXIT_FAILURE); track_num = atoi(optarg); if(track_num<0) usage(EXIT_FAILURE); break; case 'b': if(optarg[0]=='-') usage(EXIT_FAILURE); is_vbr = atoi(optarg); if(is_vbr<0) usage(EXIT_FAILURE); break; case 'c': drop_video = 1; break; case 'o': if(optarg[0]=='-') usage(EXIT_FAILURE); outfile = optarg; break; case 'p': if(optarg[0]=='-') usage(EXIT_FAILURE); audfile = optarg; break; case 'f': if(optarg[0]=='-') usage(EXIT_FAILURE); comfile = optarg; break; case 'x': if(optarg[0]=='-') usage(EXIT_FAILURE); indexfile = optarg; break; case 'v': version(); exit(EXIT_SUCCESS); case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } if(outfile == NULL || infile == NULL) usage(EXIT_FAILURE); printf("scanning file %s for video/audio parameter\n", infile); // open first file for video/audio info read only if(indexfile) { if (NULL == (avifile1 = AVI_open_input_indexfile(infile,0,indexfile))) { AVI_print_error("AVI open with index file"); } } else if(NULL == (avifile1 = AVI_open_input_file(infile,1))) { AVI_print_error("AVI open"); exit(1); } AVI_info(avifile1); // safety checks if(strcmp(infile, outfile)==0) { printf("error: output filename conflicts with input filename\n"); exit(1); } ch = optind; while (ch < argc) { if(tc_file_check(argv[ch]) != 0) { printf("error: file not found\n"); exit(1); } if(strcmp(argv[ch++], outfile)==0) { printf("error: output filename conflicts with input filename\n"); exit(1); } } // open output file if(NULL == (avifile = AVI_open_output_file(outfile))) { AVI_print_error("AVI open"); exit(1); } // read video info; width = AVI_video_width(avifile1); height = AVI_video_height(avifile1); fps = AVI_frame_rate(avifile1); codec = AVI_video_compressor(avifile1); //set video in outputfile AVI_set_video(avifile, width, height, fps, codec); if (comfile!=NULL) AVI_set_comment_fd(avifile, open(comfile, O_RDONLY)); //multi audio tracks? aud_tracks = AVI_audio_tracks(avifile1); if (out_track_num < 0) out_track_num = aud_tracks; for(j=0; j<aud_tracks; ++j) { if (out_track_num == j) continue; AVI_set_audio_track(avifile1, j); rate = AVI_audio_rate(avifile1); chan = AVI_audio_channels(avifile1); bits = AVI_audio_bits(avifile1); format = AVI_audio_format(avifile1); mp3rate= AVI_audio_mp3rate(avifile1); //printf("TRACK %d MP3RATE %ld VBR %ld\n", j, mp3rate, AVI_get_audio_vbr(avifile1)); //set next track of output file AVI_set_audio_track(avifile, j); AVI_set_audio(avifile, chan, rate, bits, format, mp3rate); AVI_set_audio_vbr(avifile, AVI_get_audio_vbr(avifile1)); } if(audfile!=NULL) goto audio_merge; // close reopen in merger function AVI_close(avifile1); //------------------------------------------------------------- printf("merging multiple AVI-files (concatenating) ...\n"); // extract and write to new files printf ("file %02d %s\n", ++cc, infile); merger(avifile, infile); while (optind < argc) { printf ("file %02d %s\n", ++cc, argv[optind]); merger(avifile, argv[optind++]); } // close new AVI file AVI_close(avifile); printf("... done merging %d file(s) in %s\n", cc, outfile); // reopen file for video/audio info if(NULL == (avifile = AVI_open_input_file(outfile,1))) { AVI_print_error("AVI open"); exit(1); } AVI_info(avifile); return(0); //------------------------------------------------------------- // ************************************************* // Merge the audio track of an additional AVI file // ************************************************* audio_merge: printf("merging audio %s track %d (multiplexing) into %d ...\n", audfile, track_num, out_track_num); // open audio file read only if(NULL == (avifile2 = AVI_open_input_file(audfile,1))) { int f=open(audfile, O_RDONLY), ret=0; char head[1024], *c; c = head; if (f>0 && (1024 == read(f, head, 1024)) ) { while ((c-head<1024-8) && (ret = tc_probe_audio_header(c, 8))<=0 ) { c++; } close(f); if (ret > 0) { aud_offset = c-head; //printf("found atrack 0x%x off=%ld\n", ret, aud_offset); goto merge_mp3; } } AVI_print_error("AVI open"); exit(1); } AVI_info(avifile2); //switch to requested track if(AVI_set_audio_track(avifile2, track_num)<0) { fprintf(stderr, "invalid audio track\n"); } rate = AVI_audio_rate(avifile2); chan = AVI_audio_channels(avifile2); bits = AVI_audio_bits(avifile2); format = AVI_audio_format(avifile2); mp3rate= AVI_audio_mp3rate(avifile2); //set next track AVI_set_audio_track(avifile, out_track_num); AVI_set_audio(avifile, chan, rate, bits, format, mp3rate); AVI_set_audio_vbr(avifile, AVI_get_audio_vbr(avifile2)); AVI_seek_start(avifile1); frames = AVI_video_frames(avifile1); offset = 0; printf ("file %02d %s\n", ++cc, infile); for (n=0; n<AVI_MAX_TRACKS; n++) aud_ms_w[n] = 0.0; vid_chunks=0; for (n=0; n<frames; ++n) { // video bytes = AVI_read_frame(avifile1, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(avifile, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } ++vid_chunks; vid_ms = vid_chunks*1000.0/fps; for(j=0; j<aud_tracks; ++j) { if (j == out_track_num) continue; AVI_set_audio_track(avifile1, j); AVI_set_audio_track(avifile, j); chan = AVI_audio_channels(avifile1); // audio chan = AVI_audio_channels(avifile1); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile); } } // merge additional track // audio chan = AVI_audio_channels(avifile2); AVI_set_audio_track(avifile, out_track_num); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms, avifile2, avifile); } // progress fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n); } fprintf(stderr,"\n"); offset = frames; //more files to merge? AVI_close(avifile1); while (optind < argc) { printf ("file %02d %s\n", ++cc, argv[optind]); if(NULL == ( avifile1 = AVI_open_input_file(argv[optind++],1))) { AVI_print_error("AVI open"); goto finish; } AVI_seek_start(avifile1); frames = AVI_video_frames(avifile1); for (n=0; n<frames; ++n) { // video bytes = AVI_read_frame(avifile1, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(avifile, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } ++vid_chunks; vid_ms = vid_chunks*1000.0/fps; // audio for(j=0; j<aud_tracks; ++j) { if (j == out_track_num) continue; AVI_set_audio_track(avifile1, j); AVI_set_audio_track(avifile, j); chan = AVI_audio_channels(avifile1); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile); } } // merge additional track chan = AVI_audio_channels(avifile2); AVI_set_audio_track(avifile, out_track_num); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms, avifile2, avifile); } // chan // progress fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n); } fprintf(stderr, "\n"); offset += frames; AVI_close(avifile1); } finish: // close new AVI file printf("... done multiplexing in %s\n", outfile); AVI_info(avifile); AVI_close(avifile); return(0); // ************************************************* // Merge a raw audio file which is either MP3 or AC3 // ************************************************* merge_mp3: f = fopen(audfile,"rb"); if (!f) { perror ("fopen"); exit(1); } fseek(f, aud_offset, SEEK_SET); len = fread(head, 1, 8, f); format_add = tc_probe_audio_header(head, len); headlen = tc_get_audio_header(head, len, format_add, &chan_i, &rate_i, &mp3rate_i); fprintf(stderr, "... this looks like a %s track ...\n", (format_add==0x55)?"MP3":"AC3"); fseek(f, aud_offset, SEEK_SET); //set next track AVI_set_audio_track(avifile, out_track_num); AVI_set_audio(avifile, chan_i, rate_i, 16, format_add, mp3rate_i); AVI_set_audio_vbr(avifile, is_vbr); AVI_seek_start(avifile1); frames = AVI_video_frames(avifile1); offset = 0; for (n=0; n<AVI_MAX_TRACKS; ++n) aud_ms_w[n] = 0.0; for (n=0; n<frames; ++n) { // video bytes = AVI_read_frame(avifile1, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(avifile, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } vid_chunks++; vid_ms = vid_chunks*1000.0/fps; for(j=0; j<aud_tracks; ++j) { if (j == out_track_num) continue; AVI_set_audio_track(avifile1, j); AVI_set_audio_track(avifile, j); chan = AVI_audio_channels(avifile1); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile); } } // merge additional track if(headlen>4 && !aud_error) { while (aud_ms < vid_ms) { //printf("reading Audio Chunk ch(%ld) vms(%lf) ams(%lf)\n", vid_chunks, vid_ms, aud_ms); pos = ftell(f); len = fread (head, 1, 8, f); if (len<=0) { //eof fprintf(stderr, "EOF in %s; continuing ..\n", audfile); aud_error=1; break; } if ( (headlen = tc_get_audio_header(head, len, format_add, NULL, NULL, &mp3rate_i))<0) { fprintf(stderr, "Broken %s track #(%d)? skipping\n", (format_add==0x55?"MP3":"AC3"), aud_tracks); aud_ms = vid_ms; aud_error=1; } else { // look in import/tcscan.c for explanation aud_ms += (headlen*8.0)/(mp3rate_i); } fseek (f, pos, SEEK_SET); len = fread (data, headlen, 1, f); if (len<=0) { //eof fprintf(stderr, "EOF in %s; continuing ..\n", audfile); aud_error=1; break; } AVI_set_audio_track(avifile, out_track_num); if(AVI_write_audio(avifile, data, headlen)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } } // progress fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n); } fprintf(stderr,"\n"); offset = frames; // more files? while (optind < argc) { printf ("file %02d %s\n", ++cc, argv[optind]); if(NULL == ( avifile1 = AVI_open_input_file(argv[optind++],1))) { AVI_print_error("AVI open"); goto finish; } AVI_seek_start(avifile1); frames = AVI_video_frames(avifile1); for (n=0; n<frames; ++n) { // video bytes = AVI_read_frame(avifile1, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(avifile, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } vid_chunks++; vid_ms = vid_chunks*1000.0/fps; for(j=0; j<aud_tracks; ++j) { if (j == out_track_num) continue; AVI_set_audio_track(avifile1, j); AVI_set_audio_track(avifile, j); chan = AVI_audio_channels(avifile1); if(chan) { sync_audio_video_avi2avi(vid_ms, &aud_ms_w[j], avifile1, avifile); } } // merge additional track // audio if(headlen>4 && !aud_error) { while (aud_ms < vid_ms) { //printf("reading Audio Chunk ch(%ld) vms(%lf) ams(%lf)\n", vid_chunks, vid_ms, aud_ms); pos = ftell(f); len = fread (head, 8, 1, f); if (len<=0) { //eof fprintf(stderr, "EOF in %s; continuing ..\n", audfile); aud_error=1; break; } if ( (headlen = tc_get_audio_header(head, len, format_add, NULL, NULL, &mp3rate_i))<0) { fprintf(stderr, "Broken %s track #(%d)?\n", (format_add==0x55?"MP3":"AC3"), aud_tracks); aud_ms = vid_ms; aud_error=1; } else { // look in import/tcscan.c for explanation aud_ms += (headlen*8.0)/(mp3rate_i); } fseek (f, pos, SEEK_SET); len = fread (data, headlen, 1, f); if (len<=0) { //eof fprintf(stderr, "EOF in %s; continuing ..\n", audfile); aud_error=1; break; } AVI_set_audio_track(avifile, out_track_num); if(AVI_write_audio(avifile, data, headlen)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } } // progress fprintf(stderr, "[%s] (%06ld-%06ld)\r", outfile, offset, offset + n); } fprintf(stderr, "\n"); offset += frames; AVI_close(avifile1); } if (f) fclose(f); printf("... done multiplexing in %s\n", outfile); AVI_close(avifile); return(0); }