add libdav1d codec, add remap_a/v_codec option keywords
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / ffmpeg.C
index 9569de77efcd11c0979e0c2f6d93c4adf1c2cb86..6d1f535b28f108c03fe0f836bf3773d3d6eb16eb 100644 (file)
@@ -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,",
@@ -1546,6 +1561,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 +2008,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 +2063,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") )