UINT CFlvUtils::Init() { HRESULT hr = S_OK; if (!m_szFlvFile) hr = E_FAIL; if (SUCCEEDED(hr)) { // Must be called before using avcodec lib avcodec_init(); // Initialize libavcodec // and register all formats and codecs av_register_all(); } if (SUCCEEDED(hr)) { //Auto detect the output format from the name. Default is flv. m_pAVOutputFormat = guess_format(NULL, m_szFlvFile, NULL); if (!m_pAVOutputFormat) { _tprintf(_T("Could not deduce output format from file extension: using FLV.\n")); m_pAVOutputFormat = guess_format("flv", NULL, NULL); } if (!m_pAVOutputFormat) { _ftprintf(stderr, _T("Error in CFlvUtils::Init():\n Could not find suitable output format!\n")); hr = E_FAIL; // TODO: error handling? } } if (SUCCEEDED(hr)) { // Allocate the output media context m_pAVFormatContext = av_alloc_format_context(); if (!m_pAVFormatContext) { _ftprintf(stderr, _T("Error in CFlvUtils::Init():\n Could not allocate the output media context!\n")); hr = E_FAIL; // TODO: error handling? } else { m_pAVFormatContext->oformat = m_pAVOutputFormat; //_sntprintf(m_pAVFormatContext->filename, sizeof(m_pAVFormatContext->filename), _T("%s"), m_szFlvFile); _snprintf(m_pAVFormatContext->filename, sizeof(m_pAVFormatContext->filename), "%s", m_szFlvFile); } } return hr; }
bool CFFMPEGLoader::CreateMovie(const char *filename, const AVOutputFormat *format, const AVCodecContext *VideoCon, const AVCodecContext *AudioCon) { if(!filename) return false; AVOutputFormat *fmt; //*fmt=*format; fmt = guess_format(NULL, filename, NULL); pFormatCon = av_alloc_format_context(); if(!pFormatCon) { cout<<"Error while allocating format context\n"; return false; } bOutput=true; strcpy(pFormatCon->filename,filename); pFormatCon->oformat=fmt; pAudioStream=pVideoStream=NULL; if (fmt->video_codec != CODEC_ID_NONE) { pVideoStream = add_video_stream(pFormatCon, fmt->video_codec,VideoCon); } if (fmt->audio_codec != CODEC_ID_NONE) { pAudioStream = add_audio_stream(pFormatCon, fmt->audio_codec,AudioCon); } if (av_set_parameters(pFormatCon, NULL) < 0) { cout<<"Invalid output format parameters\n"; return false; } if (pVideoStream) open_stream(pFormatCon, pVideoStream); if (pAudioStream) open_stream(pFormatCon, pAudioStream); dump_format(pFormatCon, 0, filename, 1); if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&pFormatCon->pb, filename, URL_WRONLY) < 0) { cout<<"Could not open '%s'"<<filename<<endl; return false; } } /* write the stream header, if any */ av_write_header(pFormatCon); return true; }
static VALUE alloc_media(VALUE self) { // Fixes the problem where GC only runs on exit, // so in a script that opens a lot of media files // it runs out of memory rb_gc(); AVFormatContext * fmt_ctx = av_alloc_format_context(); VALUE obj; fmt_ctx->oformat = NULL; fmt_ctx->iformat = NULL; obj = Data_Wrap_Struct(self, 0, free_media, fmt_ctx); return obj; }
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; }
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 OStreamVideoEncoder::encoder_initialize () { char *encoding_str; // register all codecs av_register_all(); switch ( _encoding_type ) { case OSTREAM_ENCODING_MJPEG: encoding_str = "mjpeg"; _out_fmt = guess_format ( encoding_str, NULL, NULL); if( !_out_fmt ) { // DEBUG_PRINT( "Could not find suitable output format.\n"); return false; } break; case OSTREAM_ENCODING_H263P: encoding_str ="h263"; _out_fmt = guess_format ( encoding_str, NULL, NULL); if( !_out_fmt ) { // DEBUG_PRINT( "Could not find suitable output format.\n"); return false; } // specify the sub-codec we want to use. Without this we won't be able // to stream H263P not use 640x480 videos _out_fmt->video_codec = CODEC_ID_H263P; break; default: // DEBUG_PRINT ("could not find known OSTREAM_ENCODING type.\n" ); break; } _out_fmt_context = av_alloc_format_context (); if( !_out_fmt_context ) { // DEBUG_PRINT( "Memory error.\n" ); return false; } // set output format of AVFormatContext _out_fmt_context->oformat = _out_fmt; // check if we had a correct video_codec if ( _out_fmt->video_codec == CODEC_ID_NONE ) { // DEBUG_PRINT( "CODEC_ID_NONE\n" ); return false; } // add the stream if(!( _video_stream = create_video_stream( _out_fmt_context, _out_fmt->video_codec ) )) { // DEBUG_PRINT( "error in adding stream\n" ); return false; } // set the output parameters (must be done even if no parameters) if ( av_set_parameters( _out_fmt_context, NULL ) < 0 ) { // DEBUG_PRINT( "Invalid output format parameters\n" ); return false; } // open codec associated with current video_stream if ( !open_codec( _video_stream ) ) { // DEBUG_PRINT( "could not open codec\n" ); return false; } // we should now create the frame on which we can store the converted bytes // ready to be encoded _ready_to_encode_frame = create_avframe( _video_stream->codec->pix_fmt,this->_video_width,this->_video_height ); if ( !_ready_to_encode_frame ) { // DEBUG_PRINT( "Could not allocate encoded_frame\n" ); return false; } // we'll receive IplImage(s). This _opencv_frame will be converted to a stream-compatible // AVFrame [see up _ready_to_encode_frame] _opencv_frame = NULL; return true; }
int muxer_init_muxer_lavf(muxer_t *muxer) { muxer_priv_t *priv; AVOutputFormat *fmt = NULL; char mp_filename[256] = "menc://stream.dummy"; av_register_all(); if (conf_format && strcmp(conf_format, "help") == 0) { list_formats(); return 0; } mp_msg(MSGT_MUXER, MSGL_WARN, "** MUXER_LAVF *****************************************************************\n"); if (!conf_allow_lavf) { mp_msg(MSGT_MUXER, MSGL_FATAL, "If you wish to use libavformat muxing, you must ensure that your video stream\n" "does not contain B frames (out of order decoding) and specify:\n" " -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames\n" "on the command line.\n"); } else { mp_msg(MSGT_MUXER, MSGL_WARN, "You have certified that your video stream does not contain B frames.\n"); } mp_msg(MSGT_MUXER, MSGL_WARN, "REMEMBER: MEncoder's libavformat muxing is presently broken and will generate\n" "INCORRECT files in the presence of B frames. Moreover, due to bugs MPlayer\n" "will play these INCORRECT files as if nothing were wrong!\n" "*******************************************************************************\n"); if (!conf_allow_lavf) return 0; priv = (muxer_priv_t *) calloc(1, sizeof(muxer_priv_t)); if(priv == NULL) return 0; priv->oc = av_alloc_format_context(); if(!priv->oc) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't get format context\n"); goto fail; } if(conf_format) fmt = guess_format(conf_format, NULL, NULL); if(! fmt) fmt = guess_format(NULL, out_filename, NULL); if(! fmt) { mp_msg(MSGT_MUXER, MSGL_FATAL, "CAN'T GET SPECIFIED FORMAT\n"); goto fail; } priv->oc->oformat = fmt; if(av_set_parameters(priv->oc, NULL) < 0) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Invalid output format parameters\n"); goto fail; } priv->oc->packet_size= mux_packet_size; priv->oc->mux_rate= mux_rate; priv->oc->preload= (int)(mux_preload*AV_TIME_BASE); priv->oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE); if (info_name) pstrcpy(priv->oc->title , sizeof(priv->oc->title ), info_name ); if (info_artist) pstrcpy(priv->oc->author , sizeof(priv->oc->author ), info_artist ); if (info_genre) pstrcpy(priv->oc->genre , sizeof(priv->oc->genre ), info_genre ); if (info_copyright) pstrcpy(priv->oc->copyright, sizeof(priv->oc->copyright), info_copyright); if (info_comment) pstrcpy(priv->oc->comment , sizeof(priv->oc->comment ), info_comment ); register_protocol(&mp_protocol); if(url_fopen(&priv->oc->pb, mp_filename, URL_WRONLY)) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Coulnd't open outfile\n"); goto fail; } ((URLContext*)(priv->oc->pb.opaque))->priv_data= muxer; muxer->priv = (void *) priv; muxer->cont_new_stream = &lavf_new_stream; muxer->cont_write_chunk = &write_chunk; muxer->cont_write_header = &write_header; muxer->cont_write_index = &write_trailer; muxer->fix_stream_parameters = &fix_parameters; mp_msg(MSGT_MUXER, MSGL_INFO, "OK, exit\n"); return 1; fail: free(priv); return 0; }
/// Create a video writer object that uses FFMPEG CV_IMPL CvVideoWriter* cvCreateVideoWriter( const char * filename, int fourcc, double fps, CvSize frameSize, int /*is_color*/ ) { CV_FUNCNAME("cvCreateVideoWriter"); CvAVI_FFMPEG_Writer * writer = NULL; __BEGIN__; // check arguments assert (filename); assert (fps > 0); assert (frameSize.width > 0 && frameSize.height > 0); // allocate memory for structure... writer = (CvAVI_FFMPEG_Writer *) cvAlloc( sizeof(CvAVI_FFMPEG_Writer)); memset (writer, 0, sizeof (*writer)); // tell FFMPEG to register codecs av_register_all (); /* auto detect the output format from the name. default is mpeg. */ writer->fmt = guess_format(NULL, filename, NULL); if (!writer->fmt) { CV_ERROR( CV_StsUnsupportedFormat, "Could not deduce output format from file extension"); //writer->fmt = guess_format("mpeg", NULL, NULL); } // alloc memory for context writer->oc = av_alloc_format_context(); assert (writer->oc); /* set file name */ writer->oc->oformat = writer->fmt; snprintf(writer->oc->filename, sizeof(writer->oc->filename), "%s", filename); // TODO -- safe to ignore output audio stream? writer->video_st = icv_add_video_stream_FFMPEG(writer->oc, fourcc, frameSize.width, frameSize.height, 800000, fps, PIX_FMT_YUV420P); /* set the output parameters (must be done even if no parameters). */ if (av_set_parameters(writer->oc, NULL) < 0) { CV_ERROR(CV_StsBadArg, "Invalid output format parameters"); } dump_format(writer->oc, 0, filename, 1); /* now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers */ if (!writer->video_st){ CV_ERROR(CV_StsBadArg, "Couldn't open video stream"); } AVCodec *codec; AVCodecContext *c; #if LIBAVFORMAT_BUILD > 4628 c = (writer->video_st->codec); #else c = &(writer->video_st->codec); #endif /* find the video encoder */ codec = avcodec_find_encoder(c->codec_id); if (!codec) { CV_ERROR(CV_StsBadArg, "codec not found"); } /* open the codec */ if (avcodec_open(c, codec) < 0) { char errtext[256]; sprintf(errtext, "Could not open codec '%s'", codec->name); CV_ERROR(CV_StsBadArg, errtext); } // printf("Using codec %s\n", codec->name); writer->outbuf = NULL; if (!(writer->oc->oformat->flags & AVFMT_RAWPICTURE)) { /* allocate output buffer */ /* XXX: API change will be done */ writer->outbuf_size = 200000; writer->outbuf = (uint8_t *) malloc(writer->outbuf_size); } bool need_color_convert; need_color_convert = c->pix_fmt != PIX_FMT_BGR24; /* allocate the encoded raw picture */ writer->picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); if (!writer->picture) { CV_ERROR(CV_StsNoMem, "Could not allocate picture"); } /* if the output format is not YUV420P, then a temporary YUV420P picture is needed too. It is then converted to the required output format */ writer->rgb_picture = NULL; if ( need_color_convert ) { writer->rgb_picture = icv_alloc_picture_FFMPEG(PIX_FMT_BGR24, c->width, c->height, false); if (!writer->rgb_picture) { CV_ERROR(CV_StsNoMem, "Could not allocate picture"); } } /* open the output file, if needed */ if (!(writer->fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&writer->oc->pb, filename, URL_WRONLY) < 0) { CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing"); } } /* write the stream header, if any */ av_write_header( writer->oc ); __END__; // return what we got return (CvVideoWriter *) writer; }
/// close video output stream and free associated memory void CvVideoWriter_FFMPEG::close() { unsigned i; // nothing to do if already released if ( !picture ) return; /* no more frame to compress. The codec has a latency of a few frames if using B frames, so we get the last frames by passing the same picture again */ // TODO -- do we need to account for latency here? /* write the trailer, if any */ av_write_trailer(oc); // free pictures #if LIBAVFORMAT_BUILD > 4628 if( video_st->codec->pix_fmt != input_pix_fmt){ #else if( video_st->codec.pix_fmt != input_pix_fmt){ #endif cvFree(&(picture->data[0])); } av_free(picture); if (input_picture) { av_free(input_picture); } /* close codec */ #if LIBAVFORMAT_BUILD > 4628 avcodec_close(video_st->codec); #else avcodec_close(&(video_st->codec)); #endif av_free(outbuf); /* free the streams */ for(i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]); } if (!(fmt->flags & AVFMT_NOFILE)) { /* close the output file */ #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(49<<8)+0) url_fclose(oc->pb); #else url_fclose(&oc->pb); #endif } /* free the stream */ av_free(oc); cvReleaseImage( &temp_image ); init(); } /// Create a video writer object that uses FFMPEG bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, double fps, CvSize frameSize, bool is_color ) { CV_FUNCNAME("CvVideoWriter_FFMPEG::open"); CodecID codec_id = CODEC_ID_NONE; int err, codec_pix_fmt, bitrate_scale=64; __BEGIN__; close(); // check arguments assert (filename); assert (fps > 0); assert (frameSize.width > 0 && frameSize.height > 0); // tell FFMPEG to register codecs av_register_all (); /* auto detect the output format from the name and fourcc code. */ fmt = guess_format(NULL, filename, NULL); if (!fmt) { CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension"); } /* determine optimal pixel format */ if (is_color) { input_pix_fmt = PIX_FMT_BGR24; } else { input_pix_fmt = PIX_FMT_GRAY8; } // alloc memory for context oc = av_alloc_format_context(); assert (oc); /* set file name */ oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename), "%s", filename); /* set some options */ oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ /* Lookup codec_id for given fourcc */ #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){ CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." ); } #else { const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ){ CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." ); } } #endif // set a few optimal pixel formats for lossless codecs of interest.. switch (codec_id) { #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) case CODEC_ID_JPEGLS: // BGR24 or GRAY8 depending on is_color... codec_pix_fmt = input_pix_fmt; break; #endif case CODEC_ID_HUFFYUV: codec_pix_fmt = PIX_FMT_YUV422P; break; case CODEC_ID_MJPEG: case CODEC_ID_LJPEG: codec_pix_fmt = PIX_FMT_YUVJ420P; bitrate_scale = 128; break; case CODEC_ID_RAWVIDEO: default: // good for lossy formats, MPEG, etc. codec_pix_fmt = PIX_FMT_YUV420P; break; } // TODO -- safe to ignore output audio stream? video_st = icv_add_video_stream_FFMPEG(oc, codec_id, frameSize.width, frameSize.height, frameSize.width*frameSize.height*bitrate_scale, fps, codec_pix_fmt); /* set the output parameters (must be done even if no parameters). */ if (av_set_parameters(oc, NULL) < 0) { CV_ERROR(CV_StsBadArg, "Invalid output format parameters"); } dump_format(oc, 0, filename, 1); /* now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers */ if (!video_st){ CV_ERROR(CV_StsBadArg, "Couldn't open video stream"); } AVCodec *codec; AVCodecContext *c; #if LIBAVFORMAT_BUILD > 4628 c = (video_st->codec); #else c = &(video_st->codec); #endif c->codec_tag = fourcc; /* find the video encoder */ codec = avcodec_find_encoder(c->codec_id); if (!codec) { CV_ERROR(CV_StsBadArg, "codec not found"); } /* open the codec */ if ( (err=avcodec_open(c, codec)) < 0) { char errtext[256]; sprintf(errtext, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); CV_ERROR(CV_StsBadArg, errtext); } outbuf = NULL; if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { /* allocate output buffer */ /* assume we will never get codec output with more than 4 bytes per pixel... */ outbuf_size = frameSize.width*frameSize.height*4; outbuf = (uint8_t *) av_malloc(outbuf_size); } bool need_color_convert; need_color_convert = (c->pix_fmt != input_pix_fmt); /* allocate the encoded raw picture */ picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); if (!picture) { CV_ERROR(CV_StsNoMem, "Could not allocate picture"); } /* if the output format is not our input format, then a temporary picture of the input format is needed too. It is then converted to the required output format */ input_picture = NULL; if ( need_color_convert ) { input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); if (!input_picture) { CV_ERROR(CV_StsNoMem, "Could not allocate picture"); } } /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { CV_ERROR(CV_StsBadArg, "Couldn't open output file for writing"); } } /* write the stream header, if any */ av_write_header( oc ); __END__; return true; }
/// Create a video writer object that uses FFMPEG inline bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, double fps, int width, int height, bool is_color ) { icvInitFFMPEG_internal(); CodecID codec_id = CODEC_ID_NONE; int err, codec_pix_fmt; double bitrate_scale = 1; close(); // check arguments if( !filename ) return false; if(fps <= 0) return false; // we allow frames of odd width or height, but in this case we truncate // the rightmost column/the bottom row. Probably, this should be handled more elegantly, // but some internal functions inside FFMPEG swscale require even width/height. width &= -2; height &= -2; if( width <= 0 || height <= 0 ) return false; /* auto detect the output format from the name and fourcc code. */ #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) fmt = av_guess_format(NULL, filename, NULL); #else fmt = guess_format(NULL, filename, NULL); #endif if (!fmt) return false; /* determine optimal pixel format */ if (is_color) { input_pix_fmt = PIX_FMT_BGR24; } else { input_pix_fmt = PIX_FMT_GRAY8; } /* Lookup codec_id for given fourcc */ #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ) return false; #else const struct AVCodecTag * tags[] = { codec_bmp_tags, NULL}; if( (codec_id = av_codec_get_id(tags, fourcc)) == CODEC_ID_NONE ) return false; #endif // alloc memory for context #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) oc = avformat_alloc_context(); #else oc = av_alloc_format_context(); #endif assert (oc); /* set file name */ oc->oformat = fmt; _snprintf(oc->filename, sizeof(oc->filename), "%s", filename); /* set some options */ oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ // set a few optimal pixel formats for lossless codecs of interest.. switch (codec_id) { #if LIBAVCODEC_VERSION_INT>((50<<16)+(1<<8)+0) case CODEC_ID_JPEGLS: // BGR24 or GRAY8 depending on is_color... codec_pix_fmt = input_pix_fmt; break; #endif case CODEC_ID_HUFFYUV: codec_pix_fmt = PIX_FMT_YUV422P; break; case CODEC_ID_MJPEG: case CODEC_ID_LJPEG: codec_pix_fmt = PIX_FMT_YUVJ420P; bitrate_scale = 3; break; case CODEC_ID_RAWVIDEO: codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 || input_pix_fmt == PIX_FMT_GRAY16LE || input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P; break; default: // good for lossy formats, MPEG, etc. codec_pix_fmt = PIX_FMT_YUV420P; break; } double bitrate = MIN(bitrate_scale*fps*width*height, (double)INT_MAX/2); // TODO -- safe to ignore output audio stream? video_st = icv_add_video_stream_FFMPEG(oc, codec_id, width, height, (int)(bitrate + 0.5), fps, codec_pix_fmt); /* set the output parameters (must be done even if no parameters). */ #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) if (av_set_parameters(oc, NULL) < 0) { return false; } #endif #if 0 #if FF_API_DUMP_FORMAT dump_format(oc, 0, filename, 1); #else av_dump_format(oc, 0, filename, 1); #endif #endif /* now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers */ if (!video_st){ return false; } AVCodec *codec; AVCodecContext *c; #if LIBAVFORMAT_BUILD > 4628 c = (video_st->codec); #else c = &(video_st->codec); #endif c->codec_tag = fourcc; /* find the video encoder */ codec = avcodec_find_encoder(c->codec_id); if (!codec) { fprintf(stderr, "Could not find encoder for codec id %d: %s", c->codec_id, icvFFMPEGErrStr( #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0) AVERROR_ENCODER_NOT_FOUND #else -1 #endif )); return false; } s64 lbit_rate = (s64)c->bit_rate; lbit_rate += (bitrate / 2); lbit_rate = std::min(lbit_rate, (s64)INT_MAX); c->bit_rate_tolerance = (int)lbit_rate; c->bit_rate = (int)lbit_rate; /* open the codec */ if ((err= #if LIBAVCODEC_VERSION_INT >= ((53<<16)+(8<<8)+0) avcodec_open2(c, codec, NULL) #else avcodec_open(c, codec) #endif ) < 0) { fprintf(stderr, "Could not open codec '%s': %s", codec->name, icvFFMPEGErrStr(err)); return false; } outbuf = NULL; if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { /* allocate output buffer */ /* assume we will never get codec output with more than 4 bytes per pixel... */ outbuf_size = width*height*4; outbuf = (uint8_t *) av_malloc(outbuf_size); } bool need_color_convert; need_color_convert = (c->pix_fmt != input_pix_fmt); /* allocate the encoded raw picture */ picture = icv_alloc_picture_FFMPEG(c->pix_fmt, c->width, c->height, need_color_convert); if (!picture) { return false; } /* if the output format is not our input format, then a temporary picture of the input format is needed too. It is then converted to the required output format */ input_picture = NULL; if ( need_color_convert ) { input_picture = icv_alloc_picture_FFMPEG(input_pix_fmt, c->width, c->height, false); if (!input_picture) { return false; } } /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(53, 2, 0) if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) #else if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) #endif { return false; } } #if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(52, 111, 0) /* write the stream header, if any */ err=avformat_write_header(oc, NULL); #else err=av_write_header( oc ); #endif if(err < 0) { close(); remove(filename); return false; } frame_width = width; frame_height = height; ok = true; return true; }
/// close video output stream and free associated memory void CvVideoWriter_FFMPEG::close() { unsigned i; // nothing to do if already released if ( !picture ) return; /* no more frame to compress. The codec has a latency of a few frames if using B frames, so we get the last frames by passing the same picture again */ // TODO -- do we need to account for latency here? /* write the trailer, if any */ av_write_trailer(oc); // free pictures #if LIBAVFORMAT_BUILD > 4628 if( video_st->codec->pix_fmt != input_pix_fmt){ #else if( video_st->codec.pix_fmt != input_pix_fmt){ #endif cvFree(&(picture->data[0])); } av_free(picture); if (input_picture) { av_free(input_picture); } /* close codec */ #if LIBAVFORMAT_BUILD > 4628 avcodec_close(video_st->codec); #else avcodec_close(&(video_st->codec)); #endif av_free(outbuf); /* free the streams */ for(i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]); } if (!(fmt->flags & AVFMT_NOFILE)) { /* close the output file */ #if LIBAVCODEC_VERSION_INT==((51<<16)+(49<<8)+0) url_fclose(oc->pb); #else url_fclose(&oc->pb); #endif } /* free the stream */ av_free(oc); cvReleaseImage( &temp_image ); init(); } /// Create a video writer object that uses FFMPEG bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, double fps, CvSize frameSize, bool is_color ) { CV_FUNCNAME("CvVideoWriter_FFMPEG::open"); CodecID codec_id = CODEC_ID_NONE; int err; __BEGIN__; close(); // check arguments assert (filename); assert (fps > 0); assert (frameSize.width > 0 && frameSize.height > 0); // tell FFMPEG to register codecs av_register_all (); /* auto detect the output format from the name and fourcc code. */ fmt = guess_format(NULL, filename, NULL); if (!fmt) { CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG does not recognize the given file extension"); } /* determine optimal pixel format */ if (is_color) { input_pix_fmt = PIX_FMT_BGR24; } else { input_pix_fmt = PIX_FMT_GRAY8; } // alloc memory for context oc = av_alloc_format_context(); assert (oc); /* set file name */ oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename), "%s", filename); /* set some options */ oc->max_delay = (int)(0.7*AV_TIME_BASE); /* This reduces buffer underrun warnings with MPEG */ /* Lookup codec_id for given fourcc */ if(fourcc!=CV_FOURCC_DEFAULT){ #if LIBAVCODEC_VERSION_INT<((51<<16)+(49<<8)+0) if( (codec_id = codec_get_bmp_id( fourcc )) == CODEC_ID_NONE ){ CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." ); } } #else if( (codec_id = av_codec_get_id((const AVCodecTag**)(&codec_bmp_tags), fourcc)) == CODEC_ID_NONE ){ CV_ERROR( CV_StsUnsupportedFormat, "FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection." ); } }
static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ AVFormatContext *avfc; AVFormatParameters ap; AVOption *opt; lavf_priv_t *priv= demuxer->priv; int i,g; char mp_filename[256]="mp:"; memset(&ap, 0, sizeof(AVFormatParameters)); stream_seek(demuxer->stream, 0); register_protocol(&mp_protocol); avfc = av_alloc_format_context(); if (correct_pts) avfc->flags |= AVFMT_FLAG_GENPTS; if (index_mode == 0) avfc->flags |= AVFMT_FLAG_IGNIDX; ap.prealloced_context = 1; if(opt_probesize) { double d = (double) opt_probesize; opt = av_set_double(avfc, "probesize", opt_probesize); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %.3f\r\n", d); } if(demuxer->stream->url) strncpy(mp_filename + 3, demuxer->stream->url, sizeof(mp_filename)-3); else strncpy(mp_filename + 3, "foobar.dummy", sizeof(mp_filename)-3); url_fopen(&priv->pb, mp_filename, URL_RDONLY); ((URLContext*)(priv->pb.opaque))->priv_data= demuxer->stream; if(av_open_input_stream(&avfc, &priv->pb, mp_filename, priv->avif, &ap)<0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n"); return NULL; } priv->avfc= avfc; if(av_find_stream_info(avfc) < 0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n"); return NULL; } if(avfc->title [0]) demux_info_add(demuxer, "name" , avfc->title ); if(avfc->author [0]) demux_info_add(demuxer, "author" , avfc->author ); if(avfc->copyright[0]) demux_info_add(demuxer, "copyright", avfc->copyright); if(avfc->comment [0]) demux_info_add(demuxer, "comments" , avfc->comment ); if(avfc->album [0]) demux_info_add(demuxer, "album" , avfc->album ); // if(avfc->year ) demux_info_add(demuxer, "year" , avfc->year ); // if(avfc->track ) demux_info_add(demuxer, "track" , avfc->track ); if(avfc->genre [0]) demux_info_add(demuxer, "genre" , avfc->genre ); for(i=0; i<avfc->nb_streams; i++){ AVStream *st= avfc->streams[i]; AVCodecContext *codec= st->codec; switch(codec->codec_type){ case CODEC_TYPE_AUDIO:{ WAVEFORMATEX *wf= calloc(sizeof(WAVEFORMATEX) + codec->extradata_size, 1); sh_audio_t* sh_audio; if(priv->audio_streams >= MAX_A_STREAMS) break; sh_audio=new_sh_audio(demuxer, i); if(!sh_audio) break; priv->astreams[priv->audio_streams] = i; priv->audio_streams++; if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_wav_taglists, codec->codec_id); wf->wFormatTag= codec->codec_tag; wf->nChannels= codec->channels; wf->nSamplesPerSec= codec->sample_rate; wf->nAvgBytesPerSec= codec->bit_rate/8; wf->nBlockAlign= codec->block_align ? codec->block_align : 1; wf->wBitsPerSample= codec->bits_per_sample; wf->cbSize= codec->extradata_size; if(codec->extradata_size){ memcpy( wf + 1, codec->extradata, codec->extradata_size); } sh_audio->wf= wf; sh_audio->audio.dwSampleSize= codec->block_align; if(codec->frame_size && codec->sample_rate){ sh_audio->audio.dwScale=codec->frame_size; sh_audio->audio.dwRate= codec->sample_rate; }else{ sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; sh_audio->audio.dwRate = codec->bit_rate; } g= ff_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); sh_audio->audio.dwScale /= g; sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); sh_audio->ds= demuxer->audio; sh_audio->format= codec->codec_tag; sh_audio->channels= codec->channels; sh_audio->samplerate= codec->sample_rate; sh_audio->i_bps= codec->bit_rate/8; switch (codec->codec_id) { case CODEC_ID_PCM_S8: case CODEC_ID_PCM_U8: sh_audio->samplesize = 1; break; case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: case CODEC_ID_PCM_U16BE: sh_audio->samplesize = 2; break; case CODEC_ID_PCM_ALAW: sh_audio->format = 0x6; break; case CODEC_ID_PCM_MULAW: sh_audio->format = 0x7; break; } if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); if((audio_lang && st->language[0] && !strncmp(audio_lang, st->language, 3)) || (demuxer->audio->id == i || demuxer->audio->id == -1) ) { demuxer->audio->id = i; demuxer->audio->sh= demuxer->a_streams[i]; } else st->discard= AVDISCARD_ALL; break;} case CODEC_TYPE_VIDEO:{ sh_video_t* sh_video; BITMAPINFOHEADER *bih; if(priv->video_streams >= MAX_V_STREAMS) break; sh_video=new_sh_video(demuxer, i); if(!sh_video) break; priv->vstreams[priv->video_streams] = i; priv->video_streams++; bih=calloc(sizeof(BITMAPINFOHEADER) + codec->extradata_size,1); if(!codec->codec_tag) codec->codec_tag= av_codec_get_tag(mp_bmp_taglists, codec->codec_id); bih->biSize= sizeof(BITMAPINFOHEADER) + codec->extradata_size; bih->biWidth= codec->width; bih->biHeight= codec->height; bih->biBitCount= codec->bits_per_sample; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; bih->biCompression= codec->codec_tag; sh_video->bih= bih; sh_video->disp_w= codec->width; sh_video->disp_h= codec->height; if (st->time_base.den) { /* if container has time_base, use that */ sh_video->video.dwRate= st->time_base.den; sh_video->video.dwScale= st->time_base.num; } else { sh_video->video.dwRate= codec->time_base.den; sh_video->video.dwScale= codec->time_base.num; } sh_video->fps=av_q2d(st->r_frame_rate); sh_video->frametime=1/av_q2d(st->r_frame_rate); sh_video->format = bih->biCompression; sh_video->aspect= codec->width * codec->sample_aspect_ratio.num / (float)(codec->height * codec->sample_aspect_ratio.den); sh_video->i_bps= codec->bit_rate/8; mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", codec->width, codec->sample_aspect_ratio.num, codec->height, codec->sample_aspect_ratio.den); sh_video->ds= demuxer->video; if(codec->extradata_size) memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); /* short biPlanes; int biXPelsPerMeter; int biYPelsPerMeter; int biClrUsed; int biClrImportant;*/ if(demuxer->video->id != i && demuxer->video->id != -1) st->discard= AVDISCARD_ALL; else{ demuxer->video->id = i; demuxer->video->sh= demuxer->v_streams[i]; } break;} default: st->discard= AVDISCARD_ALL; } } mp_msg(MSGT_HEADER,MSGL_V,"LAVF: %d audio and %d video streams found\n",priv->audio_streams,priv->video_streams); mp_msg(MSGT_HEADER,MSGL_V,"LAVF: build %d\n", LIBAVFORMAT_BUILD); if(!priv->audio_streams) demuxer->audio->id=-2; // nosound // else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio; if(!priv->video_streams){ if(!priv->audio_streams){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF: no audio or video headers found - broken file?\n"); return NULL; } demuxer->video->id=-2; // audio-only } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; return demuxer; }
void FFMpegManager::create(const QString &filePath, int formatId, const QStringList &paths, const QSize &size, int fps) { #ifdef HAVE_FFMPEG AVOutputFormat *fmt = guess_format(0, filePath.toLatin1().data(), 0); if ( !fmt ) { fmt = guess_format("mpeg", NULL, NULL); } // AVFormatParameters params, *ap = ¶ms; switch(formatId) { case ExportInterface::ASF: { } break; case ExportInterface::AVI: { fmt->video_codec = CODEC_ID_MSMPEG4V3; // video_st->codec.codec_tag = 0; } break; case ExportInterface::MOV: { } break; case ExportInterface::MPEG: { } break; case ExportInterface::RM: { } break; case ExportInterface::SWF: { } break; case ExportInterface::GIF: { // AVImageFormat *imageFormat = guess_image_format(filePath.toLatin1().data()); // // memset(ap, 0, sizeof(*ap)); // ap->image_format = imageFormat; } break; default: break; } AVFormatContext *oc = av_alloc_format_context(); if ( !oc ) { dError() << "Error while export"; return; } oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename), "%s", filePath.toLatin1().data()); AVStream *video_st = addVideoStream(oc, fmt->video_codec, size.width(), size.height(), fps); if ( !video_st ) { dError() << "Can't add video stream"; return; } if (av_set_parameters(oc, 0) < 0) { dError() << "Invalid output format parameters"; return ; } dump_format(oc, 0, filePath.toLatin1().data(), 1); if (!openVideo(oc, video_st) ) { dError() << "Can't open video"; return; } if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&oc->pb, filePath.toLatin1().data(), URL_WRONLY) < 0) { dError() << "Could not open " << filePath.toLatin1().data(); return; } } av_write_header(oc); double video_pts = 0.0; foreach(QString imagePath, paths) { if (video_st) { video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; } else { video_pts = 0.0; } if (!video_st || video_pts >= m_streamDuration ) { break; } if (! writeVideoFrame(imagePath, oc, video_st, fps) ) { break; } } closeVideo(oc, video_st); av_write_trailer(oc); for(int i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams[i]); } if (!(fmt->flags & AVFMT_NOFILE)) { /* close the output file */ url_fclose(&oc->pb); } av_free(oc); #endif }
static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ AVFormatContext *avfc; AVFormatParameters ap; const AVOption *opt; lavf_priv_t *priv= demuxer->priv; int i; char mp_filename[256]="mp:"; memset(&ap, 0, sizeof(AVFormatParameters)); stream_seek(demuxer->stream, 0); register_protocol(&mp_protocol); avfc = av_alloc_format_context(); if (opt_cryptokey) parse_cryptokey(avfc, opt_cryptokey); if (correct_pts) avfc->flags |= AVFMT_FLAG_GENPTS; if (index_mode == 0) avfc->flags |= AVFMT_FLAG_IGNIDX; ap.prealloced_context = 1; if(opt_probesize) { opt = av_set_int(avfc, "probesize", opt_probesize); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %u\n", opt_probesize); } if(opt_analyzeduration) { opt = av_set_int(avfc, "analyzeduration", opt_analyzeduration * AV_TIME_BASE); if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option analyzeduration to %u\n", opt_analyzeduration); } if(demuxer->stream->url) strncpy(mp_filename + 3, demuxer->stream->url, sizeof(mp_filename)-3); else strncpy(mp_filename + 3, "foobar.dummy", sizeof(mp_filename)-3); url_fopen(&priv->pb, mp_filename, URL_RDONLY); ((URLContext*)(priv->pb->opaque))->priv_data= demuxer->stream; if(av_open_input_stream(&avfc, priv->pb, mp_filename, priv->avif, &ap)<0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n"); return NULL; } priv->avfc= avfc; if(av_find_stream_info(avfc) < 0){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n"); return NULL; } if(avfc->title [0]) demux_info_add(demuxer, "name" , avfc->title ); if(avfc->author [0]) demux_info_add(demuxer, "author" , avfc->author ); if(avfc->copyright[0]) demux_info_add(demuxer, "copyright", avfc->copyright); if(avfc->comment [0]) demux_info_add(demuxer, "comments" , avfc->comment ); if(avfc->album [0]) demux_info_add(demuxer, "album" , avfc->album ); // if(avfc->year ) demux_info_add(demuxer, "year" , avfc->year ); // if(avfc->track ) demux_info_add(demuxer, "track" , avfc->track ); if(avfc->genre [0]) demux_info_add(demuxer, "genre" , avfc->genre ); if(avfc->nb_programs) { int p, start=0, found=0; if(ts_prog) { for(p=0; p<avfc->nb_programs; p++) { if(avfc->programs[p]->id == ts_prog) { start = p; found = 1; break; } } if(!found) { mp_msg(MSGT_HEADER,MSGL_ERR,"DEMUX_LAVF: program %d doesn't seem to be present\n", ts_prog); return NULL; } } p = start; do { AVProgram *program = avfc->programs[p]; mp_msg(MSGT_HEADER,MSGL_INFO,"LAVF: Program %d %s\n", program->id, (program->name ? program->name : "")); for(i=0; i<program->nb_stream_indexes; i++) handle_stream(demuxer, avfc, program->stream_index[i]); if(!priv->cur_program && (demuxer->video->sh || demuxer->audio->sh)) priv->cur_program = program->id; p = (p + 1) % avfc->nb_programs; } while(p!=start); } else for(i=0; i<avfc->nb_streams; i++) handle_stream(demuxer, avfc, i); mp_msg(MSGT_HEADER,MSGL_V,"LAVF: %d audio and %d video streams found\n",priv->audio_streams,priv->video_streams); mp_msg(MSGT_HEADER,MSGL_V,"LAVF: build %d\n", LIBAVFORMAT_BUILD); if(!priv->audio_streams) demuxer->audio->id=-2; // nosound // else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio; if(!priv->video_streams){ if(!priv->audio_streams){ mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF: no audio or video headers found - broken file?\n"); return NULL; } demuxer->video->id=-2; // audio-only } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; return demuxer; }
/** * ffmpeg_open * Opens an mpeg file using the new libavformat method. Both mpeg1 * and mpeg4 are supported. However, if the current ffmpeg version doesn't allow * mpeg1 with non-standard framerate, the open will fail. Timelapse is a special * case and is tested separately. * * Returns * A new allocated ffmpeg struct or NULL if any error happens. */ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename, unsigned char *y, unsigned char *u, unsigned char *v, int width, int height, int rate, int bps, int vbr) { AVCodecContext *c; AVCodec *codec; struct ffmpeg *ffmpeg; int is_mpeg1; int ret; /* * Allocate space for our ffmpeg structure. This structure contains all the * codec and image information we need to generate movies. * FIXME when motion exits we should close the movie to ensure that * ffmpeg is freed. */ ffmpeg = mymalloc(sizeof(struct ffmpeg)); memset(ffmpeg, 0, sizeof(struct ffmpeg)); ffmpeg->vbr = vbr; /* Store codec name in ffmpeg->codec, with buffer overflow check. */ snprintf(ffmpeg->codec, sizeof(ffmpeg->codec), "%s", ffmpeg_video_codec); /* Allocation the output media context. */ #if (LIBAVFORMAT_VERSION_MAJOR >= 53) ffmpeg->oc = avformat_alloc_context(); #else ffmpeg->oc = av_alloc_format_context(); #endif if (!ffmpeg->oc) { MOTION_LOG(ERR, TYPE_ENCODER, SHOW_ERRNO, "%s: Memory error while allocating" " output media context"); ffmpeg_cleanups(ffmpeg); return NULL; } /* Setup output format */ ffmpeg->oc->oformat = get_oformat(ffmpeg_video_codec, filename); if (!ffmpeg->oc->oformat) { ffmpeg_cleanups(ffmpeg); return NULL; } snprintf(ffmpeg->oc->filename, sizeof(ffmpeg->oc->filename), "%s", filename); /* Create a new video stream and initialize the codecs. */ ffmpeg->video_st = NULL; if (ffmpeg->oc->oformat->video_codec != AV_CODEC_ID_NONE) { ffmpeg->video_st = avformat_new_stream(ffmpeg->oc, NULL /* Codec */); if (!ffmpeg->video_st) { MOTION_LOG(ERR, TYPE_ENCODER, SHOW_ERRNO, "%s: av_new_stream - could" " not alloc stream"); ffmpeg_cleanups(ffmpeg); return NULL; } } else { /* We did not get a proper video codec. */ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Failed to obtain a proper" " video codec"); ffmpeg_cleanups(ffmpeg); return NULL; } ffmpeg->c = c = AVSTREAM_CODEC_PTR(ffmpeg->video_st); c->codec_id = ffmpeg->oc->oformat->video_codec; #if (LIBAVFORMAT_VERSION_MAJOR >= 53) c->codec_type = AVMEDIA_TYPE_VIDEO; #else c->codec_type = CODEC_TYPE_VIDEO; #endif is_mpeg1 = c->codec_id == AV_CODEC_ID_MPEG1VIDEO; if (strcmp(ffmpeg_video_codec, "ffv1") == 0) c->strict_std_compliance = -2; /* Uncomment to allow non-standard framerates. */ //c->strict_std_compliance = -1; /* Set default parameters */ c->bit_rate = bps; c->width = width; c->height = height; #if LIBAVCODEC_BUILD >= 4754 /* Frame rate = 1/time_base, so we set 1/rate, not rate/1 */ c->time_base.num = 1; c->time_base.den = rate; #else c->frame_rate = rate; c->frame_rate_base = 1; #endif /* LIBAVCODEC_BUILD >= 4754 */ MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "%s FPS %d", rate); if (vbr) c->flags |= CODEC_FLAG_QSCALE; /* * Set codec specific parameters. * Set intra frame distance in frames depending on codec. */ c->gop_size = is_mpeg1 ? 10 : 12; /* Some formats want stream headers to be separate. */ if (!strcmp(ffmpeg->oc->oformat->name, "mp4") || !strcmp(ffmpeg->oc->oformat->name, "mov") || !strcmp(ffmpeg->oc->oformat->name, "3gp")) { c->flags |= CODEC_FLAG_GLOBAL_HEADER; } /* Dump the format settings. This shows how the various streams relate to each other. */ //dump_format(ffmpeg->oc, 0, filename, 1); /* * Now that all the parameters are set, we can open the video * codec and allocate the necessary encode buffers. */ codec = avcodec_find_encoder(c->codec_id); if (!codec) { MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: Codec %s not found", ffmpeg_video_codec); ffmpeg_cleanups(ffmpeg); return NULL; } /* Set the picture format - need in ffmpeg starting round April-May 2005 */ c->pix_fmt = PIX_FMT_YUV420P; /* Get a mutex lock. */ pthread_mutex_lock(&global_lock); /* Open the codec */ ret = avcodec_open2(c, codec, NULL /* options */ ); if (ret < 0) { /* Release the lock. */ pthread_mutex_unlock(&global_lock); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: avcodec_open - could not open codec %s", ffmpeg_video_codec); ffmpeg_cleanups(ffmpeg); return NULL; } /* Release the lock. */ pthread_mutex_unlock(&global_lock); ffmpeg->video_outbuf = NULL; if (!(ffmpeg->oc->oformat->flags & AVFMT_RAWPICTURE)) { /* * Allocate output buffer * XXX: API change will be done * ffmpeg->video_outbuf_size = 200000 */ ffmpeg->video_outbuf_size = ffmpeg->c->width * 512; ffmpeg->video_outbuf = mymalloc(ffmpeg->video_outbuf_size); } /* Allocate the encoded raw picture. */ ffmpeg->picture = my_frame_alloc(); if (!ffmpeg->picture) { MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: avcodec_alloc_frame -" " could not alloc frame"); ffmpeg_cleanups(ffmpeg); return NULL; } /* Set variable bitrate if requested. */ if (ffmpeg->vbr) ffmpeg->picture->quality = ffmpeg->vbr; /* Set the frame data. */ ffmpeg->picture->data[0] = y; ffmpeg->picture->data[1] = u; ffmpeg->picture->data[2] = v; ffmpeg->picture->linesize[0] = ffmpeg->c->width; ffmpeg->picture->linesize[1] = ffmpeg->c->width / 2; ffmpeg->picture->linesize[2] = ffmpeg->c->width / 2; /* Open the output file, if needed. */ if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) { char file_proto[256]; /* * Use append file protocol for mpeg1, to get the append behavior from * url_fopen, but no protocol (=> default) for other codecs. */ if (is_mpeg1) #if defined FF_API_NEW_AVIO snprintf(file_proto, sizeof(file_proto), "%s", filename); #else snprintf(file_proto, sizeof(file_proto), APPEND_PROTO ":%s", filename); #endif else
// ###################################################################### FfmpegEncoder::FfmpegEncoder(const std::string& fname, const std::string& codecname, const int bitrate, const int framerate, const int frameratebase, const Dims& dims, const int bufsz, const bool useFormatContext) : itsFile(0), itsContext(), itsFormatContext(0), itsFrameNumber(0), itsOutbufSize(bufsz), itsFrameSizeRange(), itsUseFormatContext(useFormatContext) { GVX_TRACE(__PRETTY_FUNCTION__); // no need to guard these functions for being called multiple times; // they all have internal guards av_register_all(); avcodec_init(); avcodec_register_all(); AVOutputFormat* oformat = NULL; #if LIBAVCODEC_VERSION_MAJOR >= 53 && LIBAVCODEC_VERSION_MINOR >= 21 if (codecname.compare("List") == 0) { // list available codecs LINFO("##### Available output codecs (not all may work for video):"); AVOutputFormat* f = av_oformat_next(NULL); while(f) { LINFO("%s: %s %d", f->name, f->long_name, f->flags); f = av_oformat_next(f); } LFATAL("Please select a codec from this list"); } else { // format is given // no av_find_output_format()?? let's do it by hand... AVOutputFormat* f = av_oformat_next(NULL); while(f) { if (codecname.compare(f->name) == 0) { oformat = f; break; } f = av_oformat_next(f); } } #else if (codecname.compare("List") == 0) { // list available codecs LINFO("##### Available output codecs (not all may work for video):"); for(AVOutputFormat* f = first_oformat; f != NULL; f = f->next) LINFO("%s: %s %d", f->name, f->long_name, f->flags); LFATAL("Please select a codec from this list"); } else { // format is given // no av_find_output_format()?? let's do it by hand... for(AVOutputFormat* f = first_oformat; f != NULL; f = f->next) if (codecname.compare(f->name) == 0) { oformat = f; break; } } #endif if (oformat == 0) LFATAL("No such video codec '%s';\n" "try re-running with --output-codec=List to see a list\n" "of available codecs", codecname.c_str()); char ext[100]; ext[0] = '.'; uint i; for (i = 0; i < strlen(oformat->extensions); i ++) if (oformat->extensions[i] == ',') break; else ext[i+1] = oformat->extensions[i]; ext[i+1] = '\0'; LINFO("Using output format '%s' (%s), extension %s", oformat->name, oformat->long_name, ext); std::string oname(fname); std::string::size_type idx1 = oname.rfind('/', oname.npos); std::string::size_type idx2 = oname.rfind('.', oname.npos); // must check that idx2 is valid; otherwise if we do // oname.erase(idx2) with e.g. idx2==npos then we will get a // std::out_of_range exception if (idx2 < oname.size() && idx2 > idx1) oname.erase(idx2, oname.npos); oname.append(ext); LINFO("Output file: %s", oname.c_str()); if (itsUseFormatContext) { #ifdef INVT_FFMPEG_HAS_FORMATCONTEXT_FUNCTIONS LINFO("Using FormatContext to output data"); #ifdef AVMEDIA_TYPE_VIDEO itsFormatContext = avformat_alloc_context(); #else itsFormatContext = av_alloc_format_context(); #endif if (!itsFormatContext) LFATAL("Cannot allocate format context"); itsFormatContext->oformat = oformat; itsAVStream = av_new_stream(itsFormatContext, 0); if (!itsAVStream) LFATAL("Can not allocate AVStream"); #else LFATAL("Need a new version of ffmpeg libs for this option"); itsFormatContext = NULL; #endif } AVCodec* const codec = avcodec_find_encoder(oformat->video_codec); if (codec == NULL) LFATAL("codec not found"); #if defined(INVT_FFMPEG_HAS_DEFAULTS_FUNCTIONS) avcodec_get_context_defaults(&itsContext); #else { AVCodecContext* const tmp = avcodec_alloc_context(); memcpy(&itsContext, tmp, sizeof(AVCodecContext)); free(tmp); } #endif itsContext.bit_rate = bitrate; // Be sure to set itsContext.pix_fmt -- it may occasionally // appear to work to leave pix_fmt unset, because the value we want, // PIX_FMT_YUV420P, has the enum value of 0, so if the uninitialized // memory for pix_fmt happens to have the value 0, then we'll slip // through without setting it explicitly. itsContext.pix_fmt = PIX_FMT_YUV420P; /* resolution must be a multiple of two */ itsContext.width = dims.w(); itsContext.height = dims.h(); #if defined(INVT_FFMPEG_AVCODECCONTEXT_HAS_TIME_BASE) AVRational time_base = { frameratebase, framerate }; itsContext.time_base = time_base; const int frb = frameratebase; #elif LIBAVCODEC_VERSION_INT >= 0x000406 && LIBAVCODEC_BUILD > 4665 itsContext.frame_rate = framerate; const int frb = frameratebase; itsContext.frame_rate_base = frb; #else itsContext.frame_rate = framerate; const int frb = FRAME_RATE_BASE; #endif itsContext.gop_size = 10; /* emit one intra frame every ten frames */ if(codec->id != CODEC_ID_MPEG4 && codec->id != CODEC_ID_MPEG1VIDEO && codec->id != CODEC_ID_MPEG2VIDEO) itsContext.max_b_frames = 0; else itsContext.max_b_frames = 1; itsFrameNumber = 0; LINFO("using max_b_frames=%i bitrate=%u width=%u height=%u framerate=%u frameratebase=%u", itsContext.max_b_frames, itsContext.bit_rate, itsContext.width, itsContext.height, framerate, frb); if (avcodec_open(&itsContext, codec) < 0) LFATAL("could not open codec\n"); if (itsUseFormatContext) { #ifdef INVT_FFMPEG_HAS_FORMATCONTEXT_FUNCTIONS AVCodecContext *c = itsAVStream->codec; c->codec_id = itsContext.codec_id; #ifdef CODEC_TYPE_VIDEO c->codec_type = CODEC_TYPE_VIDEO; #else #ifdef AVMEDIA_TYPE_VIDEO c->codec_type = AVMEDIA_TYPE_VIDEO; #endif #endif /* put sample parameters */ c->bit_rate = itsContext.bit_rate; /* resolution must be a multiple of two */ c->width = itsContext.width; c->height = itsContext.height; /* time base: this is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented. for fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. */ #if defined(INVT_FFMPEG_AVCODECCONTEXT_HAS_TIME_BASE) c->time_base.den = itsContext.time_base.den; c->time_base.num = itsContext.time_base.num; #endif c->gop_size = 12; /* emit one intra frame every twelve frames at most */ c->pix_fmt = itsContext.pix_fmt; /* set the output parameters (must be done even if no parameters). */ if (av_set_parameters(itsFormatContext, NULL) < 0) LFATAL("Invalid output format parameters"); #if defined(INVT_FFMPEG_URL_OPEN_FUNC_TAKES_SINGLE_POINTER) #if defined(INVT_FFMPEG_AVFORMATCONTEXT_BYTEIO_ISPOINTER) if (url_fopen(itsFormatContext->pb, oname.c_str(), URL_WRONLY) < 0) LFATAL("Could not open '%s'", oname.c_str()); #else if (url_fopen(&itsFormatContext->pb, oname.c_str(), URL_WRONLY) < 0) LFATAL("Could not open '%s'", oname.c_str()); #endif #else #if defined(INVT_FFMPEG_AVFORMATCONTEXT_BYTEIO_ISPOINTER) if (url_fopen(&itsFormatContext->pb, oname.c_str(), URL_WRONLY) < 0) LFATAL("Could not open '%s'", oname.c_str()); #else LFATAL("Could not open '%s' ffmpeg version mismatch", oname.c_str()); #endif #endif //INVT_FFMPEG_URL_OPEN_FUNC_TAKES_SINGLE_POINTER) /* write the stream header, if any */ av_write_header(itsFormatContext); #else LFATAL("Need a new version of FFMPEG for this option"); #endif } else { itsFile = fopen(oname.c_str(), "w"); if (itsFile==NULL) LFATAL("could not open file! %s", oname.c_str()); } LINFO("EnCoder Inited"); }
void VideoWriterThread::open() { av_register_all(); // TODO: make sure this is only done once. // av_log_set_level(AV_LOG_DEBUG); #if LIBAVFORMAT_VERSION_MAJOR > 52 m_pOutputFormat = av_guess_format(0, m_sFilename.c_str(), 0); #else m_pOutputFormat = guess_format(0, m_sFilename.c_str(), 0); #endif m_pOutputFormat->video_codec = CODEC_ID_MJPEG; #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52, 24, 0) m_pOutputFormatContext = avformat_alloc_context(); #else m_pOutputFormatContext = av_alloc_format_context(); #endif m_pOutputFormatContext->oformat = m_pOutputFormat; strncpy(m_pOutputFormatContext->filename, m_sFilename.c_str(), sizeof(m_pOutputFormatContext->filename)); if (m_pOutputFormat->video_codec != CODEC_ID_NONE) { setupVideoStream(); } #if LIBAVFORMAT_VERSION_MAJOR < 52 av_set_parameters(m_pOutputFormatContext, NULL); #endif float muxMaxDelay = 0.7; m_pOutputFormatContext->max_delay = int(muxMaxDelay * AV_TIME_BASE); // av_dump_format(m_pOutputFormatContext, 0, m_sFilename.c_str(), 1); openVideoCodec(); m_pVideoBuffer = NULL; if (!(m_pOutputFormatContext->oformat->flags & AVFMT_RAWPICTURE)) { m_pVideoBuffer = (unsigned char*)(av_malloc(VIDEO_BUFFER_SIZE)); } if (!(m_pOutputFormat->flags & AVFMT_NOFILE)) { #if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(53, 8, 0) int retVal = avio_open(&m_pOutputFormatContext->pb, m_sFilename.c_str(), URL_WRONLY); #else int retVal = url_fopen(&m_pOutputFormatContext->pb, m_sFilename.c_str(), URL_WRONLY); #endif if (retVal < 0) { throw Exception(AVG_ERR_VIDEO_INIT_FAILED, string("Could not open output file: '") + m_sFilename + "'"); } } m_pFrameConversionContext = sws_getContext(m_Size.x, m_Size.y, ::PIX_FMT_RGB32, m_Size.x, m_Size.y, STREAM_PIXEL_FORMAT, SWS_BILINEAR, NULL, NULL, NULL); m_pConvertedFrame = createFrame(STREAM_PIXEL_FORMAT, m_Size); #if LIBAVFORMAT_VERSION_MAJOR > 52 avformat_write_header(m_pOutputFormatContext, 0); #else av_write_header(m_pOutputFormatContext); #endif }