Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Sat, 17 Mar 2012 22:16:05 +0000 (23:16 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sat, 17 Mar 2012 22:16:05 +0000 (23:16 +0100)
* qatar/master:
  resample: allocate a large enough output buffer
  fate: fix enc_dec_pcm tests with remote target
  wmaenc: remove bit-exact hack
  FATE: remove WMA acodec tests
  FATE: add WMAv1 and WMAv2 encode/decode tests with fuzzy comparison
  FATE: add AC-3 and E-AC-3 encode/decode tests with fuzzy comparison
  qtrle: Use bytestream2 functions to prevent buffer overreads.
  vqavideo: check malloc return values
  x11grab: fix a memory leak exposed by valgrind
  threads: fix old frames returned after avcodec_flush_buffers()
  MPV: always mark dummy frames as reference
  h264: fix deadlocks on incomplete reference frame decoding.
  mpeg4: report frame decoding completion at ff_MPV_frame_end().
  mimic: don't use self as reference, and report completion at end of decode().

Conflicts:
libavcodec/h264.c
libavcodec/qtrle.c
libavcodec/resample.c
libavcodec/vqavideo.c
libavdevice/x11grab.c
tests/ref/seek/wmav1_asf
tests/ref/seek/wmav2_asf

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/h264.c
libavcodec/mimic.c
libavcodec/mpegvideo.c
libavcodec/pthread.c
libavcodec/qtrle.c
libavcodec/resample.c
libavcodec/vqavideo.c
libavcodec/wmaenc.c
libavdevice/x11grab.c
tests/codec-regression.sh
tests/fate-run.sh

@@@ -3130,10 -3120,20 +3135,20 @@@ static int decode_slice_header(H264Cont
      }
      h->mb_field_decoding_flag = s->picture_structure != PICT_FRAME;
  
-     if (h0->current_slice == 0) {
+     if (h0->current_slice != 0) {
+         if (last_pic_structure != s->picture_structure ||
+             last_pic_dropable  != s->dropable) {
+             av_log(h->s.avctx, AV_LOG_ERROR,
+                    "Changing field mode (%d -> %d) between slices is not allowed\n",
+                    last_pic_structure, s->picture_structure);
+             s->picture_structure = last_pic_structure;
+             s->dropable          = last_pic_dropable;
+             return AVERROR_INVALIDDATA;
+         }
+     } else {
          /* Shorten frame num gaps so we don't have to allocate reference
           * frames just to throw them away */
 -        if (h->frame_num != h->prev_frame_num) {
 +        if (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0) {
              int unwrap_prev_frame_num = h->prev_frame_num;
              int max_frame_num         = 1 << h->sps.log2_max_frame_num;
  
              }
          }
  
 -        while (h->frame_num != h->prev_frame_num &&
+         /* See if we have a decoded first field looking for a pair...
+          * Here, we're using that to see if we should mark previously
+          * decode frames as "finished".
+          * We have to do that before the "dummy" in-between frame allocation,
+          * since that can modify s->current_picture_ptr. */
+         if (s0->first_field) {
+             assert(s0->current_picture_ptr);
+             assert(s0->current_picture_ptr->f.data[0]);
+             assert(s0->current_picture_ptr->f.reference != DELAYED_PIC_REF);
+             /* Mark old field/frame as completed */
+             if (!last_pic_dropable && s0->current_picture_ptr->owner2 == s0) {
+                 ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+                                           last_pic_structure == PICT_BOTTOM_FIELD);
+             }
+             /* figure out if we have a complementary field pair */
+             if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) {
+                 /* Previous field is unmatched. Don't display it, but let it
+                  * remain for reference if marked as such. */
+                 if (!last_pic_dropable && last_pic_structure != PICT_FRAME) {
+                     ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+                                               last_pic_structure == PICT_TOP_FIELD);
+                 }
+             } else {
+                 if (s0->current_picture_ptr->frame_num != h->frame_num) {
+                     /* This and previous field were reference, but had
+                      * different frame_nums. Consider this field first in
+                      * pair. Throw away previous field except for reference
+                      * purposes. */
+                     if (!last_pic_dropable && last_pic_structure != PICT_FRAME) {
+                         ff_thread_report_progress(&s0->current_picture_ptr->f, INT_MAX,
+                                                   last_pic_structure == PICT_TOP_FIELD);
+                     }
+                 } else {
+                     /* Second field in complementary pair */
+                     if (!((last_pic_structure   == PICT_TOP_FIELD &&
+                            s->picture_structure == PICT_BOTTOM_FIELD) ||
+                           (last_pic_structure   == PICT_BOTTOM_FIELD &&
+                            s->picture_structure == PICT_TOP_FIELD))) {
+                         av_log(s->avctx, AV_LOG_ERROR,
+                                "Invalid field mode combination %d/%d\n",
+                                last_pic_structure, s->picture_structure);
+                         s->picture_structure = last_pic_structure;
+                         s->dropable          = last_pic_dropable;
+                         return AVERROR_INVALIDDATA;
+                     } else if (last_pic_dropable != s->dropable) {
+                         av_log(s->avctx, AV_LOG_ERROR,
+                                "Cannot combine reference and non-reference fields in the same frame\n");
+                         av_log_ask_for_sample(s->avctx, NULL);
+                         s->picture_structure = last_pic_structure;
+                         s->dropable          = last_pic_dropable;
+                         return AVERROR_INVALIDDATA;
+                     }
+                     /* Take ownership of this buffer. Note that if another thread owned
+                      * the first field of this buffer, we're not operating on that pointer,
+                      * so the original thread is still responsible for reporting progress
+                      * on that first field (or if that was us, we just did that above).
+                      * By taking ownership, we assign responsibility to ourselves to
+                      * report progress on the second field. */
+                     s0->current_picture_ptr->owner2 = s0;
+                 }
+             }
+         }
 +        while (h->frame_num != h->prev_frame_num && h->prev_frame_num >= 0 &&
                 h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) {
              Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
              av_log(h->s.avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
                  s0->first_field         = FIELD_PICTURE;
              } else {
                  if (s0->current_picture_ptr->frame_num != h->frame_num) {
-                     /* This and the previous field had
-                      * different frame_nums. Consider this field first in pair.
-                      * Throw away previous one except for reference purposes. */
 +                    ff_thread_report_progress((AVFrame*)s0->current_picture_ptr, INT_MAX,
 +                                              s0->picture_structure==PICT_BOTTOM_FIELD);
+                     /* This and the previous field had different frame_nums.
+                      * Consider this field first in pair. Throw away previous
+                      * one except for reference purposes. */
                      s0->first_field         = 1;
                      s0->current_picture_ptr = NULL;
                  } else {
@@@ -4210,8 -4269,9 +4295,9 @@@ again
              case NAL_IDR_SLICE:
                  if (h->nal_unit_type != NAL_IDR_SLICE) {
                      av_log(h->s.avctx, AV_LOG_ERROR,
 -                           "Invalid mix of idr and non-idr slices");
 +                           "Invalid mix of idr and non-idr slices\n");
-                     return -1;
+                     buf_index = -1;
+                     goto end;
                  }
                  idr(h); // FIXME ensure we don't lose some frames if there is reordering
              case NAL_SLICE:
Simple merge
@@@ -1235,20 -1266,12 +1235,21 @@@ int ff_MPV_frame_start(MpegEncContext *
  
              /* Allocate a dummy frame */
              i = ff_find_unused_picture(s, 0);
 -            s->last_picture_ptr = &s->picture[i];
 +            if (i < 0)
 +                return i;
 +            s->last_picture_ptr= &s->picture[i];
 +            s->last_picture_ptr->f.key_frame = 0;
              if (ff_alloc_picture(s, s->last_picture_ptr, 0) < 0)
                  return -1;
 +
 +            if(s->codec_id == CODEC_ID_FLV1 || s->codec_id == CODEC_ID_H263){
 +                for(i=0; i<avctx->height; i++)
 +                    memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width);
 +            }
 +
              ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 0);
              ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 1);
+             s->last_picture_ptr->f.reference = 3;
          }
          if ((s->next_picture_ptr == NULL ||
               s->next_picture_ptr->f.data[0] == NULL) &&
Simple merge
@@@ -72,20 -62,10 +62,19 @@@ static void qtrle_decode_1bpp(QtrleCont
      unsigned char *rgb = s->frame.data[0];
      int pixel_limit = s->frame.linesize[0] * s->avctx->height;
      int skip;
 +    /* skip & 0x80 appears to mean 'start a new line', which can be interpreted
 +     * as 'go to next line' during the decoding of a frame but is 'go to first
 +     * line' at the beginning. Since we always interpret it as 'go to next line'
 +     * in the decoding loop (which makes code simpler/faster), the first line
 +     * would not be counted, so we count one more.
 +     * See: https://ffmpeg.org/trac/ffmpeg/ticket/226
 +     * In the following decoding loop, row_ptr will be the position of the
 +     * _next_ row. */
 +    lines_to_change++;
  
      while (lines_to_change) {
-         CHECK_STREAM_PTR(2);
-         skip = s->buf[stream_ptr++];
-         rle_code = (signed char)s->buf[stream_ptr++];
+         skip     =              bytestream2_get_byte(&s->g);
+         rle_code = (signed char)bytestream2_get_byte(&s->g);
          if (rle_code == 0)
              break;
          if(skip & 0x80) {
@@@ -137,15 -113,12 +125,13 @@@ static inline void qtrle_decode_2n4bpp(
      int num_pixels = (bpp == 4) ? 8 : 16;
  
      while (lines_to_change--) {
-         CHECK_STREAM_PTR(2);
-         pixel_ptr = row_ptr + (num_pixels * (s->buf[stream_ptr++] - 1));
+         pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1));
 +        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
  
-         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
              if (rle_code == 0) {
                  /* there's another skip code in the stream */
-                 CHECK_STREAM_PTR(1);
-                 pixel_ptr += (num_pixels * (s->buf[stream_ptr++] - 1));
+                 pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1));
                  CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
              } else if (rle_code < 0) {
                  /* decode the run length code */
@@@ -194,15 -167,12 +180,13 @@@ static void qtrle_decode_8bpp(QtrleCont
      int pixel_limit = s->frame.linesize[0] * s->avctx->height;
  
      while (lines_to_change--) {
-         CHECK_STREAM_PTR(2);
-         pixel_ptr = row_ptr + (4 * (s->buf[stream_ptr++] - 1));
+         pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1));
 +        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
  
-         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
              if (rle_code == 0) {
                  /* there's another skip code in the stream */
-                 CHECK_STREAM_PTR(1);
-                 pixel_ptr += (4 * (s->buf[stream_ptr++] - 1));
+                 pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1));
                  CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
              } else if (rle_code < 0) {
                  /* decode the run length code */
@@@ -248,15 -216,12 +230,13 @@@ static void qtrle_decode_16bpp(QtrleCon
      int pixel_limit = s->frame.linesize[0] * s->avctx->height;
  
      while (lines_to_change--) {
-         CHECK_STREAM_PTR(2);
-         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 2;
+         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2;
 +        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
  
-         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
              if (rle_code == 0) {
                  /* there's another skip code in the stream */
-                 CHECK_STREAM_PTR(1);
-                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 2;
+                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2;
                  CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
              } else if (rle_code < 0) {
                  /* decode the run length code */
@@@ -298,15 -259,12 +274,13 @@@ static void qtrle_decode_24bpp(QtrleCon
      int pixel_limit = s->frame.linesize[0] * s->avctx->height;
  
      while (lines_to_change--) {
-         CHECK_STREAM_PTR(2);
-         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 3;
+         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3;
 +        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
  
-         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
              if (rle_code == 0) {
                  /* there's another skip code in the stream */
-                 CHECK_STREAM_PTR(1);
-                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 3;
+                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3;
                  CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
              } else if (rle_code < 0) {
                  /* decode the run length code */
@@@ -349,15 -305,12 +321,13 @@@ static void qtrle_decode_32bpp(QtrleCon
      int pixel_limit = s->frame.linesize[0] * s->avctx->height;
  
      while (lines_to_change--) {
-         CHECK_STREAM_PTR(2);
-         pixel_ptr = row_ptr + (s->buf[stream_ptr++] - 1) * 4;
+         pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4;
 +        CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
  
-         while ((rle_code = (signed char)s->buf[stream_ptr++]) != -1) {
+         while ((rle_code = (signed char)bytestream2_get_byte(&s->g)) != -1) {
              if (rle_code == 0) {
                  /* there's another skip code in the stream */
-                 CHECK_STREAM_PTR(1);
-                 pixel_ptr += (s->buf[stream_ptr++] - 1) * 4;
+                 pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4;
                  CHECK_PIXEL_PTR(0);  /* make sure pixel_ptr is positive */
              } else if (rle_code < 0) {
                  /* decode the run length code */
@@@ -437,17 -385,13 +403,13 @@@ static int qtrle_decode_frame(AVCodecCo
                                void *data, int *data_size,
                                AVPacket *avpkt)
  {
-     const uint8_t *buf = avpkt->data;
-     int buf_size = avpkt->size;
      QtrleContext *s = avctx->priv_data;
      int header, start_line;
-     int stream_ptr, height, row_ptr;
+     int height, row_ptr;
      int has_palette = 0;
  
-     s->buf = buf;
-     s->size = buf_size;
+     bytestream2_init(&s->g, avpkt->data, avpkt->size);
 -    s->frame.reference = 1;
 +    s->frame.reference = 3;
      s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
                              FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
      if (avctx->reget_buffer(avctx, &s->frame)) {
  
      /* if a header is present, fetch additional decoding parameters */
      if (header & 0x0008) {
-         if(s->size < 14)
+         if (avpkt->size < 14)
              goto done;
-         start_line = AV_RB16(&s->buf[stream_ptr]);
-         stream_ptr += 4;
-         height = AV_RB16(&s->buf[stream_ptr]);
-         stream_ptr += 4;
+         start_line = bytestream2_get_be16(&s->g);
+         bytestream2_skip(&s->g, 2);
+         height     = bytestream2_get_be16(&s->g);
+         bytestream2_skip(&s->g, 2);
 +        if (height > s->avctx->height - start_line)
 +            goto done;
      } else {
          start_line = 0;
-         height = s->avctx->height;
+         height     = s->avctx->height;
      }
      row_ptr = s->frame.linesize[0] * start_line;
  
@@@ -320,14 -269,16 +320,16 @@@ int audio_resample(ReSampleContext *s, 
          input = s->buffer[0];
      }
  
 -    lenout = 4 * nb_samples * s->ratio + 16;
 +    lenout= 2*s->output_channels*nb_samples * s->ratio + 16;
  
      if (s->sample_fmt[1] != AV_SAMPLE_FMT_S16) {
+         int out_size = lenout * av_get_bytes_per_sample(s->sample_fmt[1]) *
+                        s->output_channels;
          output_bak = output;
  
-         if (!s->buffer_size[1] || s->buffer_size[1] < 2*lenout) {
+         if (!s->buffer_size[1] || s->buffer_size[1] < out_size) {
              av_free(s->buffer[1]);
-             s->buffer_size[1] = 2*lenout;
+             s->buffer_size[1] = out_size;
              s->buffer[1] = av_malloc(s->buffer_size[1]);
              if (!s->buffer[1]) {
                  av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n");
@@@ -178,12 -185,6 +189,7 @@@ static av_cold int vqa_decode_init(AVCo
      }
      s->next_codebook_buffer_index = 0;
  
-     /* allocate decode buffer */
-     s->decode_buffer_size = (s->width / s->vector_width) *
-         (s->height / s->vector_height) * 2;
-     s->decode_buffer = av_malloc(s->decode_buffer_size);
 +    avcodec_get_frame_defaults(&s->frame);
      s->frame.data[0] = NULL;
  
      return 0;
Simple merge
@@@ -168,8 -168,11 +168,11 @@@ x11grab_read_header(AVFormatContext *s1
      int ret = 0;
      AVRational framerate;
  
 -    param = av_strdup(s1->filename);
 -    if (!param)
 +    dpyname = av_strdup(s1->filename);
++    if (!dpyname)
+         goto out;
 -    offset = strchr(param, '+');
 +    offset = strchr(dpyname, '+');
      if (offset) {
          sscanf(offset, "%d,%d", &x_off, &y_off);
          x11grab->draw_mouse = !strstr(offset, "nomouse");
Simple merge
Simple merge