]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/avcodec.c
avcodec/avcodec: Use avcodec_close() on avcodec_open2() failure
[ffmpeg] / libavcodec / avcodec.c
index a3858213759ab2bc5c6972517e4d15cbb64d2ec7..882700f357a01b969e20d273f1993c1c35139730 100644 (file)
@@ -135,7 +135,6 @@ static int64_t get_bit_rate(AVCodecContext *ctx)
 int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
 {
     int ret = 0;
-    int codec_init_ok = 0;
     AVDictionary *tmp = NULL;
     AVCodecInternal *avci;
 
@@ -320,14 +319,16 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
     if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS))
         avctx->thread_count = 1;
 
-    if (   avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME)
-        || avci->frame_thread_encoder)) {
-        ret = avctx->codec->init(avctx);
-        if (ret < 0) {
-            codec_init_ok = -1;
-            goto free_and_end;
+    if (!(avctx->active_thread_type & FF_THREAD_FRAME) ||
+        avci->frame_thread_encoder) {
+        if (avctx->codec->init) {
+            ret = avctx->codec->init(avctx);
+            if (ret < 0) {
+                avci->needs_close = avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP;
+                goto free_and_end;
+            }
         }
-        codec_init_ok = 1;
+        avci->needs_close = 1;
     }
 
     ret=0;
@@ -378,41 +379,8 @@ end:
 
     return ret;
 free_and_end:
-    if (avctx->codec && avctx->codec->close &&
-        (codec_init_ok > 0 || (codec_init_ok < 0 &&
-         avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP)))
-        avctx->codec->close(avctx);
-
-    if (HAVE_THREADS && avci->thread_ctx)
-        ff_thread_free(avctx);
-
-    if (codec->priv_class && avctx->priv_data)
-        av_opt_free(avctx->priv_data);
-    av_opt_free(avctx);
-
-    if (av_codec_is_encoder(avctx->codec)) {
-        av_freep(&avctx->extradata);
-        avctx->extradata_size = 0;
-    }
-
+    avcodec_close(avctx);
     av_dict_free(&tmp);
-    av_freep(&avctx->priv_data);
-    if (av_codec_is_decoder(avctx->codec))
-        av_freep(&avctx->subtitle_header);
-
-    av_frame_free(&avci->buffer_frame);
-    av_packet_free(&avci->buffer_pkt);
-    av_packet_free(&avci->last_pkt_props);
-    av_fifo_freep(&avci->pkt_props);
-
-    av_packet_free(&avci->ds.in_pkt);
-    av_frame_free(&avci->es.in_frame);
-    av_bsf_free(&avci->bsf);
-
-    av_buffer_unref(&avci->pool);
-    av_freep(&avci);
-    avctx->internal = NULL;
-    avctx->codec = NULL;
     goto end;
 }
 
@@ -500,20 +468,21 @@ av_cold int avcodec_close(AVCodecContext *avctx)
         }
         if (HAVE_THREADS && avci->thread_ctx)
             ff_thread_free(avctx);
-        if (avctx->codec && avctx->codec->close)
+        if (avci->needs_close && avctx->codec->close)
             avctx->codec->close(avctx);
         avci->byte_buffer_size = 0;
         av_freep(&avci->byte_buffer);
         av_frame_free(&avci->buffer_frame);
         av_packet_free(&avci->buffer_pkt);
-        av_packet_unref(avci->last_pkt_props);
-        while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) {
-            av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props,
-                                 sizeof(*avci->last_pkt_props), NULL);
-            av_packet_unref(avci->last_pkt_props);
+        if (avci->pkt_props) {
+            while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) {
+                av_packet_unref(avci->last_pkt_props);
+                av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props,
+                                     sizeof(*avci->last_pkt_props), NULL);
+            }
+            av_fifo_freep(&avci->pkt_props);
         }
         av_packet_free(&avci->last_pkt_props);
-        av_fifo_freep(&avci->pkt_props);
 
         av_packet_free(&avci->ds.in_pkt);
         av_frame_free(&avci->es.in_frame);
@@ -543,6 +512,7 @@ av_cold int avcodec_close(AVCodecContext *avctx)
     av_freep(&avctx->priv_data);
     if (av_codec_is_encoder(avctx->codec)) {
         av_freep(&avctx->extradata);
+        avctx->extradata_size = 0;
     } else if (av_codec_is_decoder(avctx->codec))
         av_freep(&avctx->subtitle_header);