void dump_frame(BIFSVID b2v, char *conv_buf, char *out_path, u32 dump_type, avi_t *avi_out, u32 frameNum) { u32 k; M4VideoSurface fb; /*lock it*/ SR_GetScreenBuffer(b2v.sr, &fb); /*export frame*/ switch (dump_type) { case 0: /*reverse frame*/ for (k=0; k<fb.height; k++) { memcpy(conv_buf + k*fb.width*3, fb.video_buffer + (fb.height-k-1) * fb.pitch, sizeof(char) * fb.width * 3); } if (AVI_write_frame(avi_out, conv_buf, fb.height*fb.width*3, 1) <0) printf("Error writing frame\n"); break; case 2: write_raw(&fb, out_path, frameNum); break; case 1: write_bmp(&fb, out_path, frameNum); break; } /*unlock it*/ SR_ReleaseScreenBuffer(b2v.sr, &fb); }
static int append_avi(RenderData *UNUSED(rd), int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *UNUSED(reports)) { unsigned int *rt1, *rt2, *rectot; int x, y; char *cp, rt; if (avi == NULL) return 0; /* note that libavi free's the buffer... stupid interface - zr */ rectot = MEM_mallocN(rectx * recty * sizeof(int), "rectot"); rt1 = rectot; rt2 = (unsigned int *)pixels + (recty - 1) * rectx; /* flip y and convert to abgr */ for (y = 0; y < recty; y++, rt1 += rectx, rt2 -= rectx) { memcpy(rt1, rt2, rectx * sizeof(int)); cp = (char *)rt1; for (x = rectx; x > 0; x--) { rt = cp[0]; cp[0] = cp[3]; cp[3] = rt; rt = cp[1]; cp[1] = cp[2]; cp[2] = rt; cp += 4; } } AVI_write_frame(avi, (frame - start_frame), AVI_FORMAT_RGB32, rectot, rectx * recty * 4); // printf ("added frame %3d (frame %3d in avi): ", frame, frame-start_frame); return 1; }
/* ///////////////////////////////////////////////////////////////////////////// * Write AVI file */ int TTAVIWriter::writeAVI(int startIndex, int endIndex, const QFileInfo& aviFInfo) { QTime searchTime; TFrameInfo* frameInfo; int frameCount = endIndex - startIndex + 1; log->debugMsg(__FILE__, __LINE__, "---------------------------------------------"); log->debugMsg(__FILE__, __LINE__, QString("write AVI start %1 / end %2 / count %3"). arg(startIndex).arg(endIndex).arg(frameCount)); avi_file = AVI_open_output_file(aviFInfo.absoluteFilePath().toLatin1().data()); //TODO: go back to previous sequence to ensure correct encoding of // open GOP's current_frame = decoder->moveToFrameIndex(startIndex); // decode the current slice //frameInfo = decoder->decodeMPEG2Frame( formatYV12 ); frameInfo = decoder->getFrameInfo(); log->debugMsg(__FILE__, __LINE__, QString("AVI %1 width %2 x height %3"). arg(aviFInfo.absoluteFilePath()). arg(frameInfo->width). arg(frameInfo->height)); AVI_set_video(avi_file, frameInfo->width, frameInfo->height, mFrameRate, (char*)"YV12"); ref_data = new quint8[frameInfo->size+2*frameInfo->chroma_size]; //for (int i = start_frame_pos; i <= end_frame_pos; i++) for (int i = 1; i <= frameCount; i++) { // get decoded mpeg-frame data decoder->getCurrentFrameData(ref_data); log->debugMsg(__FILE__, __LINE__, QString("write frame %1 with frame-type %2"). arg(startIndex+i-1). arg(frameInfo->type)); // write the mpeg-frame data to AVI file AVI_write_frame(avi_file, (char*)ref_data, frameInfo->size+2*frameInfo->chroma_size, 2); // decode the next mpeg-frame decoder->moveToFrameIndex(startIndex+i); frameInfo = decoder->getFrameInfo(); //frameInfo = decoder->decodeMPEG2Frame( formatYV12 ); } log->debugMsg(__FILE__, __LINE__, "---------------------------------------------"); delete [] ref_data; return frameCount; }
static void index_rebuild_fallback(FallbackIndexBuilderContext *context, short *stop, short *do_update, float *progress) { int cnt = IMB_anim_get_duration(context->anim, IMB_TC_NONE); int i, pos; struct anim *anim = context->anim; for (pos = 0; pos < cnt; pos++) { struct ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); struct ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf); float next_progress = (float) pos / (float) cnt; if (*progress != next_progress) { *progress = next_progress; *do_update = TRUE; } if (*stop) { break; } IMB_flipy(tmp_ibuf); for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (context->proxy_sizes_in_use & proxy_sizes[i]) { int x = anim->x * proxy_fac[i]; int y = anim->y * proxy_fac[i]; struct ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf); IMB_scalefastImBuf(s_ibuf, x, y); IMB_convert_rgba_to_abgr(s_ibuf); AVI_write_frame(context->proxy_ctx[i], pos, AVI_FORMAT_RGB32, s_ibuf->rect, x * y * 4); /* note that libavi free's the buffer... */ s_ibuf->rect = NULL; IMB_freeImBuf(s_ibuf); } } IMB_freeImBuf(tmp_ibuf); IMB_freeImBuf(ibuf); } }
/* ///////////////////////////////////////////////////////////////////////////// * Write AVI file */ int TTAVIWriter::writeAVI(int start_frame_pos, int end_frame_pos, const QFileInfo& avi_finfo) { QTime searchTime; TFrameInfo* frameInfo; int frame_count = end_frame_pos - start_frame_pos; //qDebug( "%s------------------------------------------------",c_name ); //qDebug( "%swrite AVI: start: %ld | end: %ld | count: %d",c_name,start_frame_pos,end_frame_pos,frame_count ); //qDebug( "%s------------------------------------------------",c_name ); avi_file = AVI_open_output_file( avi_finfo.absoluteFilePath().toLatin1().data() ); //TODO: go back to previous sequence to ensure correct encoding of // open GOP's // move decode position to "ref_frame_pos" current_frame = decoder->moveToFrameIndex( start_frame_pos ); // decode the current slice frameInfo = decoder->decodeMPEG2Frame( formatYV12 ); //qDebug( "%sAVI frame info: width: %d x height: %d",c_name,frameInfo->width,frameInfo->height ); //TODO: avoid setting hard coded frame rate! AVI_set_video(avi_file, frameInfo->width, frameInfo->height, 25.0, (char*)"YV12"); ref_data = new quint8[frameInfo->size+2*frameInfo->chroma_size]; for (int i = start_frame_pos; i <= end_frame_pos; i++) { // get decoded mpeg-frame data decoder->getCurrentFrameData( ref_data ); // write the mpeg-frame data to AVI file AVI_write_frame(avi_file, (char*)ref_data, frameInfo->size+2*frameInfo->chroma_size, 2); // decode the next mpeg-frame frameInfo = decoder->decodeMPEG2Frame( formatYV12 ); } //qDebug( "%s------------------------------------------------",c_name ); delete [] ref_data; return frame_count; }
int main_loop(void *data) { int ret=0; int i,j,k,l,m,n,o; unsigned int YUVMacroPix; unsigned char *pix8 = (unsigned char *)&YUVMacroPix; Pix *pix2; char *pix; if ((pix2= malloc(sizeof(Pix)))==NULL) { printf("couldn't allocate memory for: pix2\n"); ret=1; return(ret); } //fprintf(stderr,"Thread started...\n"); /* ImageSurf=SDL_CreateRGBSurface(SDL_SWSURFACE, overlay->w, overlay->h, 24, 0x00ff0000,0x0000ff00,0x000000ff,0); */ while (videoIn->signalquit) { currtime = SDL_GetTicks(); if (currtime - lasttime > 0) { frmrate = 1000/(currtime - lasttime); } lasttime = currtime; // sprintf(capt,"Frame Rate: %d",frmrate); // SDL_WM_SetCaption(capt, NULL); if (uvcGrab(videoIn) < 0) { printf("Error grabbing=> Frame Rate is %d\n",frmrate); videoIn->signalquit=0; ret = 2; } SDL_LockYUVOverlay(overlay); memcpy(p, videoIn->framebuffer, videoIn->width * (videoIn->height) * 2); SDL_UnlockYUVOverlay(overlay); SDL_DisplayYUVOverlay(overlay, &drect); /*capture Image*/ if (videoIn->capImage){ if((pim= malloc((pscreen->w)*(pscreen->h)*3))==NULL){/*24 bits -> 3bytes 32 bits ->4 bytes*/ printf("Couldn't allocate memory for: pim\n"); videoIn->signalquit=0; ret = 3; } //char *ppmheader = "P6\n# Generated by guvcview\n320 240\n255\n"; //FILE * out = fopen("Yimage.ppm", "wb"); //saving as ppm //fprintf(out, ppmheader); k=overlay->h; //printf("overlay->h is %i\n",overlay->h); //printf("and pitches[0] is %i\n",overlay->pitches[0]); for(j=0;j<(overlay->h);j++){ l=j*overlay->pitches[0];/*must add lines already writen=*/ /*pitches is the overlay number */ /*off bytes in a line (2*width) */ m=(k*3*overlay->pitches[0])>>1;/*must add lines already writen= */ /*for this case (rgb) every pixel */ /*as 3 bytes (3*width=3*pitches/2) */ /* >>1 = (/2) divide by 2 (?faster?)*/ for (i=0;i<((overlay->pitches[0])>>2);i++){ /*>>2 = (/4)*/ /*iterate every 4 bytes (32 bits)*/ /*Y-U-V-Y1 =>2 pixel (4 bytes) */ n=i<<2;/*<<2 = (*4) multiply by 4 (?faster?)*/ pix8[0] = p[n+l]; pix8[1] = p[n+1+l]; pix8[2] = p[n+2+l]; pix8[3] = p[n+3+l]; /*get RGB data*/ pix2=yuv2rgb(YUVMacroPix,0,pix2); /*In BitMaps lines are upside down and*/ /*pixel format is bgr */ o=i*6; /*first pixel*/ pim[o+m]=pix2->b; pim[o+1+m]=pix2->g; pim[o+2+m]=pix2->r; /*second pixel*/ pim[o+3+m]=pix2->b1; pim[o+4+m]=pix2->g1; pim[o+5+m]=pix2->r1; } k--; } /* SDL_LockSurface(ImageSurf); memcpy(pix, pim,(pscreen->w)*(pscreen->h)*3); //24 bits -> 3bytes 32 bits ->4 bytes SDL_UnlockSurface(ImageSurf);*/ if(SaveBPM(videoIn->ImageFName, width, height, 24, pim)) { fprintf (stderr,"Error: Couldn't capture Image to %s \n", videoIn->ImageFName); } else { printf ("Capture Image to %s \n",videoIn->ImageFName); } free(pim); videoIn->capImage=FALSE; } /*capture AVI */ if (videoIn->capAVI && videoIn->signalquit){ long framesize; switch (AVIFormat) { case 1: framesize=(pscreen->w)*(pscreen->h)*2; /*YUY2 -> 2 bytes per pixel */ if (AVI_write_frame (AviOut, p, framesize) < 0) printf ("write error on avi out \n"); break; case 2: framesize=(pscreen->w)*(pscreen->h)*3; /*DIB 24/32 -> 3/4 bytes per pixel*/ if((pim= malloc(framesize))==NULL){ printf("Couldn't allocate memory for: pim\n"); videoIn->signalquit=0; ret = 4; } k=overlay->h; for(j=0;j<(overlay->h);j++){ l=j*overlay->pitches[0];/*must add lines already writen=*/ /*pitches is the overlay number */ /*off bytes in a line (2*width) */ m=(k*3*overlay->pitches[0])>>1;/*must add lines already writen= */ /*for this case (rgb) every pixel */ /*as 3 bytes (3*width=3*pitches/2) */ /* >>1 = (/2) divide by 2 (?faster?)*/ for (i=0;i<((overlay->pitches[0])>>2);i++){ /*>>2 = (/4)*/ /*iterate every 4 bytes (32 bits)*/ /*Y-U-V-Y1 =>2 pixel (4 bytes) */ n=i<<2;/*<<2 = (*4) multiply by 4 (?faster?)*/ pix8[0] = p[n+l]; pix8[1] = p[n+1+l]; pix8[2] = p[n+2+l]; pix8[3] = p[n+3+l]; /*get RGB data*/ pix2=yuv2rgb(YUVMacroPix,0,pix2); /*In BitMaps lines are upside down and*/ /*pixel format is bgr */ o=i*6; /*first pixel*/ pim[o+m]=pix2->b; pim[o+1+m]=pix2->g; pim[o+2+m]=pix2->r; /*second pixel*/ pim[o+3+m]=pix2->b1; pim[o+4+m]=pix2->g1; pim[o+5+m]=pix2->r1; } k--; } if (AVI_write_frame (AviOut, pim, framesize) < 0) printf ("write error on avi out \n"); free(pim); break; } framecount++; } SDL_Delay(SDL_WAIT_TIME); }
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); }
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); }
Revel_Error Revel_XvidEncoder::EncodeFrame(const Revel_VideoFrame& frame, int *frameSize) { Revel_Error revError = Revel_BaseEncoder::EncodeFrame(frame, frameSize); if (revError != REVEL_ERR_NONE) return revError; // Version for the frame and the stats xvid_enc_frame_t xvid_enc_frame; memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame)); xvid_enc_frame.version = XVID_VERSION; xvid_enc_stats_t xvid_enc_stats; memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats)); xvid_enc_stats.version = XVID_VERSION; // Bind output buffer xvid_enc_frame.bitstream = m_encodedFrame; xvid_enc_frame.length = -1; // Initialize input image fields if (frame.pixels != NULL) { xvid_enc_frame.input.plane[0] = frame.pixels; xvid_enc_frame.input.csp = GetXvidPixelFormat(frame.pixelFormat); // XviD expects the origin in the upper left. If the user specified it in the lower // left, pass a flag to flip the frame before encoding. if (m_params.origin == REVEL_ORIGIN_LOWER_LEFT) xvid_enc_frame.input.csp |= XVID_CSP_VFLIP; xvid_enc_frame.input.stride[0] = frame.width * frame.bytesPerPixel; } else { xvid_enc_frame.input.csp = XVID_CSP_NULL; } // Set up core's general features xvid_enc_frame.vol_flags = 0; // Set up core's general features int quality = GetXvidQuality(m_params.quality); xvid_enc_frame.vop_flags = vop_presets[quality]; // Frame type -- let core decide for us xvid_enc_frame.type = XVID_TYPE_AUTO; // Force the right quantizer -- It is internally managed by RC plugins xvid_enc_frame.quant = 0; // Set up motion estimation flags xvid_enc_frame.motion = motion_presets[quality]; // We don't use special matrices xvid_enc_frame.quant_intra_matrix = NULL; xvid_enc_frame.quant_inter_matrix = NULL; // Encode the frame int frameBytes = xvid_encore(m_xvidEncoderHandle, XVID_ENC_ENCODE, &xvid_enc_frame, &xvid_enc_stats); // Write the frame to the output stream. int aviErr = AVI_write_frame(m_outFile, m_encodedFrame, frameBytes); if (aviErr != 0) return REVEL_ERR_FILE; m_totalOutBytes += frameBytes; if (frameSize != NULL) *frameSize = frameBytes; return REVEL_ERR_NONE; }
/** * This thread sends the frame to TS mux * \param Parameter The GF_AVRedirect pointer */ static Bool video_encoding_thread_run(void *param) { GF_AVRedirect * avr = (GF_AVRedirect*) param; u64 currentFrameTimeProcessed = 0; u32 lastEncodedFrameTime = 0; AVCodecContext * ctx = NULL; assert( avr ); gf_sc_add_video_listener ( avr->term->compositor, &avr->video_listen ); while (avr->is_running && (!ctx || !avr->swsContext)) { ctx = ts_get_video_codec_context(avr->ts_implementation); gf_sleep(16); } if (!ctx) { goto exit; } printf("******* Video Codec Context = %d/%d, start="LLU"\n", ctx->time_base.num, ctx->time_base.den, ctx->timecode_frame_start); while (avr->is_running) { { gf_mx_p(avr->frameMutex); while (!avr->frameTime || currentFrameTimeProcessed == avr->frameTime) { gf_mx_v(avr->frameMutex); if (!avr->is_running) { goto exit; } gf_mx_p(avr->frameMutex); gf_sleep(1); } assert( currentFrameTimeProcessed != avr->frameTime); currentFrameTimeProcessed = avr->frameTime; { avpicture_fill ( ( AVPicture * ) avr->RGBpicture, avr->frame, PIX_FMT_RGB24, avr->srcWidth, avr->srcHeight ); assert( avr->swsContext ); sws_scale ( avr->swsContext, #ifdef USE_AVCODEC2 ( const uint8_t * const * ) #else ( uint8_t ** ) #endif /* USE_AVCODEC2 */ avr->RGBpicture->data, avr->RGBpicture->linesize, 0, avr->srcHeight, avr->YUVpicture->data, avr->YUVpicture->linesize ); #ifdef AVR_DUMP_RAW_AVI if ( AVI_write_frame ( avr->avi_out, avr->frame, avr->size, 1 ) <0 ) { GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error writing video frame\n" ) ); } #endif /* AVR_DUMP_RAW_AVI */ gf_mx_v(avr->frameMutex); if (avr->encode) { int written; //u32 sysclock = gf_sys_clock(); avr->YUVpicture->pts = currentFrameTimeProcessed; //printf("Encoding frame PTS="LLU", frameNum=%u, time=%u...", avr->YUVpicture->pts, avr->YUVpicture->coded_picture_number, currentFrameTimeProcessed); written = avcodec_encode_video ( ctx, avr->videoOutbuf, avr->videoOutbufSize, avr->YUVpicture ); //ctx->coded_frame->pts = currentFrameTimeProcessed; if ( written < 0 ) { GF_LOG ( GF_LOG_ERROR, GF_LOG_MODULE, ( "[AVRedirect] Error while encoding video frame =%d\n", written ) ); } else if ( written > 0 ) { ts_encode_video_frame(avr->ts_implementation, avr->videoOutbuf, written); } lastEncodedFrameTime = currentFrameTimeProcessed; } } } avr->frameTimeEncoded = currentFrameTimeProcessed; gf_sleep(1); } /* End of main loop */ exit: GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[AVRedirect] Ending video encoding thread...\n")); if (avr->term) gf_sc_remove_video_listener ( avr->term->compositor, &avr->video_listen ); return 0; }
int evid_enc_frame(evid_handler_t *evid_handler, pixel_t *frame) { xvid_enc_frame_t xvid_enc_frame; handler_t *handler=(handler_t *)evid_handler; static const int vop_presets[] = { 0, 0, XVID_VOP_HALFPEL, XVID_VOP_HALFPEL | XVID_VOP_INTER4V, XVID_VOP_HALFPEL | XVID_VOP_INTER4V, XVID_VOP_HALFPEL | XVID_VOP_INTER4V | XVID_VOP_TRELLISQUANT, XVID_VOP_HALFPEL | XVID_VOP_INTER4V | XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED, }; static const int motion_presets[] = { 0, XVID_ME_ADVANCEDDIAMOND16, XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16, XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8, XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP, XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP, XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 | XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 | XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP, }; int frame_size; // XviD memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame)); xvid_enc_frame.version=XVID_VERSION; xvid_enc_frame.vol_flags=0; xvid_enc_frame.vol_flags|=XVID_VOL_INTERLACING; xvid_enc_frame.quant_intra_matrix=NULL; xvid_enc_frame.quant_inter_matrix=NULL; xvid_enc_frame.par=XVID_PAR_11_VGA; xvid_enc_frame.par_width=1; xvid_enc_frame.par_height=1; xvid_enc_frame.fincr=0; xvid_enc_frame.vop_flags=vop_presets[handler->evid_xvidpar.quality]; if(handler->evid_xvidpar.gray) xvid_enc_frame.vop_flags|=XVID_VOP_GREYSCALE; xvid_enc_frame.motion=motion_presets[handler->evid_xvidpar.quality]; xvid_enc_frame.input.csp=XVID_CSP_YUY2; xvid_enc_frame.input.plane[0]=frame; xvid_enc_frame.input.stride[0]=handler->frame_par.width*PALETTE_DEPTH; xvid_enc_frame.type=XVID_TYPE_AUTO; xvid_enc_frame.quant=handler->evid_xvidpar.quant; xvid_enc_frame.bitstream=handler->xvid.bitstream; xvid_enc_frame.length=-1; frame_size=xvid_encore(handler->xvid.handle, XVID_ENC_ENCODE, &xvid_enc_frame, NULL); // avilib if(AVI_write_frame(handler->avilib.avi, (char *)handler->xvid.bitstream, (long)frame_size, ((xvid_enc_frame.out_flags&XVID_KEYFRAME)?1:0))) { free(handler->errstr); switch(AVI_errno) { case AVI_ERR_SIZELIM: return 1; break; default: x_asprintf(&handler->errstr, "Error writing encoded frame to AVI file: %s.\n", AVI_strerror()); break; } return 1; } // update header if(AVI_make_header(handler->avilib.avi)) { free(handler->errstr); x_asprintf(&handler->errstr, "Error writing encoded frame to AVI file: %s.\n", AVI_strerror()); return 1; } return 0; }
static void index_rebuild_fallback(struct anim * anim, IMB_Timecode_Type UNUSED(tcs_in_use), IMB_Proxy_Size proxy_sizes_in_use, int quality, short *stop, short *do_update, float *progress) { int cnt = IMB_anim_get_duration(anim, IMB_TC_NONE); int i, pos; AviMovie * proxy_ctx[IMB_PROXY_MAX_SLOT]; char fname[FILE_MAXDIR+FILE_MAXFILE]; char fname_tmp[FILE_MAXDIR+FILE_MAXFILE]; memset(proxy_ctx, 0, sizeof(proxy_ctx)); /* since timecode indices only work with ffmpeg right now, don't know a sensible fallback here... so no proxies, no game to play... */ if (proxy_sizes_in_use == IMB_PROXY_NONE) { return; } for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (proxy_sizes_in_use & proxy_sizes[i]) { char fname[FILE_MAXDIR+FILE_MAXFILE]; get_proxy_filename(anim, proxy_sizes[i], fname, TRUE); BLI_make_existing_file(fname); proxy_ctx[i] = alloc_proxy_output_avi( anim, fname, anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality); } } for (pos = 0; pos < cnt; pos++) { struct ImBuf * ibuf = IMB_anim_absolute( anim, pos, IMB_TC_NONE, IMB_PROXY_NONE); int next_progress = (int) ((double) pos / (double) cnt); if (*progress != next_progress) { *progress = next_progress; *do_update = 1; } if (*stop) { break; } IMB_flipy(ibuf); for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (proxy_sizes_in_use & proxy_sizes[i]) { int x = anim->x * proxy_fac[i]; int y = anim->y * proxy_fac[i]; struct ImBuf * s_ibuf = IMB_scalefastImBuf( ibuf, x, y); IMB_convert_rgba_to_abgr(s_ibuf); AVI_write_frame (proxy_ctx[i], pos, AVI_FORMAT_RGB32, s_ibuf->rect, x * y * 4); /* note that libavi free's the buffer... */ s_ibuf->rect = 0; IMB_freeImBuf(s_ibuf); } } } for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (proxy_sizes_in_use & proxy_sizes[i]) { AVI_close_compress (proxy_ctx[i]); MEM_freeN (proxy_ctx[i]); get_proxy_filename(anim, proxy_sizes[i], fname_tmp, TRUE); get_proxy_filename(anim, proxy_sizes[i], fname, FALSE); if (*stop) { unlink(fname_tmp); } else { rename(fname_tmp, fname); } } } }
int main(int argc, char *argv[]) { int opt_shutter_angle = 0; int opt_mjpeg_quality = 100; int nf, i, nc, nr; int tfs, fps; vc *pos_i, *pos_h, *pos_y; es_ctx *es; rs_ctx *rs; opterr = 0; while ((i = getopt(argc, argv, "r:q:")) != -1) { switch (i) { case 'r': opt_shutter_angle = atoi(optarg); break; case 'q': opt_mjpeg_quality = atoi(optarg); break; default: print_help(argv); } } if (argc < optind + 2) print_help(argv); if (AVI_open_movie(argv[optind], &mv_in) != AVI_ERROR_NONE) { printf("error: can't read from %s\n", argv[optind]); return EXIT_FAILURE; } if (mv_in.header->Streams < 1 || mv_in.streams[0].sh.Type != AVIST_VIDEO) { printf("error: video stream not found on %s\n", argv[optind]); return EXIT_FAILURE; } if (AVI_open_compress(argv[optind + 1], &mv_out, 1, AVI_FORMAT_MJPEG) != AVI_ERROR_NONE) { printf("error: can't write to %s\n", argv[optind + 1]); return EXIT_FAILURE; } printf("status: setup\n"); prepare_lanc_kernels(); nc = mv_in.header->Width; nr = mv_in.header->Height; tfs = mv_in.header->TotalFrames; fps = 1000000 / mv_in.header->MicroSecPerFrame; pos_i = (vc *)malloc(tfs * sizeof(vc)); pos_h = (vc *)malloc(tfs * sizeof(vc)); pos_y = (vc *)malloc(nr * sizeof(vc)); AVI_set_compress_option(&mv_out, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &nc); AVI_set_compress_option(&mv_out, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &nr); AVI_set_compress_option(&mv_out, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &fps); AVI_set_compress_option(&mv_out, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &opt_mjpeg_quality); es = es_init(nc, nr); rs = rs_init(nc, nr); printf("status: estimating\n"); for (nf = 0; nf < tfs; nf ++) { unsigned char *fr = (unsigned char *)AVI_read_frame(&mv_in, AVI_FORMAT_RGB24, nf, 0); pos_i[nf] = vc_add( nf > 0 ? pos_i[nf - 1] : vc_set(0.0, 0.0), es_estimate(es, fr) ); free(fr); if ((nf + 1) % 10 == 0) { printf("."); fflush(stdout); } } printf("\nstatus: filtering\n"); hipass(pos_i, pos_h, tfs, fps / 2); printf("status: resampling\n"); for (nf = 0; nf < tfs; nf ++) { unsigned char *fr = (unsigned char *)AVI_read_frame(&mv_in, AVI_FORMAT_RGB24, nf, 0); for (i = 0; i < nr; i ++) { pos_y[i] = interp( pos_h, tfs, nf + (i - nr / 2.0) * opt_shutter_angle / (nr * 360.0) ); } rs_resample(rs, fr, pos_y); AVI_write_frame(&mv_out, nf, AVI_FORMAT_RGB24, fr, nc * nr * 3 * sizeof(unsigned char)); if ((nf + 1) % 10 == 0) { printf("."); fflush(stdout); } } printf("\nstatus: closing\n"); es_free(es); rs_free(rs); free_lanc_kernels(); AVI_close(&mv_in); AVI_close_compress(&mv_out); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { avi_t *avifile1=NULL; avi_t *avifile2=NULL; avi_t *avifile3=NULL; char *in_file=NULL, *out_file=NULL; long frames, bytes; double fps; char *codec; int track_num=0, aud_tracks; int encode_null=0; int i, j, n, key, shift=0; int ch, preload=0; long rate, mp3rate; int width, height, format, chan, bits; int be_quiet = 0; FILE *status_fd = stderr; /* for null frame encoding */ char nulls[32000]; long nullbytes=0; char tmp0[] = "/tmp/nullfile.00.avi"; /* XXX: use mktemp*() */ buffer_list_t *ptr; double vid_ms = 0.0, shift_ms = 0.0, one_vid_ms = 0.0; double aud_ms [ AVI_MAX_TRACKS ]; int aud_bitrate = 0; int aud_chunks = 0; ac_init(AC_ALL); if(argc==1) usage(EXIT_FAILURE); while ((ch = getopt(argc, argv, "a:b:vi:o:n:Nq?h")) != -1) { switch (ch) { case 'i': if(optarg[0]=='-') usage(EXIT_FAILURE); in_file=optarg; 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 'o': if(optarg[0]=='-') usage(EXIT_FAILURE); out_file=optarg; break; case 'f': if(optarg[0]=='-') usage(EXIT_FAILURE); comfile = optarg; break; case 'n': if(sscanf(optarg,"%d", &shift)!=1) { fprintf(stderr, "invalid parameter for option -n\n"); usage(EXIT_FAILURE); } break; case 'N': encode_null=1; break; case 'q': be_quiet = 1; break; case 'v': version(); exit(0); break; case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } // check if(in_file==NULL || out_file == NULL) usage(EXIT_FAILURE); if(shift == 0) fprintf(stderr, "no sync requested - exit"); memset (nulls, 0, sizeof(nulls)); // open file if(NULL == (avifile1 = AVI_open_input_file(in_file,1))) { AVI_print_error("AVI open"); exit(1); } if(strcmp(in_file, out_file)==0) { printf("error: output filename conflicts with input filename\n"); exit(1); } if(NULL == (avifile2 = AVI_open_output_file(out_file))) { AVI_print_error("AVI open"); exit(1); } if (be_quiet) { if (!(status_fd = fopen("/dev/null", "w"))) { fprintf(stderr, "Can't open /dev/null\n"); exit(1); } } // read video info; AVI_info(avifile1); // read video info; frames = AVI_video_frames(avifile1); 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(avifile2, width, height, fps, codec); if (comfile!=NULL) AVI_set_comment_fd(avifile2, open(comfile, O_RDONLY)); aud_tracks = AVI_audio_tracks(avifile1); for(j=0; j<aud_tracks; ++j) { 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); //set next track of output file AVI_set_audio_track(avifile2, j); AVI_set_audio(avifile2, chan, rate, bits, format, mp3rate); AVI_set_audio_vbr(avifile2, is_vbr); } //switch to requested audio_channel if(AVI_set_audio_track(avifile1, track_num)<0) { fprintf(stderr, "invalid auto track\n"); } AVI_set_audio_track(avifile2, track_num); if (encode_null) { char cmd[1024]; 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); if (bits==0) bits=16; if (mp3rate%2) mp3rate++; fprintf(status_fd, "Creating silent mp3 frame with current parameter\n"); memset (cmd, 0, sizeof(cmd)); tc_snprintf(cmd, sizeof(cmd), "transcode -i /dev/zero -o %s -x raw,raw" " -n 0x1 -g 16x16 -y raw,raw -c 0-5 -e %ld,%d,%d -b %ld -q0", tmp0, rate,bits,chan, mp3rate); printf(cmd); system(cmd); if(NULL == (avifile3 = AVI_open_input_file(tmp0,1))) { AVI_print_error("AVI open"); exit(1); } nullbytes = AVI_audio_size(avifile3, 3); /* just read a few frames */ if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } memset (nulls, 0, sizeof(nulls)); if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } memset (nulls, 0, sizeof(nulls)); if(AVI_read_audio(avifile3, nulls, nullbytes) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } /* printf("\nBytes (%ld): \n", nullbytes); { int asd=0; for (asd=0; asd<nullbytes; asd++){ printf("%x ",(unsigned char)nulls[asd]); } printf("\n"); } */ } vid_ms = 0.0; shift_ms = 0.0; for (n=0; n<AVI_MAX_TRACKS; ++n) aud_ms[n] = 0.0; // --------------------------------------------------------------------- for (n=0; n<frames; ++n) { // video unchanged bytes = AVI_read_frame(avifile1, data, &key); if(bytes < 0) { AVI_print_error("AVI read video frame"); return(-1); } if(AVI_write_frame(avifile2, data, bytes, key)<0) { AVI_print_error("AVI write video frame"); return(-1); } vid_ms = (n+1)*1000.0/fps; // Pass-through all other audio tracks. for(j=0; j<aud_tracks; ++j) { // skip track we want to modify if (j == track_num) continue; // switch to track AVI_set_audio_track(avifile1, j); AVI_set_audio_track(avifile2, j); sync_audio_video_avi2avi(vid_ms, &aud_ms[j], avifile1, avifile2); } //switch to requested audio_channel if(AVI_set_audio_track(avifile1, track_num)<0) { fprintf(stderr, "invalid auto track\n"); } AVI_set_audio_track(avifile2, track_num); shift_ms = (double)shift*1000.0/fps; one_vid_ms = 1000.0/fps; format = AVI_audio_format(avifile1); rate = AVI_audio_rate(avifile1); chan = AVI_audio_channels(avifile1); bits = AVI_audio_bits(avifile1); bits = bits==0?16:bits; mp3rate= AVI_audio_mp3rate(avifile1); if(shift>0) { // for n < shift, shift audio frames are discarded if(!preload) { if (tc_format_ms_supported(format)) { for(i=0;i<shift;++i) { //fprintf (stderr, "shift (%d) i (%d) n (%d) a (%d)\n", shift, i, n, aud_chunks); while (aud_ms[track_num] < vid_ms + one_vid_ms*(double)i) { aud_bitrate = (format==0x1||format==0x2000)?1:0; aud_chunks++; if( (bytes = AVI_read_audio_chunk(avifile1, data)) <= 0) { aud_ms[track_num] = vid_ms + one_vid_ms*i; if (bytes == 0) continue; AVI_print_error("AVI 2 audio read frame"); break; } if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) { // if this is the last frame of the file, slurp in audio chunks if (n == frames-1) continue; aud_ms[track_num] = vid_ms + one_vid_ms*i; } else aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0): (format==0x2000?(double)(mp3rate):aud_bitrate)); } } } else { // fallback bytes=0; for(i=0;i<shift;++i) { do { if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } } while (AVI_can_read_audio(avifile1)); } } preload=1; } // copy rest of the track if(n<frames-shift) { if (tc_format_ms_supported(format)) { while (aud_ms[track_num] < vid_ms + shift_ms) { aud_chunks++; aud_bitrate = (format==0x1||format==0x2000)?1:0; if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) { aud_ms[track_num] = vid_ms + shift_ms; AVI_print_error("AVI 3 audio read frame"); break; } if(AVI_write_audio(avifile2, data, bytes) < 0) { AVI_print_error("AVI 3 write audio frame"); return(-1); } fprintf(status_fd, "V [%05d][%08.2f] | A [%05d][%08.2f] [%05ld]\r", n, vid_ms, aud_chunks, aud_ms[track_num], bytes); if (bytes == 0) { aud_ms[track_num] = vid_ms + shift_ms; continue; } if(n>=frames-2*shift) { // save audio frame for later ptr = buffer_register(n); if(ptr==NULL) { fprintf(stderr,"buffer allocation failed\n"); break; } ac_memcpy(ptr->data, data, bytes); ptr->size = bytes; ptr->status = BUFFER_READY; } if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) { if (n == frames-1) continue; aud_ms[track_num] = vid_ms + shift_ms; } else aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0): (format==0x2000?(double)(mp3rate):aud_bitrate)); } } else { // fallback bytes = AVI_audio_size(avifile1, n+shift-1); do { if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } if(AVI_write_audio(avifile2, data, bytes) < 0) { AVI_print_error("AVI write audio frame"); return(-1); } fprintf(status_fd, "V [%05d] | A [%05d] [%05ld]\r", n, n+shift, bytes); if(n>=frames-2*shift) { // save audio frame for later ptr = buffer_register(n); if(ptr==NULL) { fprintf(stderr,"buffer allocation failed\n"); break; } ac_memcpy(ptr->data, data, bytes); ptr->size = bytes; ptr->status = BUFFER_READY; } } while (AVI_can_read_audio(avifile1)); } } // padding at the end if(n>=frames-shift) { if (!ptrlen) { ptr = buffer_retrieve(); ac_memcpy (ptrdata, ptr->data, ptr->size); ptrlen = ptr->size; } if (tc_format_ms_supported(format)) { while (aud_ms[track_num] < vid_ms + shift_ms) { aud_bitrate = (format==0x1||format==0x2000)?1:0; // mute this -- check if can mute (valid A header)! if (tc_probe_audio_header(ptrdata, ptrlen) > 0) tc_format_mute(ptrdata, ptrlen, format); if(AVI_write_audio(avifile2, ptrdata, ptrlen) < 0) { AVI_print_error("AVI write audio frame"); return(-1); } fprintf(status_fd, " V [%05d][%08.2f] | A [%05d][%08.2f] [%05ld]\r", n, vid_ms, n+shift, aud_ms[track_num], bytes); if ( !aud_bitrate && tc_get_audio_header(ptrdata, ptrlen, format, NULL, NULL, &aud_bitrate)<0) { //if (n == frames-1) continue; aud_ms[track_num] = vid_ms + shift_ms; } else aud_ms[track_num] += (ptrlen*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0): (format==0x2000?(double)(mp3rate):aud_bitrate)); } } else { // fallback // get next audio frame ptr = buffer_retrieve(); while (1) { printf("ptr->id (%d) ptr->size (%d)\n", ptr->id, ptr->size); if(ptr==NULL) { fprintf(stderr,"no buffer found\n"); break; } if (encode_null) { if(AVI_write_audio(avifile2, nulls, nullbytes)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } else { // simple keep old frames to force exact time delay if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } fprintf(status_fd, "V [%05d] | padding\r", n); if (ptr->next && ptr->next->id == ptr->id) { buffer_remove(ptr); ptr = buffer_retrieve(); continue; } buffer_remove(ptr); break; } // 1 } } // ************************************* // negative shift (pad audio at start) // ************************************* } else { if (tc_format_ms_supported(format)) { /* fprintf(status_fd, "n(%d) -shift(%d) shift_ms (%.2lf) vid_ms(%.2lf) aud_ms[%d](%.2lf) v-s(%.2lf)\n", n, -shift, shift_ms, vid_ms, track_num, aud_ms[track_num], vid_ms + shift_ms); */ // shift<0 -> shift_ms<0 ! while (aud_ms[track_num] < vid_ms) { /* fprintf(stderr, " 1 (%02d) %s frame_read len=%4ld (A/V) (%8.2f/%8.2f)\n", n, format==0x55?"MP3":"AC3", bytes, aud_ms[track_num], vid_ms); */ aud_bitrate = (format==0x1||format==0x2000)?1:0; if( (bytes = AVI_read_audio_chunk(avifile1, data)) < 0) { AVI_print_error("AVI 2 audio read frame"); aud_ms[track_num] = vid_ms; break; //return(-1); } // save audio frame for later ptr = buffer_register(n); if(ptr==NULL) { fprintf(stderr,"buffer allocation failed\n"); break; } ac_memcpy(ptr->data, data, bytes); ptr->size = bytes; ptr->status = BUFFER_READY; if(n<-shift) { // mute this -- check if can mute! if (tc_probe_audio_header(data, bytes) > 0) tc_format_mute(data, bytes, format); // simple keep old frames to force exact time delay if(AVI_write_audio(avifile2, data, bytes)<0) { AVI_print_error("AVI write audio frame"); return(-1); } fprintf(status_fd, "V [%05d] | padding\r", n); } else { if (n==-shift) fprintf(status_fd, "\n"); // get next audio frame ptr = buffer_retrieve(); if(ptr==NULL) { fprintf(stderr,"no buffer found\n"); break; } if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) { AVI_print_error("AVI write audio frame"); return(-1); } bytes = ptr->size; ac_memcpy (data, ptr->data, bytes); fprintf(status_fd, "V [%05d] | A [%05d]\r", n, ptr->id); buffer_remove(ptr); } if ( !aud_bitrate && tc_get_audio_header(data, bytes, format, NULL, NULL, &aud_bitrate)<0) { if (n == frames-1) continue; aud_ms[track_num] = vid_ms; } else aud_ms[track_num] += (bytes*8.0)/(format==0x1?((double)(rate*chan*bits)/1000.0): (format==0x2000?(double)(mp3rate):aud_bitrate)); /* fprintf(stderr, " 1 (%02d) %s frame_read len=%4ld (A/V) (%8.2f/%8.2f)\n", n, format==0x55?"MP3":"AC3", bytes, aud_ms[track_num], vid_ms); */ } } else { // no supported format bytes = AVI_audio_size(avifile1, n); if(bytes > SIZE_RGB_FRAME) { fprintf(stderr, "invalid frame size\n"); return(-1); } if(AVI_read_audio(avifile1, data, bytes) < 0) { AVI_print_error("AVI audio read frame"); return(-1); } // save audio frame for later ptr = buffer_register(n); if(ptr==NULL) { fprintf(stderr,"buffer allocation failed\n"); break; } ac_memcpy(ptr->data, data, bytes); ptr->size = bytes; ptr->status = BUFFER_READY; if(n<-shift) { if (encode_null) { if(AVI_write_audio(avifile2, nulls, nullbytes)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } else { // simple keep old frames to force exact time delay if(AVI_write_audio(avifile2, data, bytes)<0) { AVI_print_error("AVI write audio frame"); return(-1); } } fprintf(status_fd, "V [%05d] | padding\r", n); } else { // get next audio frame ptr = buffer_retrieve(); if(ptr==NULL) { fprintf(stderr,"no buffer found\n"); break; } if(AVI_write_audio(avifile2, ptr->data, ptr->size)<0) { AVI_print_error("AVI write audio frame"); return(-1); } fprintf(status_fd, "V [%05d] | A [%05d]\r", n, ptr->id); buffer_remove(ptr); } } } } fprintf(status_fd, "\n"); if (be_quiet) { fclose(status_fd); } AVI_close(avifile1); AVI_close(avifile2); if (avifile3) { memset(nulls, 0, sizeof(nulls)); tc_snprintf(nulls, sizeof(nulls), "rm -f %s", tmp0); system(nulls); AVI_close(avifile3); } return(0); }