Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 10 Aug 2012 02:46:13 +0000 (04:46 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 10 Aug 2012 02:46:13 +0000 (04:46 +0200)
* qatar/master:
  motion_est: drop inline from sad_hpel_motion_search()
  motion_est: remove unused macros
  motion_est: remove useless no_motion_search() function
  lagarith: frame multithreading
  doxygen: qdm2: Drop documentation for non-existing function parameters
  build: add HOSTOBJS to SUBDIR_VARS list

Conflicts:
Makefile

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Makefile
libavcodec/motion_est.c
libavcodec/qdm2.c

diff --combined Makefile
+++ b/Makefile
@@@ -1,32 -1,73 +1,32 @@@
 +MAIN_MAKEFILE=1
  include config.mak
  
  vpath %.c    $(SRC_PATH)
 +vpath %.cpp  $(SRC_PATH)
  vpath %.h    $(SRC_PATH)
  vpath %.S    $(SRC_PATH)
  vpath %.asm  $(SRC_PATH)
  vpath %.v    $(SRC_PATH)
  vpath %.texi $(SRC_PATH)
 +vpath %/fate_config.sh.template $(SRC_PATH)
  
 -ifndef V
 -Q      = @
 -ECHO   = printf "$(1)\t%s\n" $(2)
 -BRIEF  = CC HOSTCC AS YASM AR LD
 -SILENT = DEPCC DEPHOSTCC DEPAS DEPYASM RANLIB RM
 -MSG    = $@
 -M      = @$(call ECHO,$(TAG),$@);
 -$(foreach VAR,$(BRIEF), \
 -    $(eval override $(VAR) = @$$(call ECHO,$(VAR),$$(MSG)); $($(VAR))))
 -$(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
 -$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_PATH)/%=%)); $(INSTALL))
 -endif
 -
 -ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil swscale
 -
 -IFLAGS     := -I. -I$(SRC_PATH)
 -CPPFLAGS   := $(IFLAGS) $(CPPFLAGS)
 -CFLAGS     += $(ECFLAGS)
 -CCFLAGS     = $(CPPFLAGS) $(CFLAGS)
 -ASFLAGS    := $(CPPFLAGS) $(ASFLAGS)
 -YASMFLAGS  += $(IFLAGS:%=%/) -I$(SRC_PATH)/libavutil/x86/ -Pconfig.asm
 -HOSTCCFLAGS = $(IFLAGS) $(HOSTCFLAGS)
 -LDFLAGS    := $(ALLFFLIBS:%=-Llib%) $(LDFLAGS)
 -
 -define COMPILE
 -      $(call $(1)DEP,$(1))
 -      $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $<
 -endef
 -
 -COMPILE_C = $(call COMPILE,CC)
 -COMPILE_S = $(call COMPILE,AS)
 -
 -%.o: %.c
 -      $(COMPILE_C)
 -
 -%.o: %.S
 -      $(COMPILE_S)
 -
 -%.h.c:
 -      $(Q)echo '#include "$*.h"' >$@
 -
 -%.ver: %.v
 -      $(Q)sed 's/$$MAJOR/$($(basename $(@F))_VERSION_MAJOR)/' $^ > $@
 -
 -%.c %.h: TAG = GEN
 -
 -PROGS-$(CONFIG_AVCONV)   += avconv
 -PROGS-$(CONFIG_AVPLAY)   += avplay
 -PROGS-$(CONFIG_AVPROBE)  += avprobe
 -PROGS-$(CONFIG_AVSERVER) += avserver
 +PROGS-$(CONFIG_FFMPEG)   += ffmpeg
 +PROGS-$(CONFIG_FFPLAY)   += ffplay
 +PROGS-$(CONFIG_FFPROBE)  += ffprobe
 +PROGS-$(CONFIG_FFSERVER) += ffserver
  
  PROGS      := $(PROGS-yes:%=%$(EXESUF))
 +INSTPROGS   = $(PROGS-yes:%=%$(PROGSSUF)$(EXESUF))
  OBJS        = cmdutils.o
 -OBJS-avconv = avconv_opt.o avconv_filter.o
 +OBJS-ffmpeg = ffmpeg_opt.o ffmpeg_filter.o
  TESTTOOLS   = audiogen videogen rotozoom tiny_psnr base64
  HOSTPROGS  := $(TESTTOOLS:%=tests/%) doc/print_options
  TOOLS       = qt-faststart trasher
  TOOLS-$(CONFIG_ZLIB) += cws2fws
  
 -BASENAMES   = avconv avplay avprobe avserver
 -ALLPROGS    = $(BASENAMES:%=%$(EXESUF))
 +BASENAMES   = ffmpeg ffplay ffprobe ffserver
 +ALLPROGS    = $(BASENAMES:%=%$(PROGSSUF)$(EXESUF))
 +ALLPROGS_G  = $(BASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
  ALLMANPAGES = $(BASENAMES:%=%.1)
  
  FFLIBS-$(CONFIG_AVDEVICE) += avdevice
@@@ -34,14 -75,11 +34,14 @@@ FFLIBS-$(CONFIG_AVFILTER) += avfilte
  FFLIBS-$(CONFIG_AVFORMAT) += avformat
  FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
  FFLIBS-$(CONFIG_AVCODEC)  += avcodec
 +FFLIBS-$(CONFIG_POSTPROC) += postproc
 +FFLIBS-$(CONFIG_SWRESAMPLE)+= swresample
  FFLIBS-$(CONFIG_SWSCALE)  += swscale
  
  FFLIBS := avutil
  
 -DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.avpreset)
 +DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset) $(SRC_PATH)/doc/ffprobe.xsd
 +EXAMPLES_FILES := $(wildcard $(SRC_PATH)/doc/examples/*.c) $(SRC_PATH)/doc/examples/Makefile
  
  SKIPHEADERS = cmdutils_common_opts.h
  
@@@ -52,10 -90,6 +52,10 @@@ FF_DEP_LIBS  := $(DEP_LIBS
  
  all: $(PROGS)
  
 +$(PROGS): %$(EXESUF): %$(PROGSSUF)_g$(EXESUF)
 +      $(CP) $< $@$(PROGSSUF)
 +      $(STRIP) $@$(PROGSSUF)
 +
  $(TOOLS): %$(EXESUF): %.o
        $(LD) $(LDFLAGS) -o $@ $< $(ELIBS)
  
@@@ -72,8 -106,7 +72,8 @@@ SUBDIR_VARS := CLEANFILES EXAMPLES FFLI
                 ARMV5TE-OBJS ARMV6-OBJS ARMVFP-OBJS NEON-OBJS             \
                 MMI-OBJS ALTIVEC-OBJS VIS-OBJS                            \
                 MMX-OBJS YASM-OBJS                                        \
-                OBJS TESTOBJS
 +               MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSPR1-OBJS MIPS32R2-OBJS  \
+                OBJS HOSTOBJS TESTOBJS
  
  define RESET
  $(1) :=
@@@ -92,16 -125,16 +92,16 @@@ $(foreach D,$(FFLIBS),$(eval $(call DOS
  
  define DOPROG
  OBJS-$(1) += $(1).o
 -$(1)$(EXESUF): $(OBJS-$(1))
 +$(1)_g$(EXESUF): $(OBJS-$(1))
  $$(OBJS-$(1)): CFLAGS  += $(CFLAGS-$(1))
 -$(1)$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
 -$(1)$(EXESUF): FF_EXTRALIBS += $(LIBS-$(1))
 +$(1)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
 +$(1)_g$(EXESUF): FF_EXTRALIBS += $(LIBS-$(1))
  -include $$(OBJS-$(1):.o=.d)
  endef
  
  $(foreach P,$(PROGS-yes),$(eval $(call DOPROG,$(P))))
  
 -$(PROGS): %$(EXESUF): %.o cmdutils.o $(FF_DEP_LIBS)
 +%$(PROGSSUF)_g$(EXESUF): %.o cmdutils.o $(FF_DEP_LIBS)
        $(LD) $(LDFLAGS) -o $@ $(OBJS-$*) cmdutils.o $(FF_EXTRALIBS)
  
  OBJDIRS += tools
@@@ -134,12 -167,11 +134,12 @@@ install-progs-$(CONFIG_SHARED): install
  
  install-progs: install-progs-yes $(PROGS)
        $(Q)mkdir -p "$(BINDIR)"
 -      $(INSTALL) -c -m 755 $(PROGS) "$(BINDIR)"
 +      $(INSTALL) -c -m 755 $(INSTPROGS) "$(BINDIR)"
  
 -install-data: $(DATA_FILES)
 -      $(Q)mkdir -p "$(DATADIR)"
 +install-data: $(DATA_FILES) $(EXAMPLES_FILES)
 +      $(Q)mkdir -p "$(DATADIR)/examples"
        $(INSTALL) -m 644 $(DATA_FILES) "$(DATADIR)"
 +      $(INSTALL) -m 644 $(EXAMPLES_FILES) "$(DATADIR)/examples"
  
  uninstall: uninstall-libs uninstall-headers uninstall-progs uninstall-data
  
@@@ -150,30 -182,19 +150,30 @@@ uninstall-data
        $(RM) -r "$(DATADIR)"
  
  clean::
 -      $(RM) $(ALLPROGS)
 +      $(RM) $(ALLPROGS) $(ALLPROGS_G)
        $(RM) $(CLEANSUFFIXES)
        $(RM) $(TOOLS)
        $(RM) $(CLEANSUFFIXES:%=tools/%)
 +      $(RM) coverage.info
 +      $(RM) -r coverage-html
  
  distclean::
        $(RM) $(DISTCLEANSUFFIXES)
        $(RM) config.* .version version.h libavutil/avconfig.h
  
  config:
 -      $(SRC_PATH)/configure $(value LIBAV_CONFIGURATION)
 +      $(SRC_PATH)/configure $(value FFMPEG_CONFIGURATION)
 +
 +# Without the sed genthml thinks "libavutil" and "./libavutil" are two different things
 +coverage.info: $(wildcard *.gcda *.gcno */*.gcda */*.gcno */*/*.gcda */*/*.gcno)
 +      $(Q)lcov -c -d . -b . | sed -e 's#/./#/#g' > $@
 +
 +coverage-html: coverage.info
 +      $(Q)mkdir -p $@
 +      $(Q)genhtml -o $@ $<
 +      $(Q)touch $@
  
 -check: all alltools checkheaders examples testprogs fate
 +check: all alltools examples testprogs fate
  
  include $(SRC_PATH)/doc/Makefile
  include $(SRC_PATH)/tests/Makefile
@@@ -189,5 -210,5 +189,5 @@@ $(sort $(OBJDIRS))
  # so this saves some time on slow systems.
  .SUFFIXES:
  
 -.PHONY: all all-yes alltools check *clean config examples install*
 +.PHONY: all all-yes alltools check *clean config install*
  .PHONY: testprogs uninstall*
diff --combined libavcodec/motion_est.c
@@@ -5,20 -5,20 +5,20 @@@
   *
   * new motion estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #undef NDEBUG
  #include <assert.h>
  
- #define SQ(a) ((a)*(a))
  #define P_LEFT P[1]
  #define P_TOP P[2]
  #define P_TOPRIGHT P[3]
  #define P_MEDIAN P[4]
  #define P_MV1 P[9]
  
- static inline int sad_hpel_motion_search(MpegEncContext * s,
+ static int sad_hpel_motion_search(MpegEncContext * s,
                                    int *mx_ptr, int *my_ptr, int dmin,
                                    int src_index, int ref_index,
                                    int size, int h);
@@@ -374,15 -372,6 +372,6 @@@ int ff_init_me(MpegEncContext *s)
      return 0;
  }
  
- static inline void no_motion_search(MpegEncContext * s,
-                                     int *mx_ptr, int *my_ptr)
- {
-     *mx_ptr = 16 * s->mb_x;
-     *my_ptr = 16 * s->mb_y;
- }
- #define Z_THRESHOLD 256
  #define CHECK_SAD_HALF_MV(suffix, x, y) \
  {\
      d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\
      COPY3_IF_LT(dminh, d, dx, x, dy, y)\
  }
  
- static inline int sad_hpel_motion_search(MpegEncContext * s,
+ static int sad_hpel_motion_search(MpegEncContext * s,
                                    int *mx_ptr, int *my_ptr, int dmin,
                                    int src_index, int ref_index,
                                    int size, int h)
@@@ -536,8 -525,8 +525,8 @@@ static inline void get_limits(MpegEncCo
      if (s->unrestricted_mv) {
          c->xmin = - x - 16;
          c->ymin = - y - 16;
 -        c->xmax = - x + s->mb_width *16;
 -        c->ymax = - y + s->mb_height*16;
 +        c->xmax = - x + s->width;
 +        c->ymax = - y + s->height;
      } else if (s->out_format == FMT_H261){
          // Search range of H261 is different from other codec standards
          c->xmin = (x > 15) ? - 15 : 0;
@@@ -576,11 -565,10 +565,11 @@@ static inline int h263_mv4_search(MpegE
      const int h=8;
      int block;
      int P[10][2];
 -    int dmin_sum=0, mx4_sum=0, my4_sum=0;
 +    int dmin_sum=0, mx4_sum=0, my4_sum=0, i;
      int same=1;
      const int stride= c->stride;
      uint8_t *mv_penalty= c->current_mv_penalty;
 +    int saftey_cliping= s->unrestricted_mv && (s->width&15) && (s->height&15);
  
      init_mv4_ref(c);
  
          const int mot_stride = s->b8_stride;
          const int mot_xy = s->block_index[block];
  
 +        if(saftey_cliping){
 +            c->xmax = - 16*s->mb_x + s->width  - 8*(block &1);
 +            c->ymax = - 16*s->mb_y + s->height - 8*(block>>1);
 +        }
 +
          P_LEFT[0] = s->current_picture.f.motion_val[0][mot_xy - 1][0];
          P_LEFT[1] = s->current_picture.f.motion_val[0][mot_xy - 1][1];
  
          }
          P_MV1[0]= mx;
          P_MV1[1]= my;
 +        if(saftey_cliping)
 +            for(i=0; i<10; i++){
 +                if(P[i][0] > (c->xmax<<shift)) P[i][0]= (c->xmax<<shift);
 +                if(P[i][1] > (c->ymax<<shift)) P[i][1]= (c->ymax<<shift);
 +            }
  
          dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift);
  
@@@ -1051,9 -1029,8 +1040,8 @@@ void ff_estimate_p_frame_motion(MpegEnc
      switch(s->me_method) {
      case ME_ZERO:
      default:
-         no_motion_search(s, &mx, &my);
-         mx-= mb_x*16;
-         my-= mb_y*16;
+         mx   = 0;
+         my   = 0;
          dmin = 0;
          break;
      case ME_X1:
@@@ -1294,10 -1271,9 +1282,9 @@@ static int ff_estimate_motion_b(MpegEnc
      switch(s->me_method) {
      case ME_ZERO:
      default:
-         no_motion_search(s, &mx, &my);
+         mx   = 0;
+         my   = 0;
          dmin = 0;
-         mx-= mb_x*16;
-         my-= mb_y*16;
          break;
      case ME_X1:
      case ME_EPZS:
diff --combined libavcodec/qdm2.c
@@@ -5,20 -5,20 +5,20 @@@
   * Copyright (c) 2005 Alex Beregszaszi
   * Copyright (c) 2005 Roberto Togni
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -169,7 -169,7 +169,7 @@@ typedef struct 
      /// I/O data
      const uint8_t *compressed_data;
      int compressed_size;
 -    float output_buffer[QDM2_MAX_FRAME_SIZE * 2];
 +    float output_buffer[QDM2_MAX_FRAME_SIZE * MPA_MAX_CHANNELS * 2];
  
      /// Synthesis filter
      MPADSPContext mpadsp;
@@@ -343,14 -343,7 +343,14 @@@ static int qdm2_get_vlc (GetBitContext 
  
      /* stage-3, optional */
      if (flag) {
 -        int tmp = vlc_stage3_values[value];
 +        int tmp;
 +
 +        if (value >= 60) {
 +            av_log(0, AV_LOG_ERROR, "value %d in qdm2_get_vlc too large\n", value);
 +            return 0;
 +        }
 +
 +        tmp= vlc_stage3_values[value];
  
          if ((value & ~3) > 0)
              tmp += get_bits (gb, (value >> 2));
@@@ -768,7 -761,7 +768,7 @@@ static void fill_coding_method_array (s
   * @param sb_min    lower subband processed (sb_min included)
   * @param sb_max    higher subband processed (sb_max excluded)
   */
 -static void synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int length, int sb_min, int sb_max)
 +static int synthfilt_build_sb_samples (QDM2Context *q, GetBitContext *gb, int length, int sb_min, int sb_max)
  {
      int sb, j, k, n, ch, run, channels;
      int joined_stereo, zero_encoding, chs;
          for (sb=sb_min; sb < sb_max; sb++)
              build_sb_samples_from_noise (q, sb);
  
 -        return;
 +        return 0;
      }
  
      for (sb = sb_min; sb < sb_max; sb++) {
                      case 30:
                          if (get_bits_left(gb) >= 4) {
                              unsigned index = qdm2_get_vlc(gb, &vlc_tab_type30, 0, 1);
 -                            if (index < FF_ARRAY_ELEMS(type30_dequant)) {
 -                                samples[0] = type30_dequant[index];
 -                            } else
 -                                samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx);
 +                            if (index >= FF_ARRAY_ELEMS(type30_dequant)) {
 +                                av_log(NULL, AV_LOG_ERROR, "index %d out of type30_dequant array\n", index);
 +                                return AVERROR_INVALIDDATA;
 +                            }
 +                            samples[0] = type30_dequant[index];
                          } else
                              samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx);
  
                                  type34_first = 0;
                              } else {
                                  unsigned index = qdm2_get_vlc(gb, &vlc_tab_type34, 0, 1);
 -                                if (index < FF_ARRAY_ELEMS(type34_delta)) {
 -                                    samples[0] = type34_delta[index] / type34_div + type34_predictor;
 -                                    type34_predictor = samples[0];
 -                                } else
 -                                    samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx);
 +                                if (index >= FF_ARRAY_ELEMS(type34_delta)) {
 +                                    av_log(NULL, AV_LOG_ERROR, "index %d out of type34_delta array\n", index);
 +                                    return AVERROR_INVALIDDATA;
 +                                }
 +                                samples[0] = type34_delta[index] / type34_div + type34_predictor;
 +                                type34_predictor = samples[0];
                              }
                          } else {
                              samples[0] = SB_DITHERING_NOISE(sb,q->noise_idx);
              } // j loop
          } // channel loop
      } // subband loop
 +    return 0;
  }
  
  
   * @param quantized_coeffs    pointer to quantized_coeffs[ch][0]
   * @param gb        bitreader context
   */
 -static void init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb)
 +static int init_quantized_coeffs_elem0 (int8_t *quantized_coeffs, GetBitContext *gb)
  {
      int i, k, run, level, diff;
  
      if (get_bits_left(gb) < 16)
 -        return;
 +        return -1;
      level = qdm2_get_vlc(gb, &vlc_tab_level, 0, 2);
  
      quantized_coeffs[0] = level;
  
      for (i = 0; i < 7; ) {
          if (get_bits_left(gb) < 16)
 -            break;
 +            return -1;
          run = qdm2_get_vlc(gb, &vlc_tab_run, 0, 1) + 1;
  
 +        if (i + run >= 8)
 +            return -1;
 +
          if (get_bits_left(gb) < 16)
 -            break;
 +            return -1;
          diff = qdm2_get_se_vlc(&vlc_tab_diff, gb, 2);
  
          for (k = 1; k <= run; k++)
          level += diff;
          i += run;
      }
 +    return 0;
  }
  
  
@@@ -1063,7 -1049,7 +1063,7 @@@ static void init_tone_level_dequantizat
   * @param q       context
   * @param node    pointer to node with packet
   */
 -static void process_subpacket_9 (QDM2Context *q, QDM2SubPNode *node)
 +static int process_subpacket_9 (QDM2Context *q, QDM2SubPNode *node)
  {
      GetBitContext gb;
      int i, j, k, n, ch, run, level, diff;
                  run = qdm2_get_vlc(&gb, &vlc_tab_run, 0, 1) + 1;
                  diff = qdm2_get_se_vlc(&vlc_tab_diff, &gb, 2);
  
 +                if (j + run >= 8)
 +                    return -1;
 +
                  for (k = 1; k <= run; k++)
                      q->quantized_coeffs[ch][i][j + k] = (level + ((k*diff) / run));
  
      for (ch = 0; ch < q->nb_channels; ch++)
          for (i = 0; i < 8; i++)
              q->quantized_coeffs[ch][0][i] = 0;
 +
 +    return 0;
  }
  
  
   *
   * @param q         context
   * @param node      pointer to node with packet
-  * @param length    packet length in bits
   */
  static void process_subpacket_10 (QDM2Context *q, QDM2SubPNode *node)
  {
@@@ -1154,7 -1134,6 +1153,6 @@@ static void process_subpacket_11 (QDM2C
   *
   * @param q         context
   * @param node      pointer to node with packet
-  * @param length    packet length in bits
   */
  static void process_subpacket_12 (QDM2Context *q, QDM2SubPNode *node)
  {
@@@ -1359,14 -1338,9 +1357,14 @@@ static void qdm2_fft_decode_tones (QDM2
      local_int_10 = 1 << (q->group_order - duration - 1);
      offset = 1;
  
 -    while (1) {
 +    while (get_bits_left(gb)>0) {
          if (q->superblocktype_2_3) {
              while ((n = qdm2_get_vlc(gb, &vlc_tab_fft_tone_offset[local_int_8], 1, 2)) < 2) {
 +                if (get_bits_left(gb)<0) {
 +                    if(local_int_4 < q->group_size)
 +                        av_log(0, AV_LOG_ERROR, "overread in qdm2_fft_decode_tones()\n");
 +                    return;
 +                }
                  offset = 1;
                  if (n == 0) {
                      local_int_4 += local_int_10;
@@@ -1794,10 -1768,8 +1792,10 @@@ static av_cold int qdm2_decode_init(AVC
  
      avctx->channels = s->nb_channels = s->channels = AV_RB32(extradata);
      extradata += 4;
 -    if (s->channels > MPA_MAX_CHANNELS)
 +    if (s->channels > MPA_MAX_CHANNELS) {
 +        av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
          return AVERROR_INVALIDDATA;
 +    }
  
      avctx->sample_rate = AV_RB32(extradata);
      extradata += 4;
      // something like max decodable tones
      s->group_order = av_log2(s->group_size) + 1;
      s->frame_size = s->group_size / 16; // 16 iterations per super block
 +
      if (s->frame_size > QDM2_MAX_FRAME_SIZE)
          return AVERROR_INVALIDDATA;
  
@@@ -1896,9 -1867,6 +1894,9 @@@ static int qdm2_decode (QDM2Context *q
      int ch, i;
      const int frame_size = (q->frame_size * q->channels);
  
 +    if((unsigned)frame_size > FF_ARRAY_ELEMS(q->output_buffer)/2)
 +        return -1;
 +
      /* select input buffer */
      q->compressed_data = in;
      q->compressed_size = q->checksum_size;