]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/utils.c
avcodec/utils: Use more bits for intermediate for AV_CODEC_ID_ADPCM_MS
[ffmpeg] / libavcodec / utils.c
index 008e95c2393fce63cac42cd968952f9caa96195e..66d286565b7b72b51284f6304c5960eadcd26fc1 100644 (file)
@@ -50,7 +50,6 @@
 #include "thread.h"
 #include "frame_thread_encoder.h"
 #include "internal.h"
-#include "packet_internal.h"
 #include "put_bits.h"
 #include "raw.h"
 #include "bytestream.h"
@@ -513,7 +512,14 @@ static int64_t get_bit_rate(AVCodecContext *ctx)
         break;
     case AVMEDIA_TYPE_AUDIO:
         bits_per_sample = av_get_bits_per_sample(ctx->codec_id);
-        bit_rate = bits_per_sample ? ctx->sample_rate * (int64_t)ctx->channels * bits_per_sample : ctx->bit_rate;
+        if (bits_per_sample) {
+            bit_rate = ctx->sample_rate * (int64_t)ctx->channels;
+            if (bit_rate > INT64_MAX / bits_per_sample) {
+                bit_rate = 0;
+            } else
+                bit_rate *= bits_per_sample;
+        } else
+            bit_rate = ctx->bit_rate;
         break;
     default:
         bit_rate = 0;
@@ -535,18 +541,6 @@ static void ff_unlock_avcodec(const AVCodec *codec)
         ff_mutex_unlock(&codec_mutex);
 }
 
-int attribute_align_arg ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
-{
-    int ret = 0;
-
-    ff_unlock_avcodec(codec);
-
-    ret = avcodec_open2(avctx, codec, options);
-
-    ff_lock_avcodec(avctx, codec);
-    return ret;
-}
-
 int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
 {
     int ret = 0;
@@ -585,18 +579,24 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
     }
     avctx->internal = avci;
 
+#if FF_API_OLD_ENCDEC
     avci->to_free = av_frame_alloc();
     avci->compat_decode_frame = av_frame_alloc();
     avci->compat_encode_packet = av_packet_alloc();
+    if (!avci->to_free || !avci->compat_decode_frame || !avci->compat_encode_packet) {
+        ret = AVERROR(ENOMEM);
+        goto free_and_end;
+    }
+#endif
     avci->buffer_frame = av_frame_alloc();
     avci->buffer_pkt = av_packet_alloc();
     avci->es.in_frame = av_frame_alloc();
     avci->ds.in_pkt = av_packet_alloc();
     avci->last_pkt_props = av_packet_alloc();
-    if (!avci->compat_decode_frame || !avci->compat_encode_packet ||
-        !avci->buffer_frame || !avci->buffer_pkt          ||
+    avci->pkt_props = av_fifo_alloc(sizeof(*avci->last_pkt_props));
+    if (!avci->buffer_frame || !avci->buffer_pkt          ||
         !avci->es.in_frame  || !avci->ds.in_pkt           ||
-        !avci->to_free      || !avci->last_pkt_props) {
+        !avci->last_pkt_props || !avci->pkt_props) {
         ret = AVERROR(ENOMEM);
         goto free_and_end;
     }
@@ -667,6 +667,15 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
         ret = AVERROR(EINVAL);
         goto free_and_end;
     }
+    if (av_codec_is_decoder(codec) &&
+        codec->type == AVMEDIA_TYPE_AUDIO &&
+        !(codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF) &&
+        avctx->channels == 0) {
+        av_log(avctx, AV_LOG_ERROR, "Decoder requires channel count but channels not set\n");
+        ret = AVERROR(EINVAL);
+        goto free_and_end;
+    }
+
     if (avctx->sample_rate < 0) {
         av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate);
         ret = AVERROR(EINVAL);
@@ -678,6 +687,19 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
         goto free_and_end;
     }
 
+#if FF_API_THREAD_SAFE_CALLBACKS
+FF_DISABLE_DEPRECATION_WARNINGS
+    if ((avctx->thread_type & FF_THREAD_FRAME) &&
+        avctx->get_buffer2 != avcodec_default_get_buffer2 &&
+        !avctx->thread_safe_callbacks) {
+        av_log(avctx, AV_LOG_WARNING, "Requested frame threading with a "
+               "custom get_buffer2() implementation which is not marked as "
+               "thread safe. This is not supported anymore, make your "
+               "callback thread-safe.\n");
+    }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
     avctx->codec = codec;
     if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) &&
         avctx->codec_id == AV_CODEC_ID_NONE) {
@@ -1048,12 +1070,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
     av_freep(&avctx->priv_data);
     av_freep(&avctx->subtitle_header);
 
+#if FF_API_OLD_ENCDEC
     av_frame_free(&avci->to_free);
     av_frame_free(&avci->compat_decode_frame);
-    av_frame_free(&avci->buffer_frame);
     av_packet_free(&avci->compat_encode_packet);
+#endif
+    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);
@@ -1089,10 +1114,21 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
     avci->draining_done = 0;
     avci->nb_draining_errors = 0;
     av_frame_unref(avci->buffer_frame);
+#if FF_API_OLD_ENCDEC
     av_frame_unref(avci->compat_decode_frame);
     av_packet_unref(avci->compat_encode_packet);
+#endif
     av_packet_unref(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);
+    }
+    av_fifo_reset(avci->pkt_props);
+
     av_frame_unref(avci->es.in_frame);
     av_packet_unref(avci->ds.in_pkt);
 
@@ -1107,8 +1143,12 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
     if (av_codec_is_decoder(avctx->codec))
         av_bsf_flush(avci->bsf);
 
+#if FF_API_OLD_ENCDEC
+FF_DISABLE_DEPRECATION_WARNINGS
     if (!avctx->refcounted_frames)
         av_frame_unref(avci->to_free);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 }
 
 void avsubtitle_free(AVSubtitle *sub)
@@ -1148,14 +1188,24 @@ av_cold int avcodec_close(AVCodecContext *avctx)
             avctx->codec->close(avctx);
         avctx->internal->byte_buffer_size = 0;
         av_freep(&avctx->internal->byte_buffer);
+#if FF_API_OLD_ENCDEC
         av_frame_free(&avctx->internal->to_free);
         av_frame_free(&avctx->internal->compat_decode_frame);
-        av_frame_free(&avctx->internal->buffer_frame);
         av_packet_free(&avctx->internal->compat_encode_packet);
+#endif
+        av_frame_free(&avctx->internal->buffer_frame);
         av_packet_free(&avctx->internal->buffer_pkt);
+        av_packet_unref(avctx->internal->last_pkt_props);
+        while (av_fifo_size(avctx->internal->pkt_props) >=
+               sizeof(*avctx->internal->last_pkt_props)) {
+            av_fifo_generic_read(avctx->internal->pkt_props,
+                                 avctx->internal->last_pkt_props,
+                                 sizeof(*avctx->internal->last_pkt_props),
+                                 NULL);
+            av_packet_unref(avctx->internal->last_pkt_props);
+        }
         av_packet_free(&avctx->internal->last_pkt_props);
-        avpriv_packet_list_free(&avctx->internal->pkt_props,
-                                &avctx->internal->pkt_props_tail);
+        av_fifo_freep(&avctx->internal->pkt_props);
 
         av_packet_free(&avctx->internal->ds.in_pkt);
         av_frame_free(&avctx->internal->es.in_frame);
@@ -1491,6 +1541,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
     case AV_CODEC_ID_ADPCM_ARGO:
     case AV_CODEC_ID_ADPCM_CT:
     case AV_CODEC_ID_ADPCM_IMA_ALP:
+    case AV_CODEC_ID_ADPCM_IMA_AMV:
     case AV_CODEC_ID_ADPCM_IMA_APC:
     case AV_CODEC_ID_ADPCM_IMA_APM:
     case AV_CODEC_ID_ADPCM_IMA_EA_SEAD:
@@ -1510,6 +1561,7 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
     case AV_CODEC_ID_PCM_VIDC:
     case AV_CODEC_ID_PCM_S8:
     case AV_CODEC_ID_PCM_S8_PLANAR:
+    case AV_CODEC_ID_PCM_SGA:
     case AV_CODEC_ID_PCM_U8:
     case AV_CODEC_ID_SDX2_DPCM:
     case AV_CODEC_ID_DERF_DPCM:
@@ -1631,14 +1683,10 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
             return 256 * sr / 245;
         else if (id == AV_CODEC_ID_DST)
             return 588 * sr / 44100;
-
-        if (ch > 0) {
-            /* calc from sample rate and channels */
-            if (id == AV_CODEC_ID_BINKAUDIO_DCT) {
-                if (sr / 22050 > 22)
-                    return 0;
-                return (480 << (sr / 22050)) / ch;
-            }
+        else if (id == AV_CODEC_ID_BINKAUDIO_DCT) {
+            if (sr / 22050 > 22)
+                return 0;
+            return (480 << (sr / 22050));
         }
 
         if (id == AV_CODEC_ID_MP3)
@@ -1688,7 +1736,10 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
                 return frame_bytes / (9 * ch) * 16;
             case AV_CODEC_ID_ADPCM_PSX:
             case AV_CODEC_ID_ADPCM_DTK:
-                return frame_bytes / (16 * ch) * 28;
+                frame_bytes /= 16 * ch;
+                if (frame_bytes > INT_MAX / 28)
+                    return 0;
+                return frame_bytes * 28;
             case AV_CODEC_ID_ADPCM_4XM:
             case AV_CODEC_ID_ADPCM_IMA_DAT4:
             case AV_CODEC_ID_ADPCM_IMA_ISS:
@@ -1746,7 +1797,7 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
                 case AV_CODEC_ID_ADPCM_IMA_RAD:
                     return blocks * ((ba - 4 * ch) * 2 / ch);
                 case AV_CODEC_ID_ADPCM_MS:
-                    return blocks * (2 + (ba - 7 * ch) * 2 / ch);
+                    return blocks * (2 + (ba - 7 * ch) * 2LL / ch);
                 case AV_CODEC_ID_ADPCM_MTAF:
                     return blocks * (ba - 16) * 2 / ch;
                 }