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 8b9cc27fe5585d70fa522c8a7cd580c47a243331..5ff87abc9779a9428d26d69bca3601da3718a13b 100644 (file)
@@ -275,6 +275,7 @@ FFStream::FFStream(FFMPEG *ffmpeg, AVStream *st, int fidx)
        flushed = 0;
        need_packet = 1;
        frame = fframe = 0;
+       probe_frame = 0;
        bsfc = 0;
        stats_fp = 0;
        stats_filename = 0;
@@ -284,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);
@@ -293,6 +295,8 @@ FFStream::~FFStream()
        if( filter_graph ) avfilter_graph_free(&filter_graph);
        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);
@@ -419,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);
@@ -427,35 +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 ) {
-                               if( need_packet ) {
-                                       need_packet = 0;
-                                       ret = read_packet();
-                               }
-                               if( ret >= 0 ) {
-                                       AVPacket *pkt = (AVPacket*)ipkt;
-                                       ret = avcodec_send_packet(avctx, pkt);
-                                       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;
-                                               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;
-                                       }
+                               if( !(hw_frame=av_frame_alloc()) ) {
+                                       fprintf(stderr, "FFStream::decode_activate: av_frame_alloc failed\n");
+                                       ret = AVERROR(ENOMEM);
                                }
+                               if( ret >= 0 )
+                                       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"));
                }
@@ -483,9 +486,14 @@ int FFStream::read_packet()
 
 int FFStream::decode(AVFrame *frame)
 {
+       if( probe_frame ) { // hw probe reads first frame
+               av_frame_ref(frame, probe_frame);
+               av_frame_free(&probe_frame);
+               return 1;
+       }
        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;
@@ -508,6 +516,7 @@ int FFStream::decode(AVFrame *frame)
                        flushed = st_eof();
                }
        }
+       frm_lock->unlock();
 
        if( retries < 0 ) {
                fprintf(stderr, "FFStream::decode: Retry limit\n");
@@ -720,7 +729,8 @@ 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);
 #if 0
@@ -752,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;
@@ -766,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;
@@ -1080,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 &&
@@ -1096,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;
 }
@@ -2965,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 )
@@ -3318,7 +3347,7 @@ float FFMPEG::ff_aspect_ratio(int stream)
        return ffvideo[stream]->aspect_ratio;
 }
 
-const char* FFMPEG::ff_video_format(int stream)
+const char* FFMPEG::ff_video_codec(int stream)
 {
        AVStream *st = ffvideo[stream]->st;
        AVCodecID id = st->codecpar->codec_id;
@@ -3512,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"));
@@ -3593,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);