TuttleOFX
1
|
00001 #include "LibAVVideoWriter.hpp" 00002 #include "LibAVPreset.hpp" 00003 #include "LibAVFormatPreset.hpp" 00004 00005 #include <tuttle/plugin/global.hpp> 00006 #include <tuttle/plugin/exceptions.hpp> 00007 00008 #include <boost/foreach.hpp> 00009 00010 #include <cstdio> 00011 00012 00013 namespace tuttle { 00014 namespace plugin { 00015 namespace av { 00016 00017 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT( 52, 40, 0 ) 00018 // compatibility with previous versions of libavformat 00019 #define av_guess_format guess_format 00020 #endif 00021 00022 #ifdef _MSC_VER 00023 #define snprintf _snprintf 00024 #endif 00025 00026 static boost::int64_t pts = 0; 00027 00028 LibAVVideoWriter::LibAVVideoWriter() 00029 : LibAV() 00030 , _avFormatOptions ( NULL ) 00031 , _stream ( NULL ) 00032 , _avVideoOptions ( NULL ) 00033 , _avAudioOptions ( NULL ) 00034 , _sws_context ( NULL ) 00035 , _videoCodec ( NULL ) 00036 , _audioCodec ( NULL ) 00037 , _ofmt ( NULL ) 00038 , _statusCode ( eWriterStatusIgnoreFinish ) 00039 , _filename ( "" ) 00040 , _width ( 0 ) 00041 , _height ( 0 ) 00042 , _aspectRatio ( 1 ) 00043 , _out_pixelFormat ( PIX_FMT_YUV420P ) 00044 , _fps ( 25.0f ) 00045 , _formatName ( "" ) 00046 , _videoCodecName ( "" ) 00047 , _audioCodecName ( "" ) 00048 { 00049 AVOutputFormat* fmt = av_oformat_next( NULL ); 00050 00051 while( fmt ) 00052 { 00053 // add only format with video track 00054 if( fmt->video_codec != AV_CODEC_ID_NONE ) 00055 { 00056 if( fmt->long_name ) 00057 { 00058 _formatsLongNames.push_back( std::string( fmt->long_name ) + std::string( " (" ) + std::string( fmt->name ) + std::string( ")" ) ); 00059 _formatsShortNames.push_back( std::string( fmt->name ) ); 00060 } 00061 if( fmt->priv_class ) 00062 { 00063 const AVOption *o = NULL; 00064 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 51, 12, 0 ) 00065 while( ( o = av_next_option( &fmt->priv_class, o ) ) ) 00066 #else 00067 while( ( o = av_opt_next( &fmt->priv_class, o ) ) ) 00068 #endif 00069 { 00070 AVPrivOption avprivopt; 00071 avprivopt.o = *o; 00072 avprivopt.class_name = std::string( fmt->name ); 00073 _formatPrivOpts.push_back( avprivopt ); 00074 } 00075 } 00076 } 00077 fmt = av_oformat_next( fmt ); 00078 } 00079 00080 AVCodec* c = NULL; 00081 while( ( c = av_codec_next( c ) ) ) 00082 { 00083 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 53, 34, 0 ) 00084 if( c->encode2 ) 00085 #else 00086 if( c->encode ) 00087 #endif 00088 { 00089 switch( c->type ) 00090 { 00091 case AVMEDIA_TYPE_VIDEO: 00092 { 00093 if( c->long_name ) 00094 { 00095 _videoCodecsLongNames.push_back( std::string( c->long_name ) ); 00096 _videoCodecsShortNames.push_back( std::string( c->name ) ); 00097 } 00098 if( c->priv_class ) 00099 { 00100 const AVOption *o = NULL; 00101 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 51, 12, 0 ) 00102 while( ( o = av_next_option( &c->priv_class, o ) ) ) 00103 #else 00104 while( ( o = av_opt_next( &c->priv_class, o ) ) ) 00105 #endif 00106 { 00107 AVPrivOption avprivopt; 00108 avprivopt.o = *o; 00109 avprivopt.class_name = std::string( c->name ); 00110 _videoCodecPrivOpts.push_back( avprivopt ); 00111 } 00112 } 00113 break; 00114 } 00115 case AVMEDIA_TYPE_AUDIO: 00116 { 00117 if( c->long_name ) 00118 { 00119 _audioCodecsLongNames.push_back( std::string( c->long_name ) ); 00120 _audioCodecsShortNames.push_back( std::string( c->name ) ); 00121 } 00122 if( c->priv_class ) 00123 { 00124 const AVOption *o = NULL; 00125 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 51, 12, 0 ) 00126 while( ( o = av_next_option( &c->priv_class, o ) ) ) 00127 #else 00128 while( ( o = av_opt_next( &c->priv_class, o ) ) ) 00129 #endif 00130 { 00131 AVPrivOption avprivopt; 00132 avprivopt.o = *o; 00133 avprivopt.class_name = std::string( c->name ); 00134 _audioCodecPrivOpts.push_back( avprivopt ); 00135 } 00136 } 00137 break; 00138 } 00139 default: 00140 break; 00141 } 00142 } 00143 } 00144 00145 } 00146 00147 int LibAVVideoWriter::start( ) 00148 { 00149 if( !_avFormatOptions ) 00150 { 00151 _avFormatOptions = avformat_alloc_context(); 00152 _ofmt = NULL; 00153 00154 const char* filename = getFilename().c_str(); 00155 00156 if( !_avFormatOptions ) 00157 { 00158 TUTTLE_LOG_ERROR( "avWriter: format context allocation failed" ); 00159 return false; 00160 } 00161 00162 if( !_formatName.empty() ) 00163 { 00164 _ofmt = av_guess_format( _formatName.c_str(), NULL, NULL ); 00165 if (!_ofmt) 00166 { 00167 TUTTLE_LOG_ERROR( "avWriter: Requested output format " << _formatName << " is not a suitable output format" ); 00168 return false; 00169 } 00170 } 00171 else 00172 { 00173 _ofmt = av_guess_format( NULL, filename, NULL ); 00174 if (!_ofmt) 00175 { 00176 TUTTLE_LOG_ERROR( "avWriter: Unable to find a suitable output format for " << filename ); 00177 return false; 00178 } 00179 } 00180 00181 _avFormatOptions->oformat = _ofmt; 00182 if( _avFormatOptions->oformat->priv_data_size > 0 ) 00183 { 00184 _avFormatOptions->priv_data = av_mallocz( _avFormatOptions->oformat->priv_data_size ); 00185 if( !_avFormatOptions->priv_data ) 00186 { 00187 TUTTLE_LOG_ERROR( "avWriter: format context allocation failed" ); 00188 return false; 00189 } 00190 if( _avFormatOptions->oformat->priv_class ) 00191 { 00192 *(const AVClass**)_avFormatOptions->priv_data= _avFormatOptions->oformat->priv_class; 00193 av_opt_set_defaults( _avFormatOptions->priv_data ); 00194 } 00195 } 00196 else 00197 _avFormatOptions->priv_data = NULL; 00198 00199 if( filename ) 00200 av_strlcpy( _avFormatOptions->filename, filename, sizeof( _avFormatOptions->filename ) ); 00201 00202 TUTTLE_LOG_TRACE( "avWriter: " << std::string( _ofmt->name ) << " format selected" ); 00203 } 00204 00205 if( !_stream ) 00206 { 00207 _videoCodec = avcodec_find_encoder_by_name( _videoCodecName.c_str() ); 00208 if (!_videoCodec) 00209 { 00210 BOOST_THROW_EXCEPTION( exception::Format() 00211 << exception::user( "avWriter: codec not found." ) ); 00212 } 00213 TUTTLE_LOG_TRACE( "avWriter: " << std::string(_videoCodec->name) << " codec selected" ); 00214 00215 _avVideoOptions = avcodec_alloc_context3( _videoCodec ); 00216 00217 _stream = avformat_new_stream( _avFormatOptions, _videoCodec ); 00218 if( !_stream ) 00219 { 00220 BOOST_THROW_EXCEPTION( exception::File() 00221 << exception::user( "avWriter: out of memory." ) ); 00222 } 00223 avcodec_get_context_defaults3(_stream->codec, _videoCodec); 00224 00225 // TUTTLE_LOG_VAR2( TUTTLE_INFO, _videoCodecName, _videoPresetName ); 00226 00227 _stream->codec->width = getWidth(); 00228 _stream->codec->height = getHeight(); 00229 _stream->codec->time_base = av_inv_q( av_d2q( _fps, INT_MAX ) ); 00230 //TUTTLE_LOG_VAR( TUTTLE_INFO, _fps ); 00231 //TUTTLE_LOG_VAR2( TUTTLE_INFO, _stream->codec->time_base.num, _stream->codec->time_base.den ); 00232 00233 _stream->codec->sample_rate = 48000; ///< samples per second 00234 _stream->codec->channels = 0; ///< number of audio channels 00235 } 00236 return true; 00237 } 00238 00239 bool LibAVVideoWriter::finishInit() 00240 { 00241 int pixfmt_allowed = 0, k; 00242 if ( _videoCodec->pix_fmts ) 00243 { 00244 for ( k = 0; _videoCodec->pix_fmts[k] != PIX_FMT_NONE; k++ ) 00245 { 00246 if ( _videoCodec->pix_fmts[k] == _out_pixelFormat ) 00247 { 00248 pixfmt_allowed = 1; 00249 break; 00250 } 00251 } 00252 } 00253 else 00254 { 00255 // If a codec does not contain a list of supported pixel 00256 // formats, just assume that _out_PixelFormat is valid 00257 pixfmt_allowed = 1; 00258 } 00259 00260 if ( !pixfmt_allowed ) 00261 { 00262 // av_get_pix_fmt_name requires lavu 51.3.0 or higher 00263 TUTTLE_LOG_ERROR( "avWriter: pixel format " << av_get_pix_fmt_name(_out_pixelFormat) << " not available in codec" ); 00264 _out_pixelFormat = _videoCodec->pix_fmts[0]; 00265 TUTTLE_LOG_ERROR( "avWriter: auto-selecting " << av_get_pix_fmt_name(_out_pixelFormat) ); 00266 } 00267 _stream->codec->pix_fmt = _out_pixelFormat; 00268 00269 if( !strcmp( _avFormatOptions->oformat->name, "mp4" ) || !strcmp( _avFormatOptions->oformat->name, "mov" ) || !strcmp( _avFormatOptions->oformat->name, "3gp" ) || !strcmp( _avFormatOptions->oformat->name, "flv" ) ) 00270 _stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; 00271 00272 av_dump_format( _avFormatOptions, 0, getFilename().c_str(), 1 ); 00273 00274 if( avcodec_open2( _stream->codec, _videoCodec, NULL ) < 0 ) 00275 { 00276 freeFormat(); 00277 BOOST_THROW_EXCEPTION( exception::Format() 00278 << exception::user( "avWriter: unable to open codec." ) ); 00279 return false; 00280 } 00281 00282 if( !( _ofmt->flags & AVFMT_NOFILE ) ) 00283 { 00284 if( avio_open2( &_avFormatOptions->pb, getFilename().c_str(), 00285 AVIO_FLAG_WRITE, NULL, NULL ) < 0 ) 00286 { 00287 freeFormat(); 00288 BOOST_THROW_EXCEPTION( exception::FileNotExist() 00289 << exception::user( "avWriter: unable to open file." ) ); 00290 } 00291 } 00292 00293 int error = avformat_write_header( _avFormatOptions, NULL ); 00294 if( error ) 00295 { 00296 TUTTLE_LOG_ERROR( libavError_toString( error) ); 00297 BOOST_THROW_EXCEPTION( exception::Format() 00298 << exception::user( "avWriter: unable to write header." ) ); 00299 } 00300 return true; 00301 } 00302 00303 std::string LibAVVideoWriter::getErrorStr( const int errnum ) const 00304 { 00305 static const std::size_t errbuf_size = 2048; 00306 char errbuf[errbuf_size]; 00307 av_strerror( errnum, errbuf, errbuf_size ); 00308 return std::string( errbuf ); 00309 } 00310 00311 int LibAVVideoWriter::execute( boost::uint8_t* const in_buffer, const int in_width, const int in_height, const PixelFormat in_pixelFormat ) 00312 { 00313 _statusCode = eWriterStatusIgnoreFinish; 00314 00315 _statusCode = eWriterStatusCleanup; 00316 00317 AVFrame* in_frame = avcodec_alloc_frame(); 00318 avcodec_get_frame_defaults( in_frame ); 00319 avpicture_fill( (AVPicture*)in_frame, in_buffer, in_pixelFormat, in_width, in_height ); 00320 00321 AVFrame* out_frame = avcodec_alloc_frame(); 00322 avcodec_get_frame_defaults( out_frame ); 00323 int out_picSize = avpicture_get_size( _out_pixelFormat, getWidth(), getHeight() ); 00324 boost::uint8_t* out_buffer = (boost::uint8_t*) av_malloc( out_picSize ); 00325 avpicture_fill( (AVPicture*) out_frame, out_buffer, _out_pixelFormat, getWidth(), getHeight() ); 00326 00327 _sws_context = sws_getCachedContext( _sws_context, in_width, in_height, in_pixelFormat, getWidth(), getHeight(), _out_pixelFormat, SWS_BICUBIC, NULL, NULL, NULL ); 00328 00329 TUTTLE_TLOG( TUTTLE_TRACE, "avWriter: input format: " << av_get_pix_fmt_name( in_pixelFormat ) << " -> output format: " << av_get_pix_fmt_name( _out_pixelFormat ) ); 00330 00331 if( !_sws_context ) 00332 { 00333 BOOST_THROW_EXCEPTION( exception::Failed() 00334 << exception::user() + "libav-conversion failed (" + in_pixelFormat + "->" + _out_pixelFormat + ")." ); 00335 } 00336 const int error = sws_scale( _sws_context, in_frame->data, in_frame->linesize, 0, getHeight(), out_frame->data, out_frame->linesize ); 00337 if( error < 0 ) 00338 { 00339 BOOST_THROW_EXCEPTION( exception::Failed() 00340 << exception::user() + "libav-conversion failed (" + in_pixelFormat + "->" + _out_pixelFormat + ")." ); 00341 } 00342 00343 int ret = 0; 00344 if( ( _avFormatOptions->oformat->flags & AVFMT_RAWPICTURE ) && 00345 ( _stream->codec->codec->id == AV_CODEC_ID_RAWVIDEO ) ) 00346 { 00347 //TUTTLE_TLOG( TUTTLE_TRACE, "RAW : " << sizeof( AVPicture ) ); 00348 AVPacket pkt; 00349 av_init_packet( &pkt ); 00350 pkt.data = (boost::uint8_t*) out_frame; 00351 pkt.size = sizeof( AVPicture ); 00352 pkt.pts = av_rescale_q(out_frame->pts, _stream->codec->time_base, _stream->time_base); 00353 pkt.stream_index = _stream->index; 00354 pkt.flags |= AV_PKT_FLAG_KEY; 00355 00356 ret = av_interleaved_write_frame( _avFormatOptions, &pkt ); 00357 if ( ret < 0 ) 00358 { 00359 BOOST_THROW_EXCEPTION( exception::File() 00360 << exception::user( "avWriter: error writing packet to file" ) ); 00361 } 00362 } 00363 else 00364 { 00365 AVPacket pkt; 00366 _hasFrame = 0; 00367 av_init_packet( &pkt ); 00368 pkt.size = 0; 00369 pkt.data = NULL; 00370 pkt.stream_index = _stream->index; 00371 00372 if( ( _stream->codec->coded_frame ) && 00373 ( _stream->codec->coded_frame->pts != static_cast<boost::int64_t>( AV_NOPTS_VALUE ) ) ) 00374 { 00375 pkt.pts = av_rescale_q( _stream->codec->coded_frame->pts, _stream->codec->time_base, _stream->time_base ); 00376 TUTTLE_TLOG( TUTTLE_TRACE, "avWriter: Video Frame PTS: " << pkt.pts ); 00377 } 00378 else 00379 { 00380 TUTTLE_TLOG( TUTTLE_TRACE, "avWriter: Video Frame PTS: not set" ); 00381 } 00382 if( _stream->codec->coded_frame && 00383 _stream->codec->coded_frame->key_frame ) 00384 { 00385 pkt.flags |= AV_PKT_FLAG_KEY; 00386 } 00387 00388 out_frame->pts = pts; 00389 out_frame->quality = _stream->codec->global_quality; 00390 pts += _stream->codec->time_base.num; 00391 ret = avcodec_encode_video2( _stream->codec, &pkt, out_frame, &_hasFrame ); 00392 if( ret < 0 ) 00393 { 00394 TUTTLE_LOG_ERROR( "avWriter: error writing packet to file" ); 00395 TUTTLE_LOG_ERROR( getErrorStr(ret) ); 00396 return false; 00397 } 00398 00399 00400 if( _hasFrame ) 00401 { 00402 ret = av_interleaved_write_frame( _avFormatOptions, &pkt ); 00403 if ( ret < 0 ) 00404 { 00405 BOOST_THROW_EXCEPTION( exception::File() 00406 << exception::user( "avWriter: error writing packet to file" ) ); 00407 } 00408 } 00409 } 00410 00411 av_free( out_buffer ); 00412 av_free( out_frame ); 00413 av_free( in_frame ); 00414 // in_buffer not free (function parameter) 00415 00416 if( ret < 0 ) 00417 { 00418 BOOST_THROW_EXCEPTION( exception::File() 00419 << exception::user( "avWriter: error writing frame to file." ) ); 00420 } 00421 00422 _statusCode = eWriterStatusSuccess; 00423 return true; 00424 } 00425 00426 void LibAVVideoWriter::finish() 00427 { 00428 if( _statusCode == eWriterStatusIgnoreFinish ) 00429 return; 00430 00431 int ret = 0; 00432 00433 for( _hasFrame = 1; _hasFrame; ) 00434 { 00435 TUTTLE_TLOG( TUTTLE_TRACE, "encode last frames ..." ); 00436 AVPacket pkt; 00437 av_init_packet( &pkt ); 00438 pkt.size = 0; 00439 pkt.data = NULL; 00440 pkt.stream_index = _stream->index; 00441 00442 00443 ret = avcodec_encode_video2( _stream->codec, &pkt, NULL, &_hasFrame ); 00444 if( ret < 0 ) 00445 { 00446 TUTTLE_LOG_ERROR( "avWriter: error writing packet to file" ); 00447 TUTTLE_LOG_ERROR( getErrorStr(ret) ); 00448 break; 00449 } 00450 00451 if( _hasFrame ) 00452 { 00453 TUTTLE_LOG_ERROR( "write packet" ); 00454 ret = av_interleaved_write_frame( _avFormatOptions, &pkt ); 00455 if ( ret < 0 ) 00456 { 00457 BOOST_THROW_EXCEPTION( exception::File() 00458 << exception::user( "avWriter: error writing packet to file" ) ); 00459 } 00460 av_free_packet( &pkt ); 00461 } 00462 } 00463 00464 av_write_trailer( _avFormatOptions ); 00465 avcodec_close( _stream->codec ); 00466 if( !( _avFormatOptions->oformat->flags & AVFMT_NOFILE ) ) 00467 avio_close( _avFormatOptions->pb ); 00468 freeFormat(); 00469 00470 } 00471 00472 void LibAVVideoWriter::freeFormat() 00473 { 00474 avcodec_close( _stream->codec ); 00475 for( int i = 0; i < static_cast<int>( _avFormatOptions->nb_streams ); ++i ) 00476 av_freep( &_avFormatOptions->streams[i] ); 00477 av_free( _avFormatOptions ); 00478 _avFormatOptions = 0; 00479 _stream = 0; 00480 } 00481 00482 } 00483 } 00484 }