//___________________________________ uint8_t A_SaveAudioNVideo(const char *name) { uint32_t needSmart=0,fl; GenericAviSave *nw=NULL; aviInfo info; uint8_t ret=0; video_body->getVideoInfo(&info); printf("\n video process mode : %d",videoProcessMode()); if (!videoProcessMode()) { if(video_body->isMultiSeg()) needSmart=1; video_body->getFlags(frameStart,&fl); if(!(fl&AVI_KEY_FRAME)) needSmart=1; if(needSmart) printf("\n probably need smart copy mode\n"); if( !isMpeg4Compatible( info.fcc) && !isMSMpeg4Compatible(info.fcc)) { printf("\n not encodable, cancelling smart mode\n"); needSmart=0; } int value=video_body->getEnv(ENV_EDITOR_SMART); nw=NULL; if(needSmart) { if(value) { nw=new GenericAviSaveSmart(3); } else { if(GUI_Question(QT_TR_NOOP("You may need smart copy.\n Enable it ?"))) { value=4; if( ! GUI_getIntegerValue(&value, 2, 31, "_Q factor (set 4):")) return 0; nw=new GenericAviSaveSmart(value); } } } if(!nw) nw=new GenericAviSaveCopy; } else { printf("\n Process mode\n"); nw=new GenericAviSaveProcess; } ret=nw->saveAvi(name); delete nw; return ret; }
/** \fn ADM_codecIdFindByFourcc \brief get lav codec if from fourcc (used by muxer) */ CodecID ADM_codecIdFindByFourcc(const char *fcc) { uint32_t fid=fourCC::get((uint8_t *)fcc); // Special cases if (isMSMpeg4Compatible (fid) == 1) { return CODEC_ID_MSMPEG4V3; } if (isDVCompatible(fid))//"CDVC")) { return CODEC_ID_DVVIDEO; } if (isH264Compatible (fid)) { return CODEC_ID_H264; } if (isMpeg4Compatible (fid) == 1) { return CODEC_ID_MPEG4; } uint32_t nb=sizeof(ffCodec)/sizeof(ffVideoCodec); for(int i=0;i<nb;i++) { if(!strcmp(fcc,ffCodec[i].string)) return ffCodec[i].codecId; } return CODEC_ID_NONE; }
uint8_t OpenDMLHeader::computePtsDts(void) { // if it is mpeg4-sp, removed packet bitstream & reindex if(isMpeg4Compatible(_videostream.fccHandler)) OpenDMLHeader::unpackPacked( ); // Now if we have B frames, it is properly tagged // Begin by putting PTS=DTS i.e. no B-frames for(int i=0;i<_videostream.dwLength;i++) { odmlIndex *idx=&( _idx[i]); idx->pts=ADM_COMPRESSED_NO_PTS; idx->dts=frameToUs(i); } _idx[0].pts=0; return 1; }
int A_SavePackedVop(const char *name) { aviInfo info; GenericAviSave *nw; int ret; video_body->getVideoInfo(&info); if( !isMpeg4Compatible( info.fcc)) { GUI_Error_HIG(QT_TR_NOOP("This cannot have packed VOP"),QT_TR_NOOP( "It is not MPEG-4 video. File will not be saved.")); return 0; } // nw=new GenericAviSaveCopyPack(); ret=nw->saveAvi(name); delete nw; return ret; }
uint8_t lavMuxer::open(const char *filename,uint32_t inbitrate, ADM_MUXER_TYPE type, aviInfo *info,uint32_t videoExtraDataSize, uint8_t *videoExtraData, WAVHeader *audioheader,uint32_t audioextraSize,uint8_t *audioextraData) { AVCodecContext *c; _type=type; _fps1000=info->fps1000; switch(_type) { case MUXER_TS: fmt=guess_format("mpegts", NULL, NULL); break; case MUXER_DVD: fmt = guess_format("dvd", NULL, NULL); break; case MUXER_VCD: fmt = guess_format("vcd", NULL, NULL); break; case MUXER_SVCD: fmt = guess_format("svcd", NULL, NULL); break; case MUXER_MP4: fmt = guess_format("mp4", NULL, NULL); break; case MUXER_PSP: fmt = guess_format("psp", NULL, NULL); break; default: fmt=NULL; } if (!fmt) { printf("Lav:Cannot guess format\n"); return 0; } oc = av_alloc_format_context(); if (!oc) { printf("Lav:Cannot allocate context\n"); return 0; } oc->oformat = fmt; snprintf(oc->filename,1000,"file://%s",filename); // Video //________ video_st = av_new_stream(oc, 0); if (!video_st) { printf("Lav: new stream failed\n"); return 0; } c = video_st->codec; switch(_type) { case MUXER_MP4: if(isMpeg4Compatible(info->fcc)) { c->codec_id = CODEC_ID_MPEG4; c->has_b_frames=1; // in doubt... }else { if(isH264Compatible(info->fcc)) { c->has_b_frames=1; // in doubt... c->codec_id = CODEC_ID_H264; c->codec=new AVCodec; memset(c->codec,0,sizeof(AVCodec)); c->codec->name=ADM_strdup("H264"); } else { c->codec_id = CODEC_ID_MPEG4; // Default value printf("Ooops, cant mux that...\n"); printf("Ooops, cant mux that...\n"); printf("Ooops, cant mux that...\n"); //return 0; } } if(videoExtraDataSize) { c->extradata=videoExtraData; c->extradata_size= videoExtraDataSize; } c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; break; case MUXER_TS: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; break; case MUXER_DVD: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; break; case MUXER_VCD: c->codec_id = CODEC_ID_MPEG1VIDEO; c->rc_buffer_size=8*1024*40; c->rc_max_rate=1152*1000; c->rc_min_rate=1152*1000; c->bit_rate=1152*1000; break; case MUXER_SVCD: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*112; c->rc_max_rate=2500*1000; c->rc_min_rate=0*1000; if(!inbitrate) c->bit_rate=2040*1000; else c->bit_rate=inbitrate; break; default: ADM_assert(0); } c->codec_type = CODEC_TYPE_VIDEO; c->flags=CODEC_FLAG_QSCALE; c->width = info->width; c->height = info->height; switch(_fps1000) { case 25000: c->time_base= (AVRational){1001,25025}; //c->frame_rate = 25025; //c->frame_rate_base = 1001; break; case 23976: /* c->frame_rate = 24000; c->frame_rate_base = 1001; break; */ if(_type==MUXER_MP4) { c->time_base= (AVRational){1001,24000}; break; } case 29970: c->time_base= (AVRational){1001,30000}; //c->frame_rate = 30000; //c->frame_rate_base = 1001; break; default: if(_type==MUXER_MP4) { c->time_base= (AVRational){1000,_fps1000}; break; } else { GUI_Error_HIG(_("Incompatible frame rate"), NULL); return 0; } } c->gop_size=15; c->max_b_frames=2; c->has_b_frames=1; // Audio //________ if(audioheader) { audio_st = av_new_stream(oc, 1); if (!audio_st) { printf("Lav: new stream failed\n"); return 0; } c = audio_st->codec; c->frame_size=1024; //For AAC mainly, sample per frame switch(audioheader->encoding) { case WAV_AC3: c->codec_id = CODEC_ID_AC3;break; case WAV_MP2: c->codec_id = CODEC_ID_MP2;break; case WAV_MP3: #warning FIXME : Probe deeper c->frame_size=1152; c->codec_id = CODEC_ID_MP3; break; case WAV_PCM: // One chunk is 10 ms (1/100 of fq) c->frame_size=4; c->codec_id = CODEC_ID_PCM_S16LE;break; case WAV_AAC: c->extradata=audioextraData; c->extradata_size= audioextraSize; c->codec_id = CODEC_ID_AAC; break; default: printf("Cant mux that ! audio\n"); printf("Cant mux that ! audio\n"); c->codec_id = CODEC_ID_MP2; return 0; break; } c->codec_type = CODEC_TYPE_AUDIO; c->bit_rate = audioheader->byterate*8; c->rc_buffer_size=(c->bit_rate/(2*8)); // 500 ms worth _audioFq=c->sample_rate = audioheader->frequency; c->channels = audioheader->channels; _audioByterate=audioheader->byterate; } // /audio //---------------------- switch(_type) { case MUXER_MP4: oc->mux_rate=10080*1000; // Needed ? break; case MUXER_TS: oc->mux_rate=10080*1000; break; case MUXER_DVD: oc->packet_size=2048; oc->mux_rate=10080*1000; break; case MUXER_VCD: oc->packet_size=2324; oc->mux_rate=2352 * 75 * 8; break; case MUXER_SVCD: oc->packet_size=2324; oc->mux_rate=2*2352 * 75 * 8; // ? break; default: ADM_assert(0); } oc->preload=AV_TIME_BASE/10; // 100 ms preloading oc->max_delay=200*1000; // 500 ms if (av_set_parameters(oc, NULL) < 0) { printf("Lav: set param failed \n"); return 0; } if (url_fopen(&(oc->pb), filename, URL_WRONLY) < 0) { printf("Lav: Failed to open file :%s\n",filename); return 0; } av_write_header(oc); dump_format(oc, 0, filename, 1); printf("lavformat mpeg muxer initialized\n"); _running=1; one=(1000*1000*1000)/_fps1000; _curDTS=one; return 1; }
decoders *getDecoder(uint32_t fcc,uint32_t w, uint32_t h,uint32_t extraLen,uint8_t *extraData) { if(isMSMpeg4Compatible(fcc)==1) { // For div3, no problem we take ffmpeg return(decoders *)( new decoderFFDiv3(w,h)); } #ifdef USE_FFMPEG if(fourCC::check(fcc,(uint8_t *)"dvsd") || fourCC::check(fcc,(uint8_t *)"DVDS") || fourCC::check(fcc,(uint8_t *)"CDVC") ) { return(decoders *)( new decoderFFDV(w,h,extraLen,extraData)); } #endif #ifdef USE_FFMPEG if(fourCC::check(fcc,(uint8_t *)"MP42")) { return(decoders *)( new decoderFFMP42(w,h)); } #endif #ifdef USE_FFMPEG if(fourCC::check(fcc,(uint8_t *)"H263")) { return(decoders *)( new decoderFFH263(w,h)); } if(fourCC::check(fcc,(uint8_t *)"HFYU")) { return(decoders *)( new decoderFFhuff(w,h,extraLen,extraData)); } if(fourCC::check(fcc,(uint8_t *)"SVQ3")) { return(decoders *)( new decoderFFSVQ3(w,h,extraLen,extraData)); } if(fourCC::check(fcc,(uint8_t *)"WMV2")) { return(decoders *)( new decoderFFWMV2(w,h,extraLen,extraData)); } if(fourCC::check(fcc,(uint8_t *)"FFV1")) { return(decoders *)( new decoderFFV1(w,h)); } #endif /* Could be either divx5 packed crap or xvid or ffmpeg For now we return FFmpeg and later will switch to divx5 if available (ugly hack for ugly hack....) */ if(isMpeg4Compatible(fcc)==1) { return(decoders *)( new decoderFFMpeg4(w,h)); // return(decoders *)( new decoderXvid(w,h)); // return(decoders *)( new decoderDIVX(w,h)); } if(fourCC::check(fcc,(uint8_t *)"MJPG") || fourCC::check(fcc,(uint8_t *)"mjpa")) { #if 0 //#ifdef USE_MJPEG printf("\n using mjpeg codec\n"); return(decoders *)( new decoderMjpeg(w,h)); #else printf("\n using FF mjpeg codec\n"); return(decoders *)( new decoderFFMJPEG(w,h)); #endif } if(fourCC::check(fcc,(uint8_t *)"YV12")) { printf("\n using null codec\n"); return(decoders *)( new decoderNull(w,h)); } if(fourCC::check(fcc,(uint8_t *)"UYVY")) { printf("\n using uyvy codec\n"); return(decoders *)( new decoderUYVY(w,h)); } if(fourCC::check(fcc,(uint8_t *)"YUY2")) { printf("\n using YUY2 codec\n"); return(decoders *)( new decoderYUY2(w,h)); } if((fcc==0) || fourCC::check(fcc,(uint8_t *)"RGB ")) { // RGB 16 Codecs printf("\n using RGB codec\n"); return(decoders *)( new decoderRGB16(w,h)); } #ifdef USE_THEORA if(fourCC::check(fcc,(uint8_t *)"VP31")) { printf("\n using Theora codec\n"); return(decoders *)( new decoderTheora(w,h)); } #else if(fourCC::check(fcc,(uint8_t *)"VP31")) { printf("\n using VP3 codec\n"); return(decoders *)( new decoderVP3(w,h)); } #endif if(isMpeg12Compatible(fcc)) { printf("\n using Mpeg1/2 codec (libmpeg2)\n"); return(decoders *)( new decoderMpeg(w,h,extraLen,extraData)); // return(decoders *)( new decoderFFMpeg12(w,h,extraLen,extraData)); } // default : null decoder printf("\n using invalid codec for \n"); fourCC::print(fcc); return(decoders *)( new decoders(w,h)); }
uint8_t GenericAviSaveSmart::initEncoder (uint32_t qz) { aviInfo info; video_body->getVideoInfo (&info); assert (0 == encoderReady); encoderReady = 1; uint8_t ret=0; FFcodecSetting myConfig={ ME_EPZS,// ME 0, // GMC 0,// _4MV; 0,// _QPEL; 0,// _TREILLIS_QUANT 2,// qmin; 31,// qmax; 3,// max_qdiff; 0,// max_b_frames; 0, // mpeg_quant; 1,// -2, // luma_elim_threshold; 1,// -5, // chroma_elim_threshold; 0.05,// lumi_masking; 1, 0.01,// dark_masking; 1, 0.5,// qcompress; /* amount of qscale change between easy & hard scenes (0.0-1.0)*/ 0.5,// qblur; /* amount of qscale smoothing over time (0.0-1.0) */ } ; if( isMpeg4Compatible(info.fcc) ) { /* #ifdef USE_DIVX _encoder = new divxEncoderCQ (info.width, info.height); #else */ // uint8_t setConfig(FFcodecSetting *set); ffmpegEncoderCQ *tmp; tmp = new ffmpegEncoderCQ (info.width, info.height,FF_MPEG4); tmp->setConfig(&myConfig); printf("\n init qz %ld\n",qz); ret= tmp->init (qz,25000); _encoder=tmp; /* #endif */ #warning 25 fps hardcoded } else { #ifdef USE_FFMPEG if(isMSMpeg4Compatible(info.fcc) ) { ffmpegEncoderCQ *tmp; tmp = new ffmpegEncoderCQ (info.width, info.height,FF_MSMP4V3); tmp->setConfig(&myConfig); ret= tmp->init (qz,25000); _encoder=tmp; } else { assert(0); } } #else assert(0); }
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming=NULL; AVDMGenericAudioStream *audio=NULL; uint8_t audioBuffer[48000]; uint8_t *videoBuffer=NULL; uint32_t alen;//,flags; uint32_t size; uint8_t ret=0; uint32_t sample_got=0,sample; uint32_t extraDataSize=0; uint8_t *extraData=NULL; lavMuxer *muxer=NULL; aviInfo info; uint32_t width,height; DIA_encoding *encoding_gui=NULL; Encoder *_encode=NULL; char *TwoPassLogFile=NULL; uint32_t total=0; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData=NULL; uint8_t *dummy,err; WAVHeader *audioinfo=NULL; int prefill=0; uint32_t displayFrame=0; ADMBitstream bitstream; uint32_t frameWrite=0; ADM_MUXER_TYPE muxerType=MUXER_MP4; uint8_t dualPass=0; uint8_t r=0; uint32_t skipping=1; if(type==ADM_PSP) muxerType=MUXER_PSP; else muxerType=MUXER_MP4; // Setup video if(videoProcessMode()) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); }else { _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart); } videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3]; // Set global header encoding, needed for H264 _encode = getVideoEncoder (_incoming->getInfo()->width, _incoming->getInfo()->height,1); total= _incoming->getInfo()->nb_frames; encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000); if (!_encode) { GUI_Error_HIG (_("Cannot initialize the video stream"), NULL); goto stopit; } // init compressor encoding_gui->setContainer("MP4"); encoding_gui->setAudioCodec("None"); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,total); if (!_encode->configure (_incoming)) { GUI_Error_HIG (_("Filter init failed"), NULL); goto stopit; }; dualPass=_encode->isDualPass(); if(dualPass) { if(!prepareDualPass(videoBuffer,TwoPassLogFile,encoding_gui,_encode,total)) goto stopit; }else { encoding_gui->setPhasis ("Encoding"); } info.width=_incoming->getInfo()->width; info.height=_incoming->getInfo()->height; info.nb_frames=_incoming->getInfo()->nb_frames; info.fps1000=_incoming->getInfo()->fps1000; info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy); if(videoExtraDataSize) { printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize); videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,dummy,videoExtraDataSize); } // _________________Setup video (cont) _______________ // ___________ Read 1st frame _________________ ADM_assert(_encode); bitstream.data=videoBuffer; preFilling: bitstream.cleanup(0); if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (_("Error while encoding"), NULL); goto stopit; } if(!bitstream.len) { prefill++; goto preFilling; } if(!bitstream.flags & AVI_KEY_FRAME) { GUI_Error_HIG (_("KeyFrame error"),_( "The beginning frame is not a key frame.\nPlease move the A marker.")); goto stopit; } //len=bitstream.len; // If needed get VOL header if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len) { // And put them as extradata for esds atom uint32_t voslen=0; if(extractVolHeader(videoBuffer,bitstream.len,&voslen)) { if(voslen) { videoExtraDataSize=voslen; videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,videoBuffer,videoExtraDataSize); } } else printf("Oops should be settings data for esds\n"); } // ____________Setup audio__________________ if(currentaudiostream) { audio=mpt_getAudioStream(); if(!audio) { GUI_Error_HIG (_("Cannot initialize the audio stream"), NULL); goto stopit; } } if(audio) { audioinfo=audio->getInfo(); audio->extraData(&extraDataSize,&extraData); if(audioProcessMode()) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); else encoding_gui->setAudioCodec("Copy"); }else { encoding_gui->setAudioCodec("None"); } // ____________Setup Muxer _____________________ muxer= new lavMuxer; if(!muxer->open( name, 2000000, // Muxrate MUXER_MP4, &info,videoExtraDataSize,videoExtraData, audioinfo,extraDataSize,extraData)) goto stopit; //_____________ Loop _____________________ encoding_gui->setContainer("MP4"); if(audio) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); // if(bitstream.len) { muxer->writeVideoPacket( &bitstream); frameWrite++; } for(int frame=1;frame<total;frame++) { while(muxer->needAudio()) { if(!audio->getPacket(audioBuffer,&alen,&sample)) break; if(alen) { muxer->writeAudioPacket(alen,audioBuffer,sample_got); encoding_gui->feedAudioFrame(alen); sample_got+=sample; } } ADM_assert(_encode); bitstream.cleanup(frameWrite); if(!prefill || frame+prefill<total) { r=_encode->encode ( prefill+frame, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if(!r) { printf("MP4:Frame %u error\n",frame); GUI_Error_HIG (_("Error while encoding"), NULL); goto stopit; } if(!bitstream.len && skipping) { printf("Frame skipped (xvid ?)\n"); continue; } skipping=0; // printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame); frameWrite++; muxer->writeVideoPacket( &bitstream); encoding_gui->setFrame(frame,total); encoding_gui->feedFrame(bitstream.len); if(!encoding_gui->isAlive()) { if(GUI_YesNo(_("Stop Request"), _("Do you want to abort encoding ?"))) goto stopit; } } ret=1; stopit: if(muxer) muxer->close(); if(encoding_gui) delete encoding_gui; if(TwoPassLogFile) delete [] TwoPassLogFile; if(videoBuffer) delete [] videoBuffer; if(muxer) delete muxer; if(_encode) delete _encode; if(videoExtraData) delete [] videoExtraData; // Cleanup deleteAudioFilter (audio); return ret; }
uint8_t lavMuxer::open(const char *filename,uint32_t inbitrate, ADM_MUXER_TYPE type, aviInfo *info, uint32_t videoExtraDataSize, uint8_t *videoExtraData, WAVHeader *audioheader, uint32_t audioextraSize,uint8_t *audioextraData) { AVCodecContext *c; _type=type; _fps1000=info->fps1000; switch(_type) { case MUXER_TS: fmt=guess_format("mpegts", NULL, NULL); break; case MUXER_DVD: fmt = guess_format("dvd", NULL, NULL); break; case MUXER_VCD: fmt = guess_format("vcd", NULL, NULL); break; case MUXER_SVCD: fmt = guess_format("svcd", NULL, NULL); break; case MUXER_MP4: fmt = guess_format("mp4", NULL, NULL); break; case MUXER_PSP: fmt = guess_format("psp", NULL, NULL); break; case MUXER_FLV: fmt = guess_format("flv", NULL, NULL); break; case MUXER_MATROSKA: fmt = guess_format("matroska", NULL, NULL); break; default: fmt=NULL; } if (!fmt) { printf("Lav:Cannot guess format\n"); ADM_assert(0); return 0; } oc = av_alloc_format_context(); if (!oc) { printf("Lav:Cannot allocate context\n"); return 0; } oc->oformat = fmt; snprintf(oc->filename,1000,"file://%s",filename); // Video //________ video_st = av_new_stream(oc, 0); if (!video_st) { printf("Lav: new stream failed\n"); return 0; } c = video_st->codec; switch(_type) { case MUXER_FLV: c->codec=new AVCodec; memset(c->codec,0,sizeof(AVCodec)); if(fourCC::check(info->fcc,(uint8_t *)"FLV1")) { c->codec_id=CODEC_ID_FLV1; c->codec->name=ADM_strdup("FLV1"); }else { if(fourCC::check(info->fcc,(uint8_t *)"VP6F")) { c->codec_id=CODEC_ID_VP6F; c->codec->name=ADM_strdup("VP6F"); } else ADM_assert(0); } break; case MUXER_MATROSKA: strcpy(oc->title,"Avidemux"); strcpy(oc->author,"Avidemux"); c->sample_aspect_ratio.num=1; c->sample_aspect_ratio.den=1; if(isMpeg4Compatible(info->fcc)) { c->codec_id = CODEC_ID_MPEG4; c->has_b_frames=1; // in doubt... }else { if(isH264Compatible(info->fcc)) { c->has_b_frames=1; // in doubt... c->codec_id = CODEC_ID_H264; c->codec=new AVCodec; memset(c->codec,0,sizeof(AVCodec)); c->codec->name=ADM_strdup("H264"); } else { if(!ADM_4cc_to_lavcodec((const char *)&(info->fcc),&(c->codec_id))) { printf("[lavFormat] Cannot map this\n"); return 0; } } } if(videoExtraDataSize) { c->extradata=videoExtraData; c->extradata_size= videoExtraDataSize; } break; case MUXER_MP4: case MUXER_PSP: { // probably a memeleak here char *foo=ADM_strdup(filename); strcpy(oc->title,ADM_GetFileName(foo)); strcpy(oc->author,"Avidemux"); c->sample_aspect_ratio.num=1; c->sample_aspect_ratio.den=1; if(isMpeg4Compatible(info->fcc)) { c->codec_id = CODEC_ID_MPEG4; c->has_b_frames=1; // in doubt... }else { if(isH264Compatible(info->fcc)) { c->has_b_frames=1; // in doubt... c->codec_id = CODEC_ID_H264; c->codec=new AVCodec; memset(c->codec,0,sizeof(AVCodec)); c->codec->name=ADM_strdup("H264"); } else { if(isDVCompatible(info->fcc)) { c->codec_id = CODEC_ID_DVVIDEO; }else { if(fourCC::check(info->fcc,(uint8_t *)"H263")) { c->codec_id=CODEC_ID_H263; }else{ c->codec_id = CODEC_ID_MPEG4; // Default value printf("Ooops, cant mux that...\n"); printf("Ooops, cant mux that...\n"); printf("Ooops, cant mux that...\n"); } } } } if(videoExtraDataSize) { c->extradata=videoExtraData; c->extradata_size= videoExtraDataSize; } if(MUXER_PSP==_type) { c->rc_buffer_size=0; //8*1024*224; c->rc_max_rate=0; //768*1000; c->rc_min_rate=0; c->bit_rate=768*1000; } else { c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; } } break; case MUXER_TS: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; break; case MUXER_DVD: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; if(!inbitrate) c->bit_rate=9000*1000; else c->bit_rate=inbitrate; break; case MUXER_VCD: c->codec_id = CODEC_ID_MPEG1VIDEO; c->rc_buffer_size=8*1024*40; c->rc_max_rate=1152*1000; c->rc_min_rate=1152*1000; c->bit_rate=1152*1000; break; case MUXER_SVCD: c->codec_id = CODEC_ID_MPEG2VIDEO; c->rc_buffer_size=8*1024*112; c->rc_max_rate=2500*1000; c->rc_min_rate=0*1000; if(!inbitrate) c->bit_rate=2040*1000; else c->bit_rate=inbitrate; break; default: ADM_assert(0); } c->codec_type = CODEC_TYPE_VIDEO; c->flags=CODEC_FLAG_QSCALE; c->width = info->width; c->height = info->height; AVRational fps25=(AVRational){1001,25025}; AVRational fps24=(AVRational){1001,24000}; AVRational fps30= (AVRational){1001,30000}; AVRational fpsfree= (AVRational){1000,_fps1000}; switch(_fps1000) { case 25000: { c->time_base= fps25; break; } case 23976: if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV || _type==MUXER_MATROSKA) { c->time_base= fps24; //(AVRational){1001,24000}; break; } case 29970: c->time_base=fps30; break; default: { if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV || _type==MUXER_MATROSKA) { c->time_base=fpsfree;// (AVRational){1000,_fps1000}; break; } else { GUI_Error_HIG(QT_TR_NOOP("Incompatible frame rate"), NULL); return 0; } } break; } c->gop_size=15; c->max_b_frames=2; c->has_b_frames=1; // Audio //________ if(audioheader) { audio_st = av_new_stream(oc, 1); if (!audio_st) { printf("Lav: new stream failed\n"); return 0; } c = audio_st->codec; c->frame_size=1024; //For AAC mainly, sample per frame printf("[LavFormat] Bitrate %u\n",(audioheader->byterate*8)/1000); _audioFq=c->sample_rate = audioheader->frequency; #if 0 if(_type== MUXER_PSP && audioheader->encoding==WAV_AAC) { _audioFq=c->sample_rate = audioheader->frequency/2; //_audioFq*=2; // SBR } #endif switch(audioheader->encoding) { case WAV_AC3: c->codec_id = CODEC_ID_AC3;break; case WAV_MP2: c->codec_id = CODEC_ID_MP2;break; case WAV_MP3: #warning FIXME : Probe deeper c->frame_size=1152; c->codec_id = CODEC_ID_MP3; break; case WAV_PCM: // One chunk is 10 ms (1/100 of fq) c->frame_size=4; c->codec_id = CODEC_ID_PCM_S16LE;break; case WAV_AAC: c->extradata=audioextraData; c->extradata_size= audioextraSize; c->codec_id = CODEC_ID_AAC; break; default: if(_type==MUXER_MATROSKA) { if(ADM_WaveTag_to_lavcodec(audioheader->encoding, &(c->codec_id))) { if(audioextraData) { c->extradata=audioextraData; c->extradata_size= audioextraSize; } // Put a dummy time increment c->time_base= fps25; break; } } printf("Cant mux that ! audio\n"); printf("Cant mux that ! audio\n"); c->codec_id = CODEC_ID_MP2; return 0; break; } c->codec_type = CODEC_TYPE_AUDIO; c->bit_rate = audioheader->byterate*8; c->rc_buffer_size=(c->bit_rate/(2*8)); // 500 ms worth c->channels = audioheader->channels; _audioByterate=audioheader->byterate; } // /audio //---------------------- switch(_type) { case MUXER_FLV: case MUXER_PSP: case MUXER_MP4: case MUXER_MATROSKA: oc->mux_rate=10080*1000; // Needed ? break; case MUXER_TS: oc->mux_rate=10080*1000; break; case MUXER_DVD: oc->packet_size=2048; oc->mux_rate=10080*1000; break; case MUXER_VCD: oc->packet_size=2324; oc->mux_rate=2352 * 75 * 8; break; case MUXER_SVCD: oc->packet_size=2324; oc->mux_rate=2*2352 * 75 * 8; // ? break; default: ADM_assert(0); } oc->preload=AV_TIME_BASE/10; // 100 ms preloading oc->max_delay=200*1000; // 500 ms if (av_set_parameters(oc, NULL) < 0) { printf("Lav: set param failed \n"); return 0; } if (url_fopen(&(oc->pb), filename, URL_WRONLY) < 0) { printf("Lav: Failed to open file :%s\n",filename); return 0; } ADM_assert(av_write_header(oc)>=0); dump_format(oc, 0, filename, 1); printf("lavformat mpeg muxer initialized\n"); _running=1; one=(1000*1000*1000)/_fps1000; _curDTS=one; return 1; }
bool muxerMp4v2::open(const char *file, ADM_videoStream *s,uint32_t nbAudioTrack,ADM_audioStream **a) { audioDelay=s->getVideoDelay(); vStream=s; nbAStreams=nbAudioTrack; aStreams=a; videoBufferSize=vStream->getWidth()*vStream->getHeight()*3; videoBuffer[0]=new uint8_t[videoBufferSize]; videoBuffer[1]=new uint8_t[videoBufferSize]; scratchBuffer=new uint8_t[videoBufferSize]; in[0].bufferSize=videoBufferSize; in[0].data=videoBuffer[0]; in[1].bufferSize=videoBufferSize; in[1].data=videoBuffer[1]; targetFileName=string(file); //------Verify everything is ok : Accept Mp4 & H264 for video, AAC for audio ---- uint32_t fcc=vStream->getFCC(); if(!isH264Compatible(fcc) && !isMpeg4Compatible(fcc)) { ADM_error("[mp4v2] Only h264 and mp4 video track!\n"); return false; } for(int i=0;i<nbAStreams;i++) { int encoding=aStreams[i]->getInfo()->encoding; switch(encoding) { case WAV_MP2:case WAV_MP3:case WAV_AAC:case WAV_AC3: continue; default: GUI_Error_HIG("Audio","Audio format not supported, only AAC/MP3/AC3"); return false; } } //------Verify everything is ok : Accept Mp4 & H264 for video, AAC for audio ---- // Create file handle=MP4Create( file, ADM_MP4_OPTIONS_OPEN); if(MP4_INVALID_FILE_HANDLE==handle) { ADM_error("[mp4v2]Cannot create output file %s\n",file); return false; } MP4LogSetLevel(MP4_LOG_INFO); if (!(MP4SetTimeScale( handle, 90*1000 ))) // 90 kHz tick { ADM_error("[mp4v2]Cannot set timescale to us\n"); return false; } if(false==initVideo()) { ADM_error("Cannot init video\n"); return false; } if(false==initAudio()) { ADM_error("Cannot init audio\n"); return false; } return true; er: return false; }
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming=NULL; AVDMGenericAudioStream *audio=NULL; uint8_t audioBuffer[48000]; uint8_t *videoBuffer=NULL; uint32_t alen;//,flags; uint32_t size; uint8_t ret=0; uint32_t sample_got=0,sample; uint32_t extraDataSize=0; uint8_t *extraData=NULL; lavMuxer *muxer=NULL; aviInfo info; uint32_t width,height; DIA_encoding *encoding_gui=NULL; Encoder *_encode=NULL; char *TwoPassLogFile=NULL; uint32_t total=0; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData=NULL; uint8_t *dummy,err; WAVHeader *audioinfo=NULL; int prefill=0; uint32_t displayFrame=0; ADMBitstream bitstream(0); uint32_t frameWrite=0; ADM_MUXER_TYPE muxerType=MUXER_MP4; uint8_t dualPass=0; uint8_t r=0; uint32_t skipping=1; pthread_t audioThread; audioQueueMT context; PacketQueue *pq;//("MP4 audioQ",50,2*1024*1024); uint32_t totalAudioSize=0; uint32_t sent=0; const char *containerTitle; switch(type) { case ADM_PSP:muxerType=MUXER_PSP;containerTitle="PSP";break; case ADM_MP4:muxerType=MUXER_MP4;containerTitle="MP4";break; case ADM_MATROSKA:muxerType=MUXER_MATROSKA;containerTitle="MKV";break; default: ADM_assert(0); } // Setup video if(videoProcessMode()) { _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); }else { _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart); } videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3]; // Set global header encoding, needed for H264 _encode = getVideoEncoder (_incoming->getInfo()->width, _incoming->getInfo()->height,1); total= _incoming->getInfo()->nb_frames; encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000); bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3; if (!_encode) { GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the video stream"), NULL); goto stopit; } // init compressor encoding_gui->setContainer(containerTitle); encoding_gui->setAudioCodec("None"); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,total); if (!_encode->configure (_incoming)) { GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); goto stopit; }; dualPass=_encode->isDualPass(); if(dualPass) { if(!prepareDualPass(bitstream.bufferSize,videoBuffer,TwoPassLogFile,encoding_gui,_encode,total)) goto stopit; }else { encoding_gui->setPhasis ("Encoding"); } info.width=_incoming->getInfo()->width; info.height=_incoming->getInfo()->height; info.nb_frames=_incoming->getInfo()->nb_frames; info.fps1000=_incoming->getInfo()->fps1000; info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy); if(videoExtraDataSize) { printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize); videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,dummy,videoExtraDataSize); } // _________________Setup video (cont) _______________ // ___________ Read 1st frame _________________ ADM_assert(_encode); bitstream.data=videoBuffer; preFilling: bitstream.cleanup(0); if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } sent++; if(!bitstream.len) { prefill++; goto preFilling; } printf("Pass 2 prefill : %u\n",prefill); if(!bitstream.flags & AVI_KEY_FRAME) { GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"),QT_TR_NOOP( "The beginning frame is not a key frame.\nPlease move the A marker.")); goto stopit; } //len=bitstream.len; // If needed get VOL header if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len) { // And put them as extradata for esds atom uint32_t voslen=0; if(extractVolHeader(videoBuffer,bitstream.len,&voslen)) { if(voslen) { videoExtraDataSize=voslen; videoExtraData=new uint8_t[videoExtraDataSize]; memcpy(videoExtraData,videoBuffer,videoExtraDataSize); } } else printf("Oops should be settings data for esds\n"); } // ____________Setup audio__________________ if(currentaudiostream) { audio=mpt_getAudioStream(); if(!audio) { GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the audio stream"), NULL); goto stopit; } } if(audio) { audioinfo=audio->getInfo(); audio->extraData(&extraDataSize,&extraData); if(audioProcessMode()) encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); else encoding_gui->setAudioCodec("Copy"); }else { encoding_gui->setAudioCodec("None"); } // ____________Setup Muxer _____________________ muxer= new lavMuxer; if(!muxer->open( name, 2000000, // Muxrate muxerType, &info,videoExtraDataSize,videoExtraData, audioinfo,extraDataSize,extraData)) goto stopit; //_____________ Loop _____________________ encoding_gui->setContainer(containerTitle); if(!videoProcessMode()) encoding_gui->setCodec("Copy"); else encoding_gui->setCodec(_encode->getDisplayName()); // UI_purge(); if(bitstream.len) { muxer->writeVideoPacket( &bitstream); frameWrite++; } //_____________ Start Audio thread _____________________ if(audio) { pq=new PacketQueue("MP4 audioQ",5000,2*1024*1024); memset(&context,0,sizeof(context)); context.audioEncoder=audio; context.audioTargetSample=0xFFFF0000; ; //FIXME context.packetQueue=pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); ADM_usleep(4000); } //_____________GO !___________________ for(int frame=1;frame<total;frame++) { while(muxer->needAudio()) { if(pq->Pop(audioBuffer,&alen,&sample)) { if(alen) { muxer->writeAudioPacket(alen,audioBuffer,sample_got); totalAudioSize+=alen; encoding_gui->setAudioSize(totalAudioSize); sample_got+=sample; } }else break; } ADM_assert(_encode); bitstream.cleanup(frameWrite); if(!prefill || frame+prefill<total) { r=_encode->encode ( prefill+frame, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if(!r && frame<total-2) { printf("MP4:Frame %u error\n",frame); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } if(!bitstream.len && skipping) { printf("Frame skipped (xvid ?)\n"); continue; } sent++; skipping=0; // printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame); frameWrite++; muxer->writeVideoPacket( &bitstream); encoding_gui->setFrame(frame,bitstream.len,bitstream.out_quantizer,total); if(!encoding_gui->isAlive()) { goto stopit; } } ret=1; stopit: printf("2nd pass, sent %u frames\n",sent); // Flush slave Q if(audio) { context.audioAbort=1; pq->Abort(); // Wait for audio slave to be over while(!context.audioDone) { printf("Waiting Audio thread\n"); ADM_usleep(500000); } delete pq; } // if(muxer) muxer->close(); if(encoding_gui) delete encoding_gui; if(TwoPassLogFile) delete [] TwoPassLogFile; if(videoBuffer) delete [] videoBuffer; if(muxer) delete muxer; if(_encode) delete _encode; if(videoExtraData) delete [] videoExtraData; // Cleanup deleteAudioFilter (audio); return ret; }
/** \fn initVideo \brief setup video part of muxer */ bool muxerFFmpeg::initVideo(ADM_videoStream *stream) { audioDelay=stream->getVideoDelay(); video_st = avformat_new_stream(oc, NULL); if (!video_st) { printf("[FF] new stream failed\n"); return false; } AVCodecContext *c; c = video_st->codec; c->sample_aspect_ratio.num=1; c->sample_aspect_ratio.den=1; video_st->sample_aspect_ratio=c->sample_aspect_ratio; uint32_t videoExtraDataSize=0; uint8_t *videoExtraData; stream->getExtraData(&videoExtraDataSize,&videoExtraData); printf("[FF] Using %d bytes for video extradata\n",(int)videoExtraDataSize); ffmpuxerSetExtradata(c,videoExtraDataSize,videoExtraData); c->rc_buffer_size=8*1024*224; c->rc_max_rate=9500*1000; c->rc_min_rate=0; c->bit_rate=9000*1000; c->codec_type = AVMEDIA_TYPE_VIDEO; c->flags=CODEC_FLAG_QSCALE; c->width = stream->getWidth(); c->height =stream->getHeight(); uint32_t fcc=stream->getFCC(); if(isMpeg4Compatible(fcc)) { c->codec_id = CODEC_ID_MPEG4; if(stream->providePts()==true) { c->has_b_frames=1; // in doubt... c->max_b_frames=2; }else { ADM_warning("Incoming stream does not provide PTS \n"); c->has_b_frames=0; // No PTS=cannot handle CTS... c->max_b_frames=0; } }else { if(isH264Compatible(fcc) || isH265Compatible(fcc)) { if(stream->providePts()==true) { c->has_b_frames=1; // in doubt... c->max_b_frames=2; }else { printf("[MP4] Source video has no PTS information, assuming no b frames\n"); c->has_b_frames=0; // No PTS=cannot handle CTS... c->max_b_frames=0; } if(isH265Compatible(fcc)) { c->codec_id = AV_CODEC_ID_HEVC; setAvCodec(c,AV_CODEC_ID_HEVC); } else { c->codec_id = CODEC_ID_H264; setAvCodec(c,CODEC_ID_H264); } } else { if(isDVCompatible(fcc)) { c->codec_id = CODEC_ID_DVVIDEO; }else { if(fourCC::check(fcc,(uint8_t *)"H263")) { c->codec_id=CODEC_ID_H263; }else if(isVP6Compatible(stream->getFCC())) { c->codec_id=CODEC_ID_VP6F; setAvCodec(c,CODEC_ID_VP6F); c->has_b_frames=0; // No PTS=cannot handle CTS... c->max_b_frames=0; }else if(fourCC::check(stream->getFCC(),(uint8_t *)"FLV1")) { c->has_b_frames=0; // No PTS=cannot handle CTS... c->max_b_frames=0; c->codec_id=CODEC_ID_FLV1; setAvCodec(c,CODEC_ID_FLV1); }else { if(fourCC::check(stream->getFCC(),(uint8_t *)"MPEG1")) { c->has_b_frames=1; // No PTS=cannot handle CTS... c->max_b_frames=2; c->codec_id=CODEC_ID_MPEG1VIDEO; } else if(fourCC::check(stream->getFCC(),(uint8_t *)"MPEG2")) { c->has_b_frames=1; // No PTS=cannot handle CTS... c->max_b_frames=2; c->codec_id=CODEC_ID_MPEG2VIDEO; }else { uint32_t id=stream->getFCC(); AVCodecID cid=ADM_codecIdFindByFourcc(fourCC::tostring(id)); if(cid==CODEC_ID_NONE) { printf("[FF] Unknown video codec\n"); return false; } c->codec_id=cid; } } } } } if(useGlobalHeader()==true) { if(videoExtraDataSize) { ADM_info("Video has extradata and muxer requires globalHeader, assuming it is done so.\n"); c->flags|=CODEC_FLAG_GLOBAL_HEADER; }else { ADM_warning("Video has no extradata but muxer requires globalHeader.\n"); } } printf("[FF] Video initialized\n"); return true; }
void A_SaveAudioNVideo(char *name) { uint32_t needSmart=0,fl; GenericAviSave *nw; aviInfo info; video_body->getVideoInfo(&info); printf("\n video process mode : %d",videoProcessMode); if (!videoProcessMode) { if(video_body->isMultiSeg()) needSmart=1; video_body->getFlags(frameStart,&fl); if(!(fl&AVI_KEY_FRAME)) needSmart=1; if(needSmart) printf("\n probably need smart copy mode\n"); if( !isMpeg4Compatible( info.fcc) #ifdef USE_FFMPEG && !isMSMpeg4Compatible(info.fcc) #endif ) { printf("\n not encodable, cancelling smart mode\n"); needSmart=0; } #ifdef HAVE_ENCODER if(needSmart && GUI_Question("You may need smart copy.\n Enable it ?")) { nw=new GenericAviSaveSmart; } else { nw=new GenericAviSaveCopy; } #else nw=new GenericAviSaveCopy; #endif } else { #ifdef HAVE_ENCODER printf("\n Process mode\n"); nw=new GenericAviSaveProcess; #else GUI_Alert("\n No encoder , cannot save in process mode"); return ; #endif } if(!nw->saveAvi(name)) { GUI_Alert(" AVI NOT saved"); } else GUI_Alert(" Saved successfully"); delete nw; }
/** \fn getDecoder \brief returns the correct decoder for a stream w,h,fcc,extraLen,extraData,bpp */ decoders *ADM_coreCodecGetDecoder (uint32_t fcc, uint32_t w, uint32_t h, uint32_t extraLen, uint8_t * extraData,uint32_t bpp) { ADM_info("Searching decoder in coreVideoCodec(%d x %d, extradataSize:%d)...\n",w,h,extraLen); if (isMSMpeg4Compatible (fcc) == 1) { return (decoders *) (new decoderFFDiv3 (w,h,fcc,extraLen,extraData,bpp)); } if (isDVCompatible(fcc))//"CDVC")) { return (decoders *) (new decoderFFDV (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "HFYU")) { return (decoders *) (new decoderFFhuff (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "PNG ")) { return (decoders *) (new decoderFFPng (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "FFVH")) { return (decoders *) (new decoderFF_ffhuff (w,h,fcc,extraLen,extraData,bpp)); } if (isH264Compatible (fcc)) { #if defined(USE_VDPAU) && 0 if(vdpauUsable()==true) return (decoders *) (new decoderFFVDPAU (w,h,fcc,extraLen,extraData,bpp)); else #endif return (decoders *) (new decoderFFH264 (w,h,fcc,extraLen,extraData,bpp)); } /* Could be either divx5 packed crap or xvid or ffmpeg For now we return FFmpeg and later will switch to divx5 if available (ugly hack for ugly hack....) */ if (isMpeg4Compatible (fcc) == 1) { return (decoders *) (new decoderFFMpeg4 (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "YV12") || fourCC::check (fcc, (uint8_t *) "yv12") || fourCC::check (fcc, (uint8_t *) "I420")) { printf ("\n using null codec\n"); return (decoders *) (new decoderNull (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "UYVY")) { printf ("\n using uyvy codec\n"); return (decoders *) (new decoderUYVY (w,h,fcc,extraLen,extraData,bpp)); } if (fourCC::check (fcc, (uint8_t *) "YUY2")) { printf ("\n using YUY2 codec\n"); return (decoders *) (new decoderYUY2 (w,h,fcc,extraLen,extraData,bpp)); } if ((fcc == 0) || fourCC::check (fcc, (uint8_t *) "RGB ")) { // RGB 16 Codecs printf ("\n using RGB codec\n"); return (decoders *) (new decoderRGB16 (w,h,fcc,extraLen,extraData,bpp)); //1 } if ((fcc == 0) || fourCC::check (fcc, (uint8_t *) "DIB ")) { // RGB 16 Codecs printf ("\n using DIB codec (%d bpp)\n",(int)bpp); return (decoders *) (new decoderRGB16 (w,h,fcc,extraLen,extraData,bpp)); //0 } if (isMpeg12Compatible (fcc)) return (decoders *) (new decoderFFMpeg12 (w,h,fcc,extraLen,extraData,bpp)); // Search ffsimple decoders *dec=admCreateFFSimple(w,h,fcc,extraLen,extraData,bpp); if(dec) { printf("using ffSimple\n"); return dec; } // default : null decoder printf ("\n using invalid codec for \n"); fourCC::print (fcc); return (decoders *) (new decoderEmpty(w,h,fcc,extraLen,extraData,bpp)); }
bool muxerMP4::open(const char *file, ADM_videoStream *s,uint32_t nbAudioTrack,ADM_audioStream **a) { if(!isMpeg4Compatible(s->getFCC()) && !isH264Compatible(s->getFCC())) { GUI_Error_HIG("Unsupported","Only MP4Video & H264 supported for video"); return false; } if(nbAudioTrack) for(int i=0; i<nbAudioTrack; i++) { uint32_t acc=a[i]->getInfo()->encoding; if(acc!=WAV_MP2 && acc!=WAV_MP3 && acc!=WAV_AAC) { GUI_Error_HIG("Unsupported","Only AAC & mpegaudio supported for audio"); return false; } } /* All seems fine, open stuff */ const char *f="mp4"; if(muxerConfig.muxerType==MP4_MUXER_PSP) f="psp"; if(false==setupMuxer(f,file)) { printf("[MP4] Failed to open muxer\n"); return false; } if(initVideo(s)==false) { printf("[MP4] Failed to init video\n"); return false; } AVCodecContext *c; AVRational myTimeBase; c = video_st->codec; rescaleFps(s->getAvgFps1000(),&(c->time_base)); myTimeBase=video_st->time_base=c->time_base; ADM_info("Video stream time base :%d,%d\n",video_st->time_base.num,video_st->time_base.den); c->gop_size=15; if(initAudio(nbAudioTrack,a)==false) { printf("[MP4] Failed to init audio\n"); return false; } // /audio int er = avio_open(&(oc->pb), file, AVIO_FLAG_WRITE); ADM_info("Timebase In = %d/%d\n",myTimeBase.num,myTimeBase.den); if (er) { ADM_error("[Mp4]: Failed to open file :%s, er=%d\n",file,er); return false; } AVDictionary *dict = NULL; char buf[64]; snprintf(buf, sizeof(buf), "%d", AV_TIME_BASE / 10); av_dict_set(&dict, "preload", buf, 0); av_dict_set(&dict, "max_delay", "200000", 0); av_dict_set(&dict, "muxrate", "10080000", 0); #ifndef _WIN32 // does not work on windows as the file must be opened twice at the same time av_dict_set(&dict, "movflags","faststart",0); #endif ADM_assert(avformat_write_header(oc, &dict) >= 0); ADM_info("Timebase codec = %d/%d\n",c->time_base.num,c->time_base.den); ADM_info("Timebase stream = %d/%d\n",video_st->time_base.num,video_st->time_base.den); if(myTimeBase.den==video_st->time_base.den && video_st->time_base.num==1) { roundup=myTimeBase.num; ADM_warning("Timebase roundup = %d\n",roundup); } av_dict_free(&dict); vStream=s; aStreams=a; nbAStreams=nbAudioTrack; initialized=true; return true; }