Merge commit '69ab9f53f901eac6a649e22d28cf093357870627'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 9 Jul 2015 03:04:13 +0000 (05:04 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 9 Jul 2015 03:06:48 +0000 (05:06 +0200)
* commit '69ab9f53f901eac6a649e22d28cf093357870627':
  hevc: split bitstream unescaping to a separate file

Conflicts:
libavcodec/Makefile
libavcodec/hevc.c

See: afa93d198aaf2cc661c4df6d4095cd030265d30a
Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/Makefile
libavcodec/hevc.c
libavcodec/hevc.h
libavcodec/hevc_parse.c

@@@ -285,7 -240,8 +285,7 @@@ OBJS-$(CONFIG_HAP_DECODER)             
  OBJS-$(CONFIG_HAP_ENCODER)             += hapenc.o
  OBJS-$(CONFIG_HEVC_DECODER)            += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \
                                            hevc_cabac.o hevc_refs.o hevcpred.o    \
-                                           hevcdsp.o hevc_filter.o
+                                           hevcdsp.o hevc_filter.o hevc_parse.o
 -OBJS-$(CONFIG_HEVC_NVENC_ENCODER)      += nvenc_hevc.o
  OBJS-$(CONFIG_HNM4_VIDEO_DECODER)      += hnm4video.o
  OBJS-$(CONFIG_HQ_HQA_DECODER)          += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
                                            canopus.o
@@@ -2954,46 -2694,18 +2841,44 @@@ static int decode_nal_units(HEVCContex
              }
              s->nals = tmp;
              memset(s->nals + s->nals_allocated, 0,
 -                   (new_size - s->nals_allocated) * sizeof(*tmp));
 +                   (new_size - s->nals_allocated) * sizeof(*s->nals));
 +
 +            tmp = av_realloc_array(s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal));
 +            if (!tmp)
 +                goto fail;
 +            s->skipped_bytes_nal = tmp;
 +
 +            tmp = av_realloc_array(s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal));
 +            if (!tmp)
 +                goto fail;
 +            s->skipped_bytes_pos_size_nal = tmp;
 +
 +            tmp = av_realloc_array(s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal));
 +            if (!tmp)
 +                goto fail;
 +            s->skipped_bytes_pos_nal = tmp;
 +
 +            s->skipped_bytes_pos_size_nal[s->nals_allocated] = 1024; // initial buffer size
 +            s->skipped_bytes_pos_nal[s->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[s->nals_allocated], sizeof(*s->skipped_bytes_pos));
 +            if (!s->skipped_bytes_pos_nal[s->nals_allocated])
 +                goto fail;
              s->nals_allocated = new_size;
          }
 -        nal = &s->nals[s->nb_nals++];
 +        s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[s->nb_nals];
 +        s->skipped_bytes_pos = s->skipped_bytes_pos_nal[s->nb_nals];
 +        nal = &s->nals[s->nb_nals];
  
 -        consumed = ff_hevc_extract_rbsp(buf, extract_length, nal);
 +        consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal);
-         s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes;
-         s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size;
-         s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos;
          if (consumed < 0) {
              ret = consumed;
              goto fail;
          }
  
 -        ret = init_get_bits8(&s->HEVClc.gb, nal->data, nal->size);
++        s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes;
++        s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size;
++        s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos;
++
 +        ret = init_get_bits8(&s->HEVClc->gb, nal->data, nal->size);
          if (ret < 0)
              goto fail;
          hls_nal_unit(s);
@@@ -1040,17 -995,19 +1037,23 @@@ void ff_hevc_deblocking_boundary_streng
                                             int log2_trafo_size);
  int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s);
  int ff_hevc_cu_qp_delta_abs(HEVCContext *s);
 -void ff_hevc_hls_filter(HEVCContext *s, int x, int y);
 +int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s);
 +int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s);
 +void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size);
  void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size);
 +void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
 +                                 int log2_trafo_size, enum ScanType scan_idx,
 +                                 int c_idx);
  
 -void ff_hevc_pps_free(HEVCPPS **ppps);
 +void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size);
  
 -void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth);
  
 -int ff_hevc_extract_rbsp(const uint8_t *src, int length,
+ /**
+  * Extract the raw (unescaped) HEVC bitstream.
+  */
++int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
+                          HEVCNAL *nal);
  extern const uint8_t ff_hevc_qpel_extra_before[4];
  extern const uint8_t ff_hevc_qpel_extra_after[4];
  extern const uint8_t ff_hevc_qpel_extra[4];
index 0000000,32a440b..260f1e1
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,129 +1,145 @@@
 - * This file is part of Libav.
+ /*
+  * HEVC common code
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
 -int ff_hevc_extract_rbsp(const uint8_t *src, int length,
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include <string.h>
+ #include "config.h"
+ #include "libavutil/intreadwrite.h"
+ #include "libavutil/mem.h"
+ #include "hevc.h"
+ /* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication
+  * between these functions would be nice. */
++int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
+                          HEVCNAL *nal)
+ {
+     int i, si, di;
+     uint8_t *dst;
++    if (s)
++        s->skipped_bytes = 0;
+ #define STARTCODE_TEST                                                  \
+         if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) {     \
+             if (src[i + 2] != 3) {                                      \
+                 /* startcode, so we must be past the end */             \
+                 length = i;                                             \
+             }                                                           \
+             break;                                                      \
+         }
+ #if HAVE_FAST_UNALIGNED
+ #define FIND_FIRST_ZERO                                                 \
+         if (i > 0 && !src[i])                                           \
+             i--;                                                        \
+         while (src[i])                                                  \
+             i++
+ #if HAVE_FAST_64BIT
+     for (i = 0; i + 1 < length; i += 9) {
+         if (!((~AV_RN64A(src + i) &
+                (AV_RN64A(src + i) - 0x0100010001000101ULL)) &
+               0x8000800080008080ULL))
+             continue;
+         FIND_FIRST_ZERO;
+         STARTCODE_TEST;
+         i -= 7;
+     }
+ #else
+     for (i = 0; i + 1 < length; i += 5) {
+         if (!((~AV_RN32A(src + i) &
+                (AV_RN32A(src + i) - 0x01000101U)) &
+               0x80008080U))
+             continue;
+         FIND_FIRST_ZERO;
+         STARTCODE_TEST;
+         i -= 3;
+     }
+ #endif /* HAVE_FAST_64BIT */
+ #else
+     for (i = 0; i + 1 < length; i += 2) {
+         if (src[i])
+             continue;
+         if (i > 0 && src[i - 1] == 0)
+             i--;
+         STARTCODE_TEST;
+     }
+ #endif /* HAVE_FAST_UNALIGNED */
+     if (i >= length - 1) { // no escaped 0
+         nal->data     =
+         nal->raw_data = src;
+         nal->size     =
+         nal->raw_size = length;
+         return length;
+     }
+     av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
+                    length + FF_INPUT_BUFFER_PADDING_SIZE);
+     if (!nal->rbsp_buffer)
+         return AVERROR(ENOMEM);
+     dst = nal->rbsp_buffer;
+     memcpy(dst, src, i);
+     si = di = i;
+     while (si + 2 < length) {
+         // remove escapes (very rare 1:2^22)
+         if (src[si + 2] > 3) {
+             dst[di++] = src[si++];
+             dst[di++] = src[si++];
+         } else if (src[si] == 0 && src[si + 1] == 0) {
+             if (src[si + 2] == 3) { // escape
+                 dst[di++] = 0;
+                 dst[di++] = 0;
+                 si       += 3;
++                if (s) {
++                        s->skipped_bytes++;
++                        if (s->skipped_bytes_pos_size < s->skipped_bytes) {
++                        s->skipped_bytes_pos_size *= 2;
++                        av_reallocp_array(&s->skipped_bytes_pos,
++                                s->skipped_bytes_pos_size,
++                                sizeof(*s->skipped_bytes_pos));
++                        if (!s->skipped_bytes_pos)
++                                return AVERROR(ENOMEM);
++                        }
++                        if (s->skipped_bytes_pos)
++                        s->skipped_bytes_pos[s->skipped_bytes-1] = di - 1;
++                }
+                 continue;
+             } else // next start code
+                 goto nsc;
+         }
+         dst[di++] = src[si++];
+     }
+     while (si < length)
+         dst[di++] = src[si++];
+ nsc:
+     memset(dst + di, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+     nal->data = dst;
+     nal->size = di;
+     nal->raw_data = src;
+     nal->raw_size = si;
+     return si;
+ }
++