X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fffmpeg.C;h=794added52ba6e9519ccd06f45f96dec2ad6de0f;hp=9569de77efcd11c0979e0c2f6d93c4adf1c2cb86;hb=120f82197b4bdfdad9a5a666d773b45a8064d049;hpb=9c8644d5f3f05b52a81c259c32217bcd57792ae5 diff --git a/cinelerra-5.1/cinelerra/ffmpeg.C b/cinelerra-5.1/cinelerra/ffmpeg.C index 9569de77..794added 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); @@ -1016,7 +1031,8 @@ AVHWDeviceType FFVideoStream::decode_hw_activate() const char *hw_dev = ffmpeg->opt_hw_dev; if( !hw_dev ) hw_dev = getenv("CIN_HW_DEV"); if( !hw_dev ) hw_dev = ffmpeg->ff_hw_dev(); - if( hw_dev && *hw_dev && strcmp(_("none"), hw_dev) ) { + if( hw_dev && *hw_dev && + strcmp("none", hw_dev) && strcmp(_("none"), hw_dev) ) { type = av_hwdevice_find_type_by_name(hw_dev); if( type == AV_HWDEVICE_TYPE_NONE ) { fprintf(stderr, "Device type %s is not supported.\n", hw_dev); @@ -1135,7 +1151,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 +1253,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 +1582,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 +2029,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 +2084,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") ) @@ -2287,7 +2372,7 @@ int FFMPEG::open_decoder() } if( bad_time && !(fflags & FF_BAD_TIMES) ) { fflags |= FF_BAD_TIMES; - printf("FFMPEG::open_decoder: some stream have bad times: %s\n", + printf(_("FFMPEG::open_decoder: some stream have bad times: %s\n"), fmt_ctx->url); } ff_unlock();