X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=70098ca189c5267b3aeea8bfdb9de8ea19f051ff;hp=3bb9dd8018c9075810154bf112e3843e4677dcb9;hb=cdb8b00f2f7ecf0b4910a40e1d90a87540d2891d;hpb=f890683b11652fc31712acd0d7317a1b235a314e diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 3bb9dd80..70098ca1 100644 --- a/cinelerra-5.1/cinelerra/ffmpeg.C +++ b/cinelerra-5.1/cinelerra/ffmpeg.C @@ -374,7 +374,21 @@ int FFStream::decode_activate() } while( ret >= 0 && st != 0 && !reading ) { AVCodecID codec_id = st->codecpar->codec_id; - AVCodec *decoder = avcodec_find_decoder(codec_id); + AVCodec *decoder = 0; + if( is_video() ) { + if( ffmpeg->opt_video_decoder ) + decoder = avcodec_find_decoder_by_name(ffmpeg->opt_video_decoder); + else + ffmpeg->video_codec_remaps.update(codec_id, decoder); + } + else if( is_audio() ) { + if( ffmpeg->opt_audio_decoder ) + decoder = avcodec_find_decoder_by_name(ffmpeg->opt_audio_decoder); + else + ffmpeg->audio_codec_remaps.update(codec_id, decoder); + } + if( !decoder ) + decoder = avcodec_find_decoder(codec_id); avctx = avcodec_alloc_context3(decoder); if( !avctx ) { eprintf(_("cant allocate codec context\n")); @@ -455,7 +469,7 @@ int FFStream::decode(AVFrame *frame) AVPacket *pkt = ret > 0 ? (AVPacket*)ipkt : 0; if( pkt ) { if( pkt->stream_index != st->index ) continue; - if( !pkt->data | !pkt->size ) continue; + if( !pkt->data || !pkt->size ) continue; } if( (ret=avcodec_send_packet(avctx, pkt)) < 0 ) { ff_err(ret, "FFStream::decode: avcodec_send_packet failed.\nfile:%s\n", @@ -835,7 +849,8 @@ int FFAudioStream::decode_frame(AVFrame *frame) frame->best_effort_timestamp = AV_NOPTS_VALUE; int ret = avcodec_receive_frame(avctx, frame); if( ret < 0 ) { - if( first_frame || ret == AVERROR(EAGAIN) ) return 0; + if( first_frame ) return 0; + if( ret == AVERROR(EAGAIN) ) return 0; if( ret == AVERROR_EOF ) { st_eof(1); return 0; } ff_err(ret, "FFAudioStream::decode_frame: Could not read audio frame.\nfile:%s\n", ffmpeg->fmt_ctx->url); @@ -1135,7 +1150,7 @@ int FFVideoStream::decode_frame(AVFrame *frame) int first_frame = seeked; seeked = 0; int ret = avcodec_receive_frame(avctx, frame); if( ret < 0 ) { - if( first_frame || ret == AVERROR(EAGAIN) ) return 0; + if( first_frame ) return 0; if( ret == AVERROR(EAGAIN) ) return 0; if( ret == AVERROR_EOF ) { st_eof(1); return 0; } ff_err(ret, "FFVideoStream::decode_frame: Could not read video frame.\nfile:%s\n,", @@ -1237,6 +1252,26 @@ int FFVideoStream::encode_frame(AVFrame *frame) frame->interlaced_frame = interlaced; frame->top_field_first = top_field_first; } + if( frame && frame->format == AV_PIX_FMT_VAAPI ) { // ugly + int ret = avcodec_send_frame(avctx, frame); + for( int retry=MAX_RETRY; !ret && --retry>=0; ) { + FFPacket pkt; av_init_packet(pkt); + pkt->data = NULL; pkt->size = 0; + if( (ret=avcodec_receive_packet(avctx, pkt)) < 0 ) { + if( ret == AVERROR(EAGAIN) ) ret = 0; // weird + break; + } + ret = write_packet(pkt); + pkt->stream_index = 0; + av_packet_unref(pkt); + } + if( ret < 0 ) { + ff_err(ret, "FFStream::encode_frame: vaapi encode failed.\nfile: %s\n", + ffmpeg->fmt_ctx->url); + return -1; + } + return 0; + } return FFStream::encode_frame(frame); } @@ -1546,6 +1581,8 @@ FFMPEG::FFMPEG(FileBase *file_base) opt_video_filter = 0; opt_audio_filter = 0; opt_hw_dev = 0; + opt_video_decoder = 0; + opt_audio_decoder = 0; fflags = 0; char option_path[BCTEXTLEN]; set_option_path(option_path, "%s", "ffmpeg.opts"); @@ -1991,6 +2028,45 @@ int FFMPEG::scan_options(const char *options, AVDictionary *&opts, AVStream *st) return ret; } +FFCodecRemap::FFCodecRemap() +{ + old_codec = 0; + new_codec = 0; +} +FFCodecRemap::~FFCodecRemap() +{ + delete [] old_codec; + delete [] new_codec; +} + +int FFCodecRemaps::add(const char *val) +{ + char old_codec[BCSTRLEN], new_codec[BCSTRLEN]; + if( sscanf(val, " %63[a-zA-z0-9_-] = %63[a-z0-9_-]", + &old_codec[0], &new_codec[0]) != 2 ) return 1; + FFCodecRemap &remap = append(); + remap.old_codec = cstrdup(old_codec); + remap.new_codec = cstrdup(new_codec); + return 0; +} + + +int FFCodecRemaps::update(AVCodecID &codec_id, AVCodec *&decoder) +{ + AVCodec *codec = avcodec_find_decoder(codec_id); + if( !codec ) return -1; + const char *name = codec->name; + FFCodecRemaps &map = *this; + int k = map.size(); + while( --k >= 0 && strcmp(map[k].old_codec, name) ); + if( k < 0 ) return 1; + const char *new_codec = map[k].new_codec; + codec = avcodec_find_decoder_by_name(new_codec); + if( !codec ) return -1; + decoder = codec; + return 0; +} + int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts) { int ret = 0, no = 0; @@ -2007,6 +2083,14 @@ int FFMPEG::read_options(FILE *fp, const char *options, AVDictionary *&opts) if( !ret ) { if( !strcmp(key, "duration") ) opt_duration = strtod(val, 0); + else if( !strcmp(key, "video_decoder") ) + opt_video_decoder = cstrdup(val); + else if( !strcmp(key, "audio_decoder") ) + opt_audio_decoder = cstrdup(val); + else if( !strcmp(key, "remap_video_decoder") ) + video_codec_remaps.add(val); + else if( !strcmp(key, "remap_audio_decoder") ) + audio_codec_remaps.add(val); else if( !strcmp(key, "video_filter") ) opt_video_filter = cstrdup(val); else if( !strcmp(key, "audio_filter") ) @@ -2487,7 +2571,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) vid->height = asset->height; vid->frame_rate = asset->frame_rate; - AVPixelFormat pix_fmt = AV_PIX_FMT_NONE; + AVPixelFormat pix_fmt = av_get_pix_fmt(asset->ff_pixel_format); if( opt_hw_dev != 0 ) { AVHWDeviceType hw_type = vid->encode_hw_activate(opt_hw_dev); switch( hw_type ) { @@ -2495,9 +2579,7 @@ int FFMPEG::open_encoder(const char *type, const char *spec) pix_fmt = AV_PIX_FMT_VAAPI; break; case AV_HWDEVICE_TYPE_NONE: - default: - pix_fmt = av_get_pix_fmt(asset->ff_pixel_format); - break; + default: break; } } if( pix_fmt == AV_PIX_FMT_NONE )