Merge commit 'd82e1adc2019135a2fc45372e0ed0b5ef107cdd0'
authorMichael Niedermayer <michael@niedermayer.cc>
Sun, 12 Jul 2015 21:31:12 +0000 (23:31 +0200)
committerMichael Niedermayer <michael@niedermayer.cc>
Sun, 12 Jul 2015 21:44:24 +0000 (23:44 +0200)
* commit 'd82e1adc2019135a2fc45372e0ed0b5ef107cdd0':
  hevc: move splitting the packet into NALUs into a separate function

Conflicts:
libavcodec/hevc.c
libavcodec/hevc.h
libavcodec/hevc_parse.c

Merged-by: Michael Niedermayer <michael@niedermayer.cc>
1  2 
libavcodec/hevc.c
libavcodec/hevc.h
libavcodec/hevc_parse.c
libavcodec/hevc_parser.c
libavcodec/hevc_refs.c

@@@ -2336,201 -2341,33 +2336,175 @@@ static int hls_decode_entry(AVCodecCont
      return ctb_addr_ts;
  }
  
 -static void restore_tqb_pixels(HEVCContext *s)
 +static int hls_slice_data(HEVCContext *s)
  {
 -    int min_pu_size = 1 << s->ps.sps->log2_min_pu_size;
 -    int x, y, c_idx;
 -
 -    for (c_idx = 0; c_idx < 3; c_idx++) {
 -        ptrdiff_t stride = s->frame->linesize[c_idx];
 -        int hshift       = s->ps.sps->hshift[c_idx];
 -        int vshift       = s->ps.sps->vshift[c_idx];
 -        for (y = 0; y < s->ps.sps->min_pu_height; y++) {
 -            for (x = 0; x < s->ps.sps->min_pu_width; x++) {
 -                if (s->is_pcm[y * s->ps.sps->min_pu_width + x]) {
 -                    int n;
 -                    int len      = min_pu_size >> hshift;
 -                    uint8_t *src = &s->frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)];
 -                    uint8_t *dst = &s->sao_frame->data[c_idx][((y << s->ps.sps->log2_min_pu_size) >> vshift) * stride + (((x << s->ps.sps->log2_min_pu_size) >> hshift) << s->ps.sps->pixel_shift)];
 -                    for (n = 0; n < (min_pu_size >> vshift); n++) {
 -                        memcpy(dst, src, len);
 -                        src += stride;
 -                        dst += stride;
 -                    }
 -                }
 +    int arg[2];
 +    int ret[2];
 +
 +    arg[0] = 0;
 +    arg[1] = 1;
 +
 +    s->avctx->execute(s->avctx, hls_decode_entry, arg, ret , 1, sizeof(int));
 +    return ret[0];
 +}
 +static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int job, int self_id)
 +{
 +    HEVCContext *s1  = avctxt->priv_data, *s;
 +    HEVCLocalContext *lc;
 +    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
 +    int more_data   = 1;
 +    int *ctb_row_p    = input_ctb_row;
 +    int ctb_row = ctb_row_p[job];
 +    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
 +    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
 +    int thread = ctb_row % s1->threads_number;
 +    int ret;
 +
 +    s = s1->sList[self_id];
 +    lc = s->HEVClc;
 +
 +    if(ctb_row) {
 +        ret = init_get_bits8(&lc->gb, s->data + s->sh.offset[ctb_row - 1], s->sh.size[ctb_row - 1]);
 +
 +        if (ret < 0)
 +            return ret;
 +        ff_init_cabac_decoder(&lc->cc, s->data + s->sh.offset[(ctb_row)-1], s->sh.size[ctb_row - 1]);
 +    }
 +
 +    while(more_data && ctb_addr_ts < s->ps.sps->ctb_size) {
 +        int x_ctb = (ctb_addr_rs % s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size;
 +        int y_ctb = (ctb_addr_rs / s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size;
 +
 +        hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
 +
 +        ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
 +
 +        if (avpriv_atomic_int_get(&s1->wpp_err)){
 +            ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
 +            return 0;
 +        }
 +
 +        ff_hevc_cabac_init(s, ctb_addr_ts);
 +        hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
 +        more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
 +
 +        if (more_data < 0) {
 +            s->tab_slice_address[ctb_addr_rs] = -1;
 +            return more_data;
 +        }
 +
 +        ctb_addr_ts++;
 +
 +        ff_hevc_save_states(s, ctb_addr_ts);
 +        ff_thread_report_progress2(s->avctx, ctb_row, thread, 1);
 +        ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size);
 +
 +        if (!more_data && (x_ctb+ctb_size) < s->ps.sps->width && ctb_row != s->sh.num_entry_point_offsets) {
 +            avpriv_atomic_int_set(&s1->wpp_err,  1);
 +            ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP);
 +            return 0;
 +        }
 +
 +        if ((x_ctb+ctb_size) >= s->ps.sps->width && (y_ctb+ctb_size) >= s->ps.sps->height ) {
 +            ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size);
 +            ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
 +            return ctb_addr_ts;
 +        }
 +        ctb_addr_rs       = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts];
 +        x_ctb+=ctb_size;
 +
 +        if(x_ctb >= s->ps.sps->width) {
 +            break;
 +        }
 +    }
 +    ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP);
 +
 +    return 0;
 +}
 +
 +static int hls_slice_data_wpp(HEVCContext *s, const uint8_t *nal, int length)
 +{
 +    HEVCLocalContext *lc = s->HEVClc;
 +    int *ret = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int));
 +    int *arg = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int));
 +    int offset;
 +    int startheader, cmpt = 0;
 +    int i, j, res = 0;
 +
 +    if (!ret || !arg) {
 +        av_free(ret);
 +        av_free(arg);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +
 +    if (!s->sList[1]) {
 +        ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
 +
 +
 +        for (i = 1; i < s->threads_number; i++) {
 +            s->sList[i] = av_malloc(sizeof(HEVCContext));
 +            memcpy(s->sList[i], s, sizeof(HEVCContext));
 +            s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext));
 +            s->sList[i]->HEVClc = s->HEVClcList[i];
 +        }
 +    }
 +
 +    offset = (lc->gb.index >> 3);
 +
 +    for (j = 0, cmpt = 0, startheader = offset + s->sh.entry_point_offset[0]; j < s->skipped_bytes; j++) {
 +        if (s->skipped_bytes_pos[j] >= offset && s->skipped_bytes_pos[j] < startheader) {
 +            startheader--;
 +            cmpt++;
 +        }
 +    }
 +
 +    for (i = 1; i < s->sh.num_entry_point_offsets; i++) {
 +        offset += (s->sh.entry_point_offset[i - 1] - cmpt);
 +        for (j = 0, cmpt = 0, startheader = offset
 +             + s->sh.entry_point_offset[i]; j < s->skipped_bytes; j++) {
 +            if (s->skipped_bytes_pos[j] >= offset && s->skipped_bytes_pos[j] < startheader) {
 +                startheader--;
 +                cmpt++;
              }
          }
 +        s->sh.size[i - 1] = s->sh.entry_point_offset[i] - cmpt;
 +        s->sh.offset[i - 1] = offset;
 +
 +    }
 +    if (s->sh.num_entry_point_offsets != 0) {
 +        offset += s->sh.entry_point_offset[s->sh.num_entry_point_offsets - 1] - cmpt;
 +        s->sh.size[s->sh.num_entry_point_offsets - 1] = length - offset;
 +        s->sh.offset[s->sh.num_entry_point_offsets - 1] = offset;
 +
      }
 +    s->data = nal;
 +
 +    for (i = 1; i < s->threads_number; i++) {
 +        s->sList[i]->HEVClc->first_qp_group = 1;
 +        s->sList[i]->HEVClc->qp_y = s->sList[0]->HEVClc->qp_y;
 +        memcpy(s->sList[i], s, sizeof(HEVCContext));
 +        s->sList[i]->HEVClc = s->HEVClcList[i];
 +    }
 +
 +    avpriv_atomic_int_set(&s->wpp_err, 0);
 +    ff_reset_entries(s->avctx);
 +
 +    for (i = 0; i <= s->sh.num_entry_point_offsets; i++) {
 +        arg[i] = i;
 +        ret[i] = 0;
 +    }
 +
 +    if (s->ps.pps->entropy_coding_sync_enabled_flag)
 +        s->avctx->execute2(s->avctx, (void *) hls_decode_entry_wpp, arg, ret, s->sh.num_entry_point_offsets + 1);
 +
 +    for (i = 0; i <= s->sh.num_entry_point_offsets; i++)
 +        res += ret[i];
 +    av_free(ret);
 +    av_free(arg);
 +    return res;
  }
  
- /**
-  * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit,
-  * 0 if the unit should be skipped, 1 otherwise
-  */
- static int hls_nal_unit(HEVCNAL *nal, AVCodecContext *avctx)
- {
-     GetBitContext *gb = &nal->gb;
-     int nuh_layer_id;
-     if (get_bits1(gb) != 0)
-         return AVERROR_INVALIDDATA;
-     nal->type = get_bits(gb, 6);
-     nuh_layer_id   = get_bits(gb, 6);
-     nal->temporal_id = get_bits(gb, 3) - 1;
-     if (nal->temporal_id < 0)
-         return AVERROR_INVALIDDATA;
-     av_log(avctx, AV_LOG_DEBUG,
-            "nal_unit_type: %d, nuh_layer_id: %d, temporal_id: %d\n",
-            nal->type, nuh_layer_id, nal->temporal_id);
-     return nuh_layer_id == 0;
- }
  static int set_side_data(HEVCContext *s)
  {
      AVFrame *out = s->ref->frame;
  
  static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
  {
-     int i, consumed, ret = 0;
+     int i, ret = 0;
  
      s->ref = NULL;
 +    s->last_eos = s->eos;
      s->eos = 0;
  
      /* split the input packet into NAL units, so we know the upper bound on the
       * number of slices in the frame */
-     s->nb_nals = 0;
-     while (length >= 4) {
-         HEVCNAL *nal;
-         int extract_length = 0;
-         if (s->is_nalff) {
-             int i;
-             for (i = 0; i < s->nal_length_size; i++)
-                 extract_length = (extract_length << 8) | buf[i];
-             buf    += s->nal_length_size;
-             length -= s->nal_length_size;
-             if (extract_length > length) {
-                 av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");
-                 ret = AVERROR_INVALIDDATA;
-                 goto fail;
-             }
-         } else {
-             /* search start code */
-             while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {
-                 ++buf;
-                 --length;
-                 if (length < 4) {
-                     av_log(s->avctx, AV_LOG_ERROR, "No start code is found.\n");
-                     ret = AVERROR_INVALIDDATA;
-                     goto fail;
-                 }
-             }
-             buf           += 3;
-             length        -= 3;
-         }
-         if (!s->is_nalff)
-             extract_length = length;
-         if (s->nals_allocated < s->nb_nals + 1) {
-             int new_size = s->nals_allocated + 1;
-             void *tmp = av_realloc_array(s->nals, new_size, sizeof(*s->nals));
-             ret = AVERROR(ENOMEM);
-             if (!tmp) {
-                 goto fail;
-             }
-             s->nals = tmp;
-             memset(s->nals + s->nals_allocated, 0,
-                    (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;
-         }
-         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(s, buf, extract_length, nal);
-         if (consumed < 0) {
-             ret = consumed;
-             goto fail;
-         }
-         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(&nal->gb, nal->data, nal->size);
-         if (ret < 0)
-             goto fail;
-         ret = hls_nal_unit(nal, s->avctx);
-         if (ret <= 0) {
-             if (ret < 0) {
-                 av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",
-                        nal->type);
-             }
-             s->nb_nals--;
-             goto skip_nal;
-         }
 -    ret = ff_hevc_split_packet(&s->pkt, buf, length, s->avctx, s->is_nalff,
++    ret = ff_hevc_split_packet(s, &s->pkt, buf, length, s->avctx, s->is_nalff,
+                                s->nal_length_size);
+     if (ret < 0) {
+         av_log(s->avctx, AV_LOG_ERROR,
+                "Error splitting the input into NAL units.\n");
+         return ret;
+     }
  
-         if (nal->type == NAL_EOB_NUT ||
-             nal->type == NAL_EOS_NUT)
+     for (i = 0; i < s->pkt.nb_nals; i++) {
+         if (s->pkt.nals[i].type == NAL_EOB_NUT ||
+             s->pkt.nals[i].type == NAL_EOS_NUT)
              s->eos = 1;
- skip_nal:
-         buf    += consumed;
-         length -= consumed;
      }
  
      /* parse the NAL units */
-     for (i = 0; i < s->nb_nals; i++) {
+     for (i = 0; i < s->pkt.nb_nals; i++) {
 +        s->skipped_bytes = s->skipped_bytes_nal[i];
 +        s->skipped_bytes_pos = s->skipped_bytes_pos_nal[i];
 +
-         ret = decode_nal_unit(s, &s->nals[i]);
+         ret = decode_nal_unit(s, &s->pkt.nals[i]);
          if (ret < 0) {
              av_log(s->avctx, AV_LOG_WARNING,
                     "Error parsing NAL unit #%d.\n", i);
@@@ -3087,19 -2821,7 +2970,19 @@@ static av_cold int hevc_decode_free(AVC
  
      av_freep(&s->md5_ctx);
  
-     for(i=0; i < s->nals_allocated; i++) {
 -    av_frame_free(&s->tmp_frame);
++    for(i=0; i < s->pkt.nals_allocated; i++) {
 +        av_freep(&s->skipped_bytes_pos_nal[i]);
 +    }
 +    av_freep(&s->skipped_bytes_pos_size_nal);
 +    av_freep(&s->skipped_bytes_nal);
 +    av_freep(&s->skipped_bytes_pos_nal);
 +
 +    av_freep(&s->cabac_state);
 +
 +    for (i = 0; i < 3; i++) {
 +        av_freep(&s->sao_pixel_buffer_h[i]);
 +        av_freep(&s->sao_pixel_buffer_v[i]);
 +    }
      av_frame_free(&s->output_frame);
  
      for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
          av_buffer_unref(&s->ps.sps_list[i]);
      for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++)
          av_buffer_unref(&s->ps.pps_list[i]);
 +    s->ps.sps = NULL;
 +    s->ps.pps = NULL;
 +    s->ps.vps = NULL;
 +
 +    av_freep(&s->sh.entry_point_offset);
 +    av_freep(&s->sh.offset);
 +    av_freep(&s->sh.size);
 +
 +    for (i = 1; i < s->threads_number; i++) {
 +        HEVCLocalContext *lc = s->HEVClcList[i];
 +        if (lc) {
 +            av_freep(&s->HEVClcList[i]);
 +            av_freep(&s->sList[i]);
 +        }
 +    }
 +    if (s->HEVClc == s->HEVClcList[0])
 +        s->HEVClc = NULL;
 +    av_freep(&s->HEVClcList[0]);
  
-     for (i = 0; i < s->nals_allocated; i++)
-         av_freep(&s->nals[i].rbsp_buffer);
-     av_freep(&s->nals);
-     s->nals_allocated = 0;
+     for (i = 0; i < s->pkt.nals_allocated; i++)
+         av_freep(&s->pkt.nals[i].rbsp_buffer);
+     av_freep(&s->pkt.nals);
+     s->pkt.nals_allocated = 0;
  
      return 0;
  }
@@@ -761,11 -718,31 +761,18 @@@ typedef struct HEVCNAL 
      int temporal_id;
  } HEVCNAL;
  
 -struct HEVCContext;
 -
 -typedef struct HEVCPredContext {
 -    void (*intra_pred[4])(struct HEVCContext *s, int x0, int y0, int c_idx);
 -
 -    void (*pred_planar[4])(uint8_t *src, const uint8_t *top,
 -                           const uint8_t *left, ptrdiff_t stride);
 -    void (*pred_dc)(uint8_t *src, const uint8_t *top, const uint8_t *left,
 -                    ptrdiff_t stride, int log2_size, int c_idx);
 -    void (*pred_angular[4])(uint8_t *src, const uint8_t *top,
 -                            const uint8_t *left, ptrdiff_t stride,
 -                            int c_idx, int mode);
 -} HEVCPredContext;
 -
+ /* an input packet split into unescaped NAL units */
+ typedef struct HEVCPacket {
+     HEVCNAL *nals;
+     int nb_nals;
+     int nals_allocated;
+ } HEVCPacket;
  typedef struct HEVCLocalContext {
 -    DECLARE_ALIGNED(16, int16_t, mc_buffer[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]);
      uint8_t cabac_state[HEVC_CONTEXTS];
  
 +    uint8_t stat_coeff[4];
 +
      uint8_t first_qp_group;
  
      GetBitContext gb;
@@@ -888,21 -850,7 +895,19 @@@ typedef struct HEVCContext 
      uint16_t seq_decode;
      uint16_t seq_output;
  
-     HEVCNAL *nals;
-     int nb_nals;
-     int nals_allocated;
 +    int enable_parallel_tiles;
 +    int wpp_err;
 +    int skipped_bytes;
 +    int *skipped_bytes_pos;
 +    int skipped_bytes_pos_size;
 +
 +    int *skipped_bytes_nal;
 +    int **skipped_bytes_pos_nal;
 +    int *skipped_bytes_pos_size_nal;
 +
 +    const uint8_t *data;
 +
+     HEVCPacket pkt;
      // type of the first VCL NAL of the current frame
      enum NALUnitType first_nal_type;
  
@@@ -1065,9 -1024,15 +1070,15 @@@ void ff_hevc_hls_mvd_coding(HEVCContex
  /**
   * Extract the raw (unescaped) HEVC bitstream.
   */
 -int ff_hevc_extract_rbsp(const uint8_t *src, int length,
 +int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
                           HEVCNAL *nal);
  
 -int ff_hevc_split_packet(HEVCPacket *pkt, const uint8_t *buf, int length,
+ /**
+  * Split an input packet into NAL units.
+  */
++int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length,
+                          AVCodecContext *avctx, int is_nalff, int nal_length_size);
  int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
                             uint8_t *buf, int buf_size);
  
@@@ -143,3 -128,101 +143,132 @@@ nsc
      return si;
  }
  
 -           "nal_unit_type: %d, nuh_layer_id: %dtemporal_id: %d\n",
+ /**
+  * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit,
+  * 0 if the unit should be skipped, 1 otherwise
+  */
+ static int hls_nal_unit(HEVCNAL *nal, AVCodecContext *avctx)
+ {
+     GetBitContext *gb = &nal->gb;
+     int nuh_layer_id;
+     if (get_bits1(gb) != 0)
+         return AVERROR_INVALIDDATA;
+     nal->type = get_bits(gb, 6);
+     nuh_layer_id   = get_bits(gb, 6);
+     nal->temporal_id = get_bits(gb, 3) - 1;
+     if (nal->temporal_id < 0)
+         return AVERROR_INVALIDDATA;
+     av_log(avctx, AV_LOG_DEBUG,
 -int ff_hevc_split_packet(HEVCPacket *pkt, const uint8_t *buf, int length,
++           "nal_unit_type: %d, nuh_layer_id: %d, temporal_id: %d\n",
+            nal->type, nuh_layer_id, nal->temporal_id);
+     return nuh_layer_id == 0;
+ }
 -            if (buf[2] == 0) {
 -                length--;
 -                buf++;
 -                continue;
++int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length,
+                          AVCodecContext *avctx, int is_nalff, int nal_length_size)
+ {
+     int consumed, ret = 0;
+     pkt->nb_nals = 0;
+     while (length >= 4) {
+         HEVCNAL *nal;
+         int extract_length = 0;
+         if (is_nalff) {
+             int i;
+             for (i = 0; i < nal_length_size; i++)
+                 extract_length = (extract_length << 8) | buf[i];
+             buf    += nal_length_size;
+             length -= nal_length_size;
+             if (extract_length > length) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");
+                 return AVERROR_INVALIDDATA;
+             }
+         } else {
 -            if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1)
 -                return AVERROR_INVALIDDATA;
++            /* search start code */
++            while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {
++                ++buf;
++                --length;
++                if (length < 4) {
++                    av_log(avctx, AV_LOG_ERROR, "No start code is found.\n");
++                    return AVERROR_INVALIDDATA;
++                }
+             }
 -            HEVCNAL *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*tmp));
+             buf           += 3;
+             length        -= 3;
+             extract_length = length;
+         }
+         if (pkt->nals_allocated < pkt->nb_nals + 1) {
+             int new_size = pkt->nals_allocated + 1;
 -                   (new_size - pkt->nals_allocated) * sizeof(*tmp));
++            void *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*pkt->nals));
++
+             if (!tmp)
+                 return AVERROR(ENOMEM);
+             pkt->nals = tmp;
+             memset(pkt->nals + pkt->nals_allocated, 0,
 -        nal = &pkt->nals[pkt->nb_nals++];
++                   (new_size - pkt->nals_allocated) * sizeof(*pkt->nals));
++
++            tmp = av_realloc_array(s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal));
++            if (!tmp)
++                return AVERROR(ENOMEM);
++            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)
++                return AVERROR(ENOMEM);
++            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)
++                return AVERROR(ENOMEM);
++            s->skipped_bytes_pos_nal = tmp;
++
++            s->skipped_bytes_pos_size_nal[pkt->nals_allocated] = 1024; // initial buffer size
++            s->skipped_bytes_pos_nal[pkt->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[pkt->nals_allocated], sizeof(*s->skipped_bytes_pos));
++            if (!s->skipped_bytes_pos_nal[pkt->nals_allocated])
++                return AVERROR(ENOMEM);
++
+             pkt->nals_allocated = new_size;
+         }
 -        consumed = ff_hevc_extract_rbsp(buf, extract_length, nal);
++        s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[pkt->nb_nals];
++        s->skipped_bytes_pos = s->skipped_bytes_pos_nal[pkt->nb_nals];
++        nal = &pkt->nals[pkt->nb_nals];
++        consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal);
+         if (consumed < 0)
+             return consumed;
++        s->skipped_bytes_nal[pkt->nb_nals] = s->skipped_bytes;
++        s->skipped_bytes_pos_size_nal[pkt->nb_nals] = s->skipped_bytes_pos_size;
++        s->skipped_bytes_pos_nal[pkt->nb_nals++] = s->skipped_bytes_pos;
++
+         ret = init_get_bits8(&nal->gb, nal->data, nal->size);
+         if (ret < 0)
+             return ret;
+         ret = hls_nal_unit(nal, avctx);
+         if (ret <= 0) {
+             if (ret < 0) {
+                 av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",
+                        nal->type);
+             }
+             pkt->nb_nals--;
+         }
+         buf    += consumed;
+         length -= consumed;
+     }
+     return 0;
+ }
++
@@@ -76,190 -71,7 +76,191 @@@ static int hevc_find_frame_end(AVCodecP
      return END_NOT_FOUND;
  }
  
 -static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 +/**
 + * Parse NAL units of found picture and decode some basic information.
 + *
 + * @param s parser context.
 + * @param avctx codec context.
 + * @param buf buffer with field/frame data.
 + * @param buf_size size of the buffer.
 + */
 +static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx,
 +                      const uint8_t *buf, int buf_size)
 +{
 +    HEVCContext   *h  = &((HEVCParseContext *)s->priv_data)->h;
 +    GetBitContext *gb = &h->HEVClc->gb;
 +    SliceHeader   *sh = &h->sh;
 +    HEVCParamSets *ps = &h->ps;
++    HEVCPacket   *pkt = &h->pkt;
 +    const uint8_t *buf_end = buf + buf_size;
 +    int state = -1, i;
 +    HEVCNAL *nal;
 +
 +    /* set some sane default values */
 +    s->pict_type         = AV_PICTURE_TYPE_I;
 +    s->key_frame         = 0;
 +    s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
 +
 +    h->avctx = avctx;
 +
 +    if (!buf_size)
 +        return 0;
 +
-     if (h->nals_allocated < 1) {
-         HEVCNAL *tmp = av_realloc_array(h->nals, 1, sizeof(*tmp));
++    if (pkt->nals_allocated < 1) {
++        HEVCNAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
 +        if (!tmp)
 +            return AVERROR(ENOMEM);
-         h->nals = tmp;
-         memset(h->nals, 0, sizeof(*tmp));
-         h->nals_allocated = 1;
++        pkt->nals = tmp;
++        memset(pkt->nals, 0, sizeof(*tmp));
++        pkt->nals_allocated = 1;
 +    }
 +
-     nal = &h->nals[0];
++    nal = &pkt->nals[0];
 +
 +    for (;;) {
 +        int src_length, consumed;
 +        buf = avpriv_find_start_code(buf, buf_end, &state);
 +        if (--buf + 2 >= buf_end)
 +            break;
 +        src_length = buf_end - buf;
 +
 +        h->nal_unit_type = (*buf >> 1) & 0x3f;
 +        h->temporal_id   = (*(buf + 1) & 0x07) - 1;
 +        if (h->nal_unit_type <= NAL_CRA_NUT) {
 +            // Do not walk the whole buffer just to decode slice segment header
 +            if (src_length > 20)
 +                src_length = 20;
 +        }
 +
 +        consumed = ff_hevc_extract_rbsp(h, buf, src_length, nal);
 +        if (consumed < 0)
 +            return consumed;
 +
 +        init_get_bits8(gb, nal->data + 2, nal->size);
 +        switch (h->nal_unit_type) {
 +        case NAL_VPS:
 +            ff_hevc_decode_nal_vps(gb, avctx, ps);
 +            break;
 +        case NAL_SPS:
 +            ff_hevc_decode_nal_sps(gb, avctx, ps, h->apply_defdispwin);
 +            break;
 +        case NAL_PPS:
 +            ff_hevc_decode_nal_pps(gb, avctx, ps);
 +            break;
 +        case NAL_SEI_PREFIX:
 +        case NAL_SEI_SUFFIX:
 +            ff_hevc_decode_nal_sei(h);
 +            break;
 +        case NAL_TRAIL_N:
 +        case NAL_TRAIL_R:
 +        case NAL_TSA_N:
 +        case NAL_TSA_R:
 +        case NAL_STSA_N:
 +        case NAL_STSA_R:
 +        case NAL_RADL_N:
 +        case NAL_RADL_R:
 +        case NAL_RASL_N:
 +        case NAL_RASL_R:
 +        case NAL_BLA_W_LP:
 +        case NAL_BLA_W_RADL:
 +        case NAL_BLA_N_LP:
 +        case NAL_IDR_W_RADL:
 +        case NAL_IDR_N_LP:
 +        case NAL_CRA_NUT:
 +            sh->first_slice_in_pic_flag = get_bits1(gb);
 +            s->picture_structure = h->picture_struct;
 +            s->field_order = h->picture_struct;
 +
 +            if (IS_IRAP(h)) {
 +                s->key_frame = 1;
 +                sh->no_output_of_prior_pics_flag = get_bits1(gb);
 +            }
 +
 +            sh->pps_id = get_ue_golomb(gb);
 +            if (sh->pps_id >= MAX_PPS_COUNT || !ps->pps_list[sh->pps_id]) {
 +                av_log(h->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id);
 +                return AVERROR_INVALIDDATA;
 +            }
 +            ps->pps = (HEVCPPS*)ps->pps_list[sh->pps_id]->data;
 +
 +            if (ps->pps->sps_id >= MAX_SPS_COUNT || !ps->sps_list[ps->pps->sps_id]) {
 +                av_log(h->avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", ps->pps->sps_id);
 +                return AVERROR_INVALIDDATA;
 +            }
 +            if (ps->sps != (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data) {
 +                ps->sps = (HEVCSPS*)ps->sps_list[ps->pps->sps_id]->data;
 +                ps->vps = (HEVCVPS*)ps->vps_list[ps->sps->vps_id]->data;
 +            }
 +
 +            if (!sh->first_slice_in_pic_flag) {
 +                int slice_address_length;
 +
 +                if (ps->pps->dependent_slice_segments_enabled_flag)
 +                    sh->dependent_slice_segment_flag = get_bits1(gb);
 +                else
 +                    sh->dependent_slice_segment_flag = 0;
 +
 +                slice_address_length = av_ceil_log2_c(ps->sps->ctb_width *
 +                                                      ps->sps->ctb_height);
 +                sh->slice_segment_addr = slice_address_length ? get_bits(gb, slice_address_length) : 0;
 +                if (sh->slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) {
 +                    av_log(h->avctx, AV_LOG_ERROR, "Invalid slice segment address: %u.\n",
 +                           sh->slice_segment_addr);
 +                    return AVERROR_INVALIDDATA;
 +                }
 +            } else
 +                sh->dependent_slice_segment_flag = 0;
 +
 +            if (sh->dependent_slice_segment_flag)
 +                break;
 +
 +            for (i = 0; i < ps->pps->num_extra_slice_header_bits; i++)
 +                skip_bits(gb, 1); // slice_reserved_undetermined_flag[]
 +
 +            sh->slice_type = get_ue_golomb(gb);
 +            if (!(sh->slice_type == I_SLICE || sh->slice_type == P_SLICE ||
 +                  sh->slice_type == B_SLICE)) {
 +                av_log(h->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n",
 +                       sh->slice_type);
 +                return AVERROR_INVALIDDATA;
 +            }
 +            s->pict_type = sh->slice_type == B_SLICE ? AV_PICTURE_TYPE_B :
 +                           sh->slice_type == P_SLICE ? AV_PICTURE_TYPE_P :
 +                                                       AV_PICTURE_TYPE_I;
 +
 +            if (ps->pps->output_flag_present_flag)
 +                sh->pic_output_flag = get_bits1(gb);
 +
 +            if (ps->sps->separate_colour_plane_flag)
 +                sh->colour_plane_id = get_bits(gb, 2);
 +
 +            if (!IS_IDR(h)) {
 +                sh->pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb);
 +                s->output_picture_number = h->poc = ff_hevc_compute_poc(h, sh->pic_order_cnt_lsb);
 +            } else
 +                s->output_picture_number = h->poc = 0;
 +
 +            if (h->temporal_id == 0 &&
 +                h->nal_unit_type != NAL_TRAIL_N &&
 +                h->nal_unit_type != NAL_TSA_N &&
 +                h->nal_unit_type != NAL_STSA_N &&
 +                h->nal_unit_type != NAL_RADL_N &&
 +                h->nal_unit_type != NAL_RASL_N &&
 +                h->nal_unit_type != NAL_RADL_R &&
 +                h->nal_unit_type != NAL_RASL_R)
 +                h->pocTid0 = h->poc;
 +
 +            return 0; /* no need to evaluate the rest */
 +        }
 +        buf += consumed;
 +    }
 +    /* didn't find a picture! */
 +    av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n");
 +    return -1;
 +}
 +
 +static int hevc_parse(AVCodecParserContext *s,
 +                      AVCodecContext *avctx,
                        const uint8_t **poutbuf, int *poutbuf_size,
                        const uint8_t *buf, int buf_size)
  {
@@@ -306,48 -116,10 +307,49 @@@ static int hevc_split(AVCodecContext *a
      return 0;
  }
  
-     for (i = 0; i < h->nals_allocated; i++)
-         av_freep(&h->nals[i].rbsp_buffer);
-     av_freep(&h->nals);
-     h->nals_allocated = 0;
 +static int hevc_init(AVCodecParserContext *s)
 +{
 +    HEVCContext  *h  = &((HEVCParseContext *)s->priv_data)->h;
 +    h->HEVClc = av_mallocz(sizeof(HEVCLocalContext));
 +    if (!h->HEVClc)
 +        return AVERROR(ENOMEM);
 +    h->skipped_bytes_pos_size = INT_MAX;
 +
 +    return 0;
 +}
 +
 +static void hevc_close(AVCodecParserContext *s)
 +{
 +    int i;
 +    HEVCContext  *h  = &((HEVCParseContext *)s->priv_data)->h;
 +    ParseContext *pc = &((HEVCParseContext *)s->priv_data)->pc;
 +    HEVCParamSets *ps = &h->ps;
++    HEVCPacket   *pkt = &h->pkt;
 +
 +    av_freep(&h->skipped_bytes_pos);
 +    av_freep(&h->HEVClc);
 +    av_freep(&pc->buffer);
 +
 +    for (i = 0; i < FF_ARRAY_ELEMS(ps->vps_list); i++)
 +        av_buffer_unref(&ps->vps_list[i]);
 +    for (i = 0; i < FF_ARRAY_ELEMS(ps->sps_list); i++)
 +        av_buffer_unref(&ps->sps_list[i]);
 +    for (i = 0; i < FF_ARRAY_ELEMS(ps->pps_list); i++)
 +        av_buffer_unref(&ps->pps_list[i]);
 +
 +    ps->sps = NULL;
 +
++    for (i = 0; i < pkt->nals_allocated; i++)
++        av_freep(&pkt->nals[i].rbsp_buffer);
++    av_freep(&pkt->nals);
++    pkt->nals_allocated = 0;
 +}
 +
  AVCodecParser ff_hevc_parser = {
      .codec_ids      = { AV_CODEC_ID_HEVC },
 -    .priv_data_size = sizeof(ParseContext),
 +    .priv_data_size = sizeof(HEVCParseContext),
 +    .parser_init    = hevc_init,
      .parser_parse   = hevc_parse,
 -    .parser_close   = ff_parse_close,
 +    .parser_close   = hevc_close,
      .split          = hevc_split,
  };
Simple merge