ffmpeg scan remap fix, configure.ac all or none fix, 3rd party libs: ffmpeg, turbo...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / ffmpeg.C
index 485385b4138bffd4cd822551766a8506521c9b96..5ff87abc9779a9428d26d69bca3601da3718a13b 100644 (file)
@@ -285,6 +285,7 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx)
 
 FFStream::~FFStream()
 {
+       frm_lock->lock("FFStream::~FFStream");
        if( reading > 0 || writing > 0 ) avcodec_close(avctx);
        if( avctx ) avcodec_free_context(&avctx);
        if( fmt_ctx ) avformat_close_input(&fmt_ctx);
@@ -295,6 +296,7 @@ FFStream::~FFStream()
        if( frame ) av_frame_free(&frame);
        if( fframe ) av_frame_free(&fframe);
        if( probe_frame ) av_frame_free(&probe_frame);
+       frm_lock->unlock();
        delete frm_lock;
        if( stats_fp ) fclose(stats_fp);
        if( stats_in ) av_freep(&stats_in);
@@ -421,7 +423,6 @@ int FFStream::decode_activate()
                        }
                        if( ret >= 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
                                ret = decode_hw_format(decoder, hw_type);
-                               if( !ret ) hw_type = AV_HWDEVICE_TYPE_NONE;
                        }
                        if( ret >= 0 ) {
                                avcodec_parameters_to_context(avctx, st->codecpar);
@@ -429,36 +430,35 @@ int FFStream::decode_activate()
                                        avctx->thread_count = ffmpeg->ff_cpus();
                                ret = avcodec_open2(avctx, decoder, &copts);
                        }
+                       AVFrame *hw_frame = 0;
                        if( ret >= 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
-                               AVFrame *frame = av_frame_alloc();
-                               if( !frame ) {
+                               if( !(hw_frame=av_frame_alloc()) ) {
                                        fprintf(stderr, "FFStream::decode_activate: av_frame_alloc failed\n");
                                        ret = AVERROR(ENOMEM);
                                }
                                if( ret >= 0 )
-                                       ret = decode(frame);
-                               if( ret < 0 || hw_pix_fmt == AV_PIX_FMT_NONE ) {
-                                       ff_err(ret, "HW device init failed, using SW decode.\nfile:%s\n",
-                                               ffmpeg->fmt_ctx->url);
-                                       avcodec_close(avctx);
-                                       avcodec_free_context(&avctx);
-                                       av_buffer_unref(&hw_device_ctx);
-                                       hw_device_ctx = 0;
-                                       av_frame_free(&frame);
-                                       hw_type = AV_HWDEVICE_TYPE_NONE;
-                                       int flags = AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY;
-                                       int idx = st->index;
-                                       av_seek_frame(fmt_ctx, idx, INT64_MIN, flags);
-                                       need_packet = 1;  flushed = 0;
-                                       seeked = 1;  st_eof(0);
-                                       ret = 0;
-                                       continue;
-                               }
-                               probe_frame = frame;
+                                       ret = decode(hw_frame);
                        }
-                       if( ret >= 0 ) {
-                               reading = 1;
+                       if( ret < 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
+                               ff_err(ret, "HW device init failed, using SW decode.\nfile:%s\n",
+                                       ffmpeg->fmt_ctx->url);
+                               avcodec_close(avctx);
+                               avcodec_free_context(&avctx);
+                               av_buffer_unref(&hw_device_ctx);
+                               hw_device_ctx = 0;
+                               av_frame_free(&hw_frame);
+                               hw_type = AV_HWDEVICE_TYPE_NONE;
+                               int flags = AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY;
+                               int idx = st->index;
+                               av_seek_frame(fmt_ctx, idx, 0, flags);
+                               need_packet = 1;  flushed = 0;
+                               seeked = 1;  st_eof(0);
+                               ret = 0;
+                               continue;
                        }
+                       probe_frame = hw_frame;
+                       if( ret >= 0 )
+                               reading = 1;
                        else
                                eprintf(_("open decoder failed\n"));
                }
@@ -493,7 +493,7 @@ int FFStream::decode(AVFrame *frame)
        }
        int ret = 0;
        int retries = MAX_RETRY;
-
+       frm_lock->lock("FFStream::decode");
        while( ret >= 0 && !flushed && --retries >= 0 ) {
                if( need_packet ) {
                        if( (ret=read_packet()) < 0 ) break;
@@ -516,6 +516,7 @@ int FFStream::decode(AVFrame *frame)
                        flushed = st_eof();
                }
        }
+       frm_lock->unlock();
 
        if( retries < 0 ) {
                fprintf(stderr, "FFStream::decode: Retry limit\n");
@@ -728,6 +729,7 @@ int FFStream::seek(int64_t no, double rate)
        tstmp = av_rescale_q(tstmp, time_base, AV_TIME_BASE_Q);
        idx = -1;
 #endif
+       frm_lock->lock("FFStream::seek");
        av_frame_free(&probe_frame);
        avcodec_flush_buffers(avctx);
        avformat_flush(fmt_ctx);
@@ -760,7 +762,9 @@ int FFStream::seek(int64_t no, double rate)
                        if( pkt_ts >= tstmp ) break;
                }
                if( retry < 0 ) {
-                       fprintf(stderr,"FFStream::seek: retry limit, pos=%jd tstmp=%jd\n",pos,tstmp);
+                       ff_err(AVERROR(EIO), "FFStream::seek: %s\n"
+                               " retry limit, pos=%jd tstmp=%jd, ",
+                               ffmpeg->fmt_ctx->url, pos, tstmp);
                        ret = -1;
                }
                if( ret < 0 ) break;
@@ -774,6 +778,7 @@ int FFStream::seek(int64_t no, double rate)
                        break;
                }
        }
+       frm_lock->unlock();
        if( ret < 0 ) {
 printf("** seek fail %jd, %jd\n", pos, tstmp);
                seeked = need_packet = 0;
@@ -1088,6 +1093,7 @@ int FFVideoStream::decode_hw_format(AVCodec *decoder, AVHWDeviceType type)
                if( !config ) {
                        fprintf(stderr, "Decoder %s does not support device type %s.\n",
                                decoder->name, av_hwdevice_get_type_name(type));
+                       ret = -1;
                        break;
                }
                if( (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) != 0 &&
@@ -1104,9 +1110,11 @@ int FFVideoStream::decode_hw_format(AVCodec *decoder, AVHWDeviceType type)
                        avctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
                        ret = 1;
                }
-               else
+               else {
                        ff_err(ret, "Failed HW device create.\ndev:%s\n",
                                av_hwdevice_get_type_name(type));
+                       ret = -1;
+               }
        }
        return ret;
 }
@@ -2973,7 +2981,20 @@ int FFMPEG::encode_activate()
                                fmt_ctx->url);
                        return -1;
                }
-
+               if( !strcmp(file_format, "image2") ) {
+                       Asset *asset = file_base->asset;
+                       const char *filename = asset->path;
+                       FILE *fp = fopen(filename,"w");
+                       if( !fp ) {
+                               eprintf(_("Cant write image2 header file: %s\n  %m"), filename);
+                               return 1;
+                       }
+                       fprintf(fp, "IMAGE2\n");
+                       fprintf(fp, "# Frame rate: %f\n", asset->frame_rate);
+                       fprintf(fp, "# Width: %d\n", asset->width);
+                       fprintf(fp, "# Height: %d\n", asset->height);
+                       fclose(fp);
+               }
                int prog_id = 1;
                AVProgram *prog = av_new_program(fmt_ctx, prog_id);
                for( int i=0; i< ffvideo.size(); ++i )
@@ -3520,7 +3541,25 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled)
                av_dict_copy(&copts, opts, 0);
                AVStream *st = fmt_ctx->streams[i];
                AVCodecID codec_id = st->codecpar->codec_id;
-               AVCodec *decoder = avcodec_find_decoder(codec_id);
+               AVCodec *decoder = 0;
+               switch( st->codecpar->codec_type ) {
+               case AVMEDIA_TYPE_VIDEO:
+                       if( opt_video_decoder )
+                               decoder = avcodec_find_decoder_by_name(opt_video_decoder);
+                       else
+                               video_codec_remaps.update(codec_id, decoder);
+                       break;
+               case AVMEDIA_TYPE_AUDIO:
+                       if( opt_audio_decoder )
+                               decoder = avcodec_find_decoder_by_name(opt_audio_decoder);
+                       else
+                               audio_codec_remaps.update(codec_id, decoder);
+                       break;
+               default:
+                       continue;
+               }
+               if( !decoder && !(decoder = avcodec_find_decoder(codec_id)) )
+                       continue;
                AVCodecContext *avctx = avcodec_alloc_context3(decoder);
                if( !avctx ) {
                        eprintf(_("cant allocate codec context\n"));
@@ -3601,8 +3640,8 @@ int FFMPEG::scan(IndexState *index_state, int64_t *scan_position, int *canceled)
                        if( vidx < 0 ) break;
                        FFVideoStream *vid = ffvideo[vidx];
                        if( !vid->avctx ) break;
-                       int64_t tstmp = pkt.dts;
-                       if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.pts;
+                       int64_t tstmp = pkt.pts;
+                       if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.dts;
                        if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) {
                                if( vid->nudge != AV_NOPTS_VALUE ) tstmp -= vid->nudge;
                                double secs = to_secs(tstmp, st->time_base);