]> git.sesse.net Git - ffmpeg/commitdiff
Merge commit 'c359d624d3efc3fd1d83210d78c4152bd329b765'
authorJames Almer <jamrial@gmail.com>
Thu, 23 Mar 2017 17:27:48 +0000 (14:27 -0300)
committerJames Almer <jamrial@gmail.com>
Thu, 23 Mar 2017 17:27:48 +0000 (14:27 -0300)
* commit 'c359d624d3efc3fd1d83210d78c4152bd329b765':
  hevcdec: move decoder-independent declarations into a separate header

Merged-by: James Almer <jamrial@gmail.com>
14 files changed:
1  2 
libavcodec/h2645_parse.c
libavcodec/hevc_mp4toannexb_bsf.c
libavcodec/hevc_parse.c
libavcodec/hevc_parser.c
libavcodec/hevc_ps.c
libavcodec/hevc_refs.c
libavcodec/hevc_sei.c
libavcodec/hevcdec.c
libavcodec/hevcdec.h
libavcodec/mediacodecdec.c
libavcodec/qsvenc_hevc.c
libavcodec/vaapi_encode_h265.c
libavformat/hevc.c
libavformat/hevcdec.c

index c14c4152c0176da1220f37b75a7fbf6179038c91,8492425e4489659c082b3f893d7d4468eb35b581..b0d9ff66f00f305af17e9382c5dc6e612eaab057
@@@ -26,7 -26,6 +26,7 @@@
  #include "libavutil/intreadwrite.h"
  #include "libavutil/mem.h"
  
- #include "hevcdec.h"
++#include "hevc.h"
  #include "h2645_parse.h"
  
  int ff_h2645_extract_rbsp(const uint8_t *src, int length,
@@@ -147,38 -127,6 +147,38 @@@ nsc
      return si;
  }
  
-     case NAL_TRAIL_N    : return "TRAIL_N";
-     case NAL_TRAIL_R    : return "TRAIL_R";
-     case NAL_TSA_N      : return "TSA_N";
-     case NAL_TSA_R      : return "TSA_R";
-     case NAL_STSA_N     : return "STSA_N";
-     case NAL_STSA_R     : return "STSA_R";
-     case NAL_RADL_N     : return "RADL_N";
-     case NAL_RADL_R     : return "RADL_R";
-     case NAL_RASL_N     : return "RASL_N";
-     case NAL_RASL_R     : return "RASL_R";
-     case NAL_BLA_W_LP   : return "BLA_W_LP";
-     case NAL_BLA_W_RADL : return "BLA_W_RADL";
-     case NAL_BLA_N_LP   : return "BLA_N_LP";
-     case NAL_IDR_W_RADL : return "IDR_W_RADL";
-     case NAL_IDR_N_LP   : return "IDR_N_LP";
-     case NAL_CRA_NUT    : return "CRA_NUT";
-     case NAL_VPS        : return "VPS";
-     case NAL_SPS        : return "SPS";
-     case NAL_PPS        : return "PPS";
-     case NAL_AUD        : return "AUD";
-     case NAL_EOS_NUT    : return "EOS_NUT";
-     case NAL_EOB_NUT    : return "EOB_NUT";
-     case NAL_FD_NUT     : return "FD_NUT";
-     case NAL_SEI_PREFIX : return "SEI_PREFIX";
-     case NAL_SEI_SUFFIX : return "SEI_SUFFIX";
 +static const char *nal_unit_name(int nal_type)
 +{
 +    switch(nal_type) {
++    case HEVC_NAL_TRAIL_N    : return "TRAIL_N";
++    case HEVC_NAL_TRAIL_R    : return "TRAIL_R";
++    case HEVC_NAL_TSA_N      : return "TSA_N";
++    case HEVC_NAL_TSA_R      : return "TSA_R";
++    case HEVC_NAL_STSA_N     : return "STSA_N";
++    case HEVC_NAL_STSA_R     : return "STSA_R";
++    case HEVC_NAL_RADL_N     : return "RADL_N";
++    case HEVC_NAL_RADL_R     : return "RADL_R";
++    case HEVC_NAL_RASL_N     : return "RASL_N";
++    case HEVC_NAL_RASL_R     : return "RASL_R";
++    case HEVC_NAL_BLA_W_LP   : return "BLA_W_LP";
++    case HEVC_NAL_BLA_W_RADL : return "BLA_W_RADL";
++    case HEVC_NAL_BLA_N_LP   : return "BLA_N_LP";
++    case HEVC_NAL_IDR_W_RADL : return "IDR_W_RADL";
++    case HEVC_NAL_IDR_N_LP   : return "IDR_N_LP";
++    case HEVC_NAL_CRA_NUT    : return "CRA_NUT";
++    case HEVC_NAL_VPS        : return "VPS";
++    case HEVC_NAL_SPS        : return "SPS";
++    case HEVC_NAL_PPS        : return "PPS";
++    case HEVC_NAL_AUD        : return "AUD";
++    case HEVC_NAL_EOS_NUT    : return "EOS_NUT";
++    case HEVC_NAL_EOB_NUT    : return "EOB_NUT";
++    case HEVC_NAL_FD_NUT     : return "FD_NUT";
++    case HEVC_NAL_SEI_PREFIX : return "SEI_PREFIX";
++    case HEVC_NAL_SEI_SUFFIX : return "SEI_SUFFIX";
 +    default : return "?";
 +    }
 +}
 +
  static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
  {
      int size = nal->size;
Simple merge
index d6bf8723037354d5fbebcb6592d59584366de798,0000000000000000000000000000000000000000..6c1138e015f1152e2c4339a773ac6575c1bacebb
mode 100644,000000..100644
--- /dev/null
@@@ -1,134 -1,0 +1,134 @@@
- #include "hevcdec.h"
 +/*
 + * This file is part of FFmpeg.
 + *
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "bytestream.h"
 +#include "h2645_parse.h"
-         case NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, logctx, ps);    break;
-         case NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, logctx, ps, 1); break;
-         case NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, logctx, ps);    break;
-         case NAL_TRAIL_R:
-         case NAL_TRAIL_N:
-         case NAL_TSA_N:
-         case NAL_TSA_R:
-         case NAL_STSA_N:
-         case NAL_STSA_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:
-         case NAL_RADL_N:
-         case NAL_RADL_R:
-         case NAL_RASL_N:
-         case NAL_RASL_R:
++#include "hevc.h"
 +#include "hevc_parse.h"
 +
 +static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets *ps,
 +                                 int is_nalff, int nal_length_size, void *logctx)
 +{
 +    int i;
 +    int ret = 0;
 +    H2645Packet pkt = { 0 };
 +
 +    ret = ff_h2645_packet_split(&pkt, buf, buf_size, logctx, is_nalff, nal_length_size, AV_CODEC_ID_HEVC, 1);
 +    if (ret < 0) {
 +        goto done;
 +    }
 +
 +    for (i = 0; i < pkt.nb_nals; i++) {
 +        H2645NAL *nal = &pkt.nals[i];
 +
 +        /* ignore everything except parameter sets and VCL NALUs */
 +        switch (nal->type) {
++        case HEVC_NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, logctx, ps);    break;
++        case HEVC_NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, logctx, ps, 1); break;
++        case HEVC_NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, logctx, ps);    break;
++        case HEVC_NAL_TRAIL_R:
++        case HEVC_NAL_TRAIL_N:
++        case HEVC_NAL_TSA_N:
++        case HEVC_NAL_TSA_R:
++        case HEVC_NAL_STSA_N:
++        case HEVC_NAL_STSA_R:
++        case HEVC_NAL_BLA_W_LP:
++        case HEVC_NAL_BLA_W_RADL:
++        case HEVC_NAL_BLA_N_LP:
++        case HEVC_NAL_IDR_W_RADL:
++        case HEVC_NAL_IDR_N_LP:
++        case HEVC_NAL_CRA_NUT:
++        case HEVC_NAL_RADL_N:
++        case HEVC_NAL_RADL_R:
++        case HEVC_NAL_RASL_N:
++        case HEVC_NAL_RASL_R:
 +            av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", nal->type);
 +            ret = AVERROR_INVALIDDATA;
 +            goto done;
 +            break;
 +        }
 +    }
 +
 +done:
 +    ff_h2645_packet_uninit(&pkt);
 +    return ret;
 +}
 +
 +int ff_hevc_decode_extradata(const uint8_t *data, int size, HEVCParamSets *ps,
 +                             int *is_nalff, int *nal_length_size,
 +                             int err_recognition, void *logctx)
 +{
 +    int ret = 0;
 +    GetByteContext gb;
 +
 +    bytestream2_init(&gb, data, size);
 +
 +    if (size > 3 && (data[0] || data[1] || data[2] > 1)) {
 +        /* It seems the extradata is encoded as hvcC format.
 +         * Temporarily, we support configurationVersion==0 until 14496-15 3rd
 +         * is finalized. When finalized, configurationVersion will be 1 and we
 +         * can recognize hvcC by checking if avctx->extradata[0]==1 or not. */
 +        int i, j, num_arrays, nal_len_size;
 +
 +        *is_nalff = 1;
 +
 +        bytestream2_skip(&gb, 21);
 +        nal_len_size = (bytestream2_get_byte(&gb) & 3) + 1;
 +        num_arrays   = bytestream2_get_byte(&gb);
 +
 +        /* nal units in the hvcC always have length coded with 2 bytes,
 +         * so put a fake nal_length_size = 2 while parsing them */
 +        *nal_length_size = 2;
 +
 +        /* Decode nal units from hvcC. */
 +        for (i = 0; i < num_arrays; i++) {
 +            int type = bytestream2_get_byte(&gb) & 0x3f;
 +            int cnt  = bytestream2_get_be16(&gb);
 +
 +            for (j = 0; j < cnt; j++) {
 +                // +2 for the nal size field
 +                int nalsize = bytestream2_peek_be16(&gb) + 2;
 +                if (bytestream2_get_bytes_left(&gb) < nalsize) {
 +                    av_log(logctx, AV_LOG_ERROR,
 +                           "Invalid NAL unit size in extradata.\n");
 +                    return AVERROR_INVALIDDATA;
 +                }
 +
 +                ret = hevc_decode_nal_units(gb.buffer, nalsize, ps, *is_nalff, *nal_length_size, logctx);
 +                if (ret < 0) {
 +                    av_log(logctx, AV_LOG_ERROR,
 +                           "Decoding nal unit %d %d from hvcC failed\n",
 +                           type, i);
 +                    return ret;
 +                }
 +                bytestream2_skip(&gb, nalsize);
 +            }
 +        }
 +
 +        /* Now store right nal length size, that will be used to parse
 +         * all other nals */
 +        *nal_length_size = nal_len_size;
 +    } else {
 +        *is_nalff = 0;
 +        ret = hevc_decode_nal_units(data, size, ps, *is_nalff, *nal_length_size, logctx);
 +        if (ret < 0)
 +            return ret;
 +    }
 +
 +    return ret;
 +}
index 22a9623601bf5f01276c382c2338b30ba275765e,49e712269bd6c68b4a09ff138befc9853eac53b4..2a5190dcb86896ef302f2a2f4a4bca523e1aee01
@@@ -99,31 -93,25 +100,31 @@@ static int parse_nal_units(AVCodecParse
  
          /* ignore everything except parameter sets and VCL NALUs */
          switch (nal->type) {
-         case NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, avctx, &ctx->ps);    break;
-         case NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, avctx, &ctx->ps, 1); break;
-         case NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, avctx, &ctx->ps);    break;
-         case NAL_TRAIL_R:
-         case NAL_TRAIL_N:
-         case NAL_TSA_N:
-         case NAL_TSA_R:
-         case NAL_STSA_N:
-         case NAL_STSA_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:
-         case NAL_RADL_N:
-         case NAL_RADL_R:
-         case NAL_RASL_N:
-         case NAL_RASL_R:
+         case HEVC_NAL_VPS: ff_hevc_decode_nal_vps(&nal->gb, avctx, &ctx->ps);    break;
+         case HEVC_NAL_SPS: ff_hevc_decode_nal_sps(&nal->gb, avctx, &ctx->ps, 1); break;
+         case HEVC_NAL_PPS: ff_hevc_decode_nal_pps(&nal->gb, avctx, &ctx->ps);    break;
+         case HEVC_NAL_TRAIL_R:
+         case HEVC_NAL_TRAIL_N:
+         case HEVC_NAL_TSA_N:
+         case HEVC_NAL_TSA_R:
+         case HEVC_NAL_STSA_N:
+         case HEVC_NAL_STSA_R:
+         case HEVC_NAL_BLA_W_LP:
+         case HEVC_NAL_BLA_W_RADL:
+         case HEVC_NAL_BLA_N_LP:
+         case HEVC_NAL_IDR_W_RADL:
+         case HEVC_NAL_IDR_N_LP:
+         case HEVC_NAL_CRA_NUT:
+         case HEVC_NAL_RADL_N:
+         case HEVC_NAL_RADL_R:
+         case HEVC_NAL_RASL_N:
 -        case HEVC_NAL_RASL_R: hevc_parse_slice_header(s, nal, avctx); break;
++        case HEVC_NAL_RASL_R:
 +            if (buf == avctx->extradata) {
 +                av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", nal->type);
 +                return AVERROR_INVALIDDATA;
 +            }
 +            hevc_parse_slice_header(s, nal, avctx);
 +            break;
          }
      }
  
@@@ -174,236 -163,7 +175,236 @@@ static int hevc_find_frame_end(AVCodecP
      return END_NOT_FOUND;
  }
  
 -static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 +#if ADVANCED_PARSER
 +/**
 + * 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, const uint8_t *buf,
 +                           int buf_size, AVCodecContext *avctx)
 +{
 +    HEVCParserContext *ctx = s->priv_data;
 +    HEVCContext       *h   = &ctx->h;
 +    GetBitContext      *gb;
 +    SliceHeader        *sh = &h->sh;
 +    HEVCParamSets *ps = &h->ps;
 +    H2645Packet   *pkt = &ctx->pkt;
 +    const uint8_t *buf_end = buf + buf_size;
 +    int state = -1, i;
 +    H2645NAL *nal;
 +    int is_global = buf == avctx->extradata;
 +
 +    if (!h->HEVClc)
 +        h->HEVClc = av_mallocz(sizeof(HEVCLocalContext));
 +    if (!h->HEVClc)
 +        return AVERROR(ENOMEM);
 +
 +    gb = &h->HEVClc->gb;
 +
 +    /* 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;
 +
 +    ff_hevc_reset_sei(h);
 +
 +    if (!buf_size)
 +        return 0;
 +
 +    if (pkt->nals_allocated < 1) {
 +        H2645NAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
 +        if (!tmp)
 +            return AVERROR(ENOMEM);
 +        pkt->nals = tmp;
 +        memset(pkt->nals, 0, sizeof(*tmp));
 +        pkt->nals_allocated = 1;
 +    }
 +
 +    nal = &pkt->nals[0];
 +
 +    for (;;) {
 +        int src_length, consumed;
 +        int ret;
 +        int num = 0, den = 0;
 +        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) {
++        if (h->nal_unit_type <= HEVC_NAL_CRA_NUT) {
 +            // Do not walk the whole buffer just to decode slice segment header
 +            if (src_length > 20)
 +                src_length = 20;
 +        }
 +
 +        consumed = ff_h2645_extract_rbsp(buf, src_length, nal, 1);
 +        if (consumed < 0)
 +            return consumed;
 +
 +        ret = init_get_bits8(gb, nal->data + 2, nal->size);
 +        if (ret < 0)
 +            return ret;
 +
 +        switch (h->nal_unit_type) {
-         case NAL_VPS:
++        case HEVC_NAL_VPS:
 +            ff_hevc_decode_nal_vps(gb, avctx, ps);
 +            break;
-         case NAL_SPS:
++        case HEVC_NAL_SPS:
 +            ff_hevc_decode_nal_sps(gb, avctx, ps, 1);
 +            break;
-         case NAL_PPS:
++        case HEVC_NAL_PPS:
 +            ff_hevc_decode_nal_pps(gb, avctx, ps);
 +            break;
-         case NAL_SEI_PREFIX:
-         case NAL_SEI_SUFFIX:
++        case HEVC_NAL_SEI_PREFIX:
++        case HEVC_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:
++        case HEVC_NAL_TRAIL_N:
++        case HEVC_NAL_TRAIL_R:
++        case HEVC_NAL_TSA_N:
++        case HEVC_NAL_TSA_R:
++        case HEVC_NAL_STSA_N:
++        case HEVC_NAL_STSA_R:
++        case HEVC_NAL_RADL_N:
++        case HEVC_NAL_RADL_R:
++        case HEVC_NAL_RASL_N:
++        case HEVC_NAL_RASL_R:
++        case HEVC_NAL_BLA_W_LP:
++        case HEVC_NAL_BLA_W_RADL:
++        case HEVC_NAL_BLA_N_LP:
++        case HEVC_NAL_IDR_W_RADL:
++        case HEVC_NAL_IDR_N_LP:
++        case HEVC_NAL_CRA_NUT:
 +
 +            if (is_global) {
 +                av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", h->nal_unit_type);
 +                return AVERROR_INVALIDDATA;
 +            }
 +
 +            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]) {
++            if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !ps->pps_list[sh->pps_id]) {
 +                av_log(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]) {
++            if (ps->pps->sps_id >= HEVC_MAX_SPS_COUNT || !ps->sps_list[ps->pps->sps_id]) {
 +                av_log(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;
 +            }
 +
 +            s->coded_width  = ps->sps->width;
 +            s->coded_height = ps->sps->height;
 +            s->width        = ps->sps->output_width;
 +            s->height       = ps->sps->output_height;
 +            s->format       = ps->sps->pix_fmt;
 +            avctx->profile  = ps->sps->ptl.general_ptl.profile_idc;
 +            avctx->level    = ps->sps->ptl.general_ptl.level_idc;
 +
 +            if (ps->vps->vps_timing_info_present_flag) {
 +                num = ps->vps->vps_num_units_in_tick;
 +                den = ps->vps->vps_time_scale;
 +            } else if (ps->sps->vui.vui_timing_info_present_flag) {
 +                num = ps->sps->vui.vui_num_units_in_tick;
 +                den = ps->sps->vui.vui_time_scale;
 +            }
 +
 +            if (num != 0 && den != 0)
 +                av_reduce(&avctx->framerate.den, &avctx->framerate.num,
 +                          num, den, 1 << 30);
 +
 +            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 = get_bitsz(gb, slice_address_length);
 +                if (sh->slice_segment_addr >= ps->sps->ctb_width * ps->sps->ctb_height) {
 +                    av_log(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(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->nal_unit_type != HEVC_NAL_TRAIL_N &&
++                h->nal_unit_type != HEVC_NAL_TSA_N &&
++                h->nal_unit_type != HEVC_NAL_STSA_N &&
++                h->nal_unit_type != HEVC_NAL_RADL_N &&
++                h->nal_unit_type != HEVC_NAL_RASL_N &&
++                h->nal_unit_type != HEVC_NAL_RADL_R &&
++                h->nal_unit_type != HEVC_NAL_RASL_R)
 +                h->pocTid0 = h->poc;
 +
 +            return 0; /* no need to evaluate the rest */
 +        }
 +        buf += consumed;
 +    }
 +    /* didn't find a picture! */
 +    if (!is_global)
 +        av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit\n");
 +    return -1;
 +}
 +#endif
 +
 +static int hevc_parse(AVCodecParserContext *s,
 +                      AVCodecContext *avctx,
                        const uint8_t **poutbuf, int *poutbuf_size,
                        const uint8_t *buf, int buf_size)
  {
  // Split after the parameter sets at the beginning of the stream if they exist.
  static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
  {
 -    int i;
 +    const uint8_t *ptr = buf, *end = buf + buf_size;
      uint32_t state = -1;
 -    int has_ps = 0;
 -
 -    for (i = 0; i < buf_size; i++) {
 -        state = (state << 8) | buf[i];
 -        if (((state >> 8) & 0xFFFFFF) == START_CODE) {
 -            int nut = (state >> 1) & 0x3F;
 -            if (nut >= HEVC_NAL_VPS && nut <= HEVC_NAL_PPS)
 -                has_ps = 1;
 -            else if (has_ps)
 -                return i - 3;
 -            else // no parameter set at the beginning of the stream
 -                return 0;
 +    int has_vps = 0;
 +    int has_sps = 0;
 +    int has_pps = 0;
 +    int nut;
 +
 +    while (ptr < end) {
 +        ptr = avpriv_find_start_code(ptr, end, &state);
 +        if ((state >> 8) != START_CODE)
 +            break;
 +        nut = (state >> 1) & 0x3F;
-         if (nut == NAL_VPS)
++        if (nut == HEVC_NAL_VPS)
 +            has_vps = 1;
-         else if (nut == NAL_SPS)
++        else if (nut == HEVC_NAL_SPS)
 +            has_sps = 1;
-         else if (nut == NAL_PPS)
++        else if (nut == HEVC_NAL_PPS)
 +            has_pps = 1;
-         else if ((nut != NAL_SEI_PREFIX || has_pps) &&
-                   nut != NAL_AUD) {
++        else if ((nut != HEVC_NAL_SEI_PREFIX || has_pps) &&
++                  nut != HEVC_NAL_AUD) {
 +            if (has_vps && has_sps) {
 +                while (ptr - 4 > buf && ptr[-5] == 0)
 +                    ptr--;
 +                return ptr - 4 - buf;
 +            }
          }
      }
      return 0;
index 4a3091ca7b365c6bb7fbdc1aa05f263d1d3107b7,520017bc6e78d19c9ac6f8894c11fae63b47b322..f9f04a5388ecf8b0333ca18540ce53ad86a17d0f
@@@ -409,19 -369,8 +409,19 @@@ int ff_hevc_decode_nal_vps(GetBitContex
  
      av_log(avctx, AV_LOG_DEBUG, "Decoding VPS\n");
  
 +    nal_size = gb->buffer_end - gb->buffer;
 +    if (nal_size > sizeof(vps->data)) {
 +        av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized VPS "
 +               "(%"PTRDIFF_SPECIFIER" > %"SIZE_SPECIFIER")\n",
 +               nal_size, sizeof(vps->data));
 +        vps->data_size = sizeof(vps->data);
 +    } else {
 +        vps->data_size = nal_size;
 +    }
 +    memcpy(vps->data, gb->buffer, vps->data_size);
 +
      vps_id = get_bits(gb, 4);
-     if (vps_id >= MAX_VPS_COUNT) {
+     if (vps_id >= HEVC_MAX_VPS_COUNT) {
          av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", vps_id);
          goto err;
      }
@@@ -833,9 -690,10 +833,9 @@@ int ff_hevc_parse_sps(HEVCSPS *sps, Get
      // Coded parameters
  
      sps->vps_id = get_bits(gb, 4);
-     if (sps->vps_id >= MAX_VPS_COUNT) {
+     if (sps->vps_id >= HEVC_MAX_VPS_COUNT) {
          av_log(avctx, AV_LOG_ERROR, "VPS id out of range: %d\n", sps->vps_id);
 -        ret = AVERROR_INVALIDDATA;
 -        goto err;
 +        return AVERROR_INVALIDDATA;
      }
  
      if (vps_list && !vps_list[sps->vps_id]) {
      }
  
      sps->max_sub_layers = get_bits(gb, 3) + 1;
-     if (sps->max_sub_layers > MAX_SUB_LAYERS) {
+     if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) {
          av_log(avctx, AV_LOG_ERROR, "sps_max_sub_layers out of range: %d\n",
                 sps->max_sub_layers);
 -        ret = AVERROR_INVALIDDATA;
 -        goto err;
 +        return AVERROR_INVALIDDATA;
      }
  
      skip_bits1(gb); // temporal_id_nesting_flag
  
 -    parse_ptl(gb, avctx, &sps->ptl, sps->max_sub_layers);
 +    if ((ret = parse_ptl(gb, avctx, &sps->ptl, sps->max_sub_layers)) < 0)
 +        return ret;
  
      *sps_id = get_ue_golomb_long(gb);
-     if (*sps_id >= MAX_SPS_COUNT) {
+     if (*sps_id >= HEVC_MAX_SPS_COUNT) {
          av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", *sps_id);
 -        ret = AVERROR_INVALIDDATA;
 -        goto err;
 +        return AVERROR_INVALIDDATA;
      }
  
      sps->chroma_format_idc = get_ue_golomb_long(gb);
      }
  
      sps->nb_st_rps = get_ue_golomb_long(gb);
-     if (sps->nb_st_rps > MAX_SHORT_TERM_RPS_COUNT) {
+     if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_RPS_COUNT) {
          av_log(avctx, AV_LOG_ERROR, "Too many short term RPS: %d.\n",
                 sps->nb_st_rps);
 -        ret = AVERROR_INVALIDDATA;
 -        goto err;
 +        return AVERROR_INVALIDDATA;
      }
      for (i = 0; i < sps->nb_st_rps; i++) {
          if ((ret = ff_hevc_decode_short_term_rps(gb, avctx, &sps->st_rps[i],
index aa1162735c7bc427eb7d37a6a31f283ffcdbfa1f,82a115788783b7d725bd6d44f323aae5b2451330..db1ac2bf90f2aea0d3483b89cbac977757892abd
@@@ -386,9 -336,8 +387,9 @@@ static HEVCFrame *find_ref_idx(HEVCCont
          }
      }
  
-     if (s->nal_unit_type != NAL_CRA_NUT && !IS_BLA(s))
 -    av_log(s->avctx, AV_LOG_ERROR,
 -           "Could not find ref with POC %d\n", poc);
++    if (s->nal_unit_type != HEVC_NAL_CRA_NUT && !IS_BLA(s))
 +        av_log(s->avctx, AV_LOG_ERROR,
 +               "Could not find ref with POC %d\n", poc);
      return NULL;
  }
  
index bb4414402d948e9f43405ca3a1f4b89b674ebce6,8865cecdeda99e5f867c5337311ed9f951edbf07..a4b93c2b3f35868f43f0191de5ca69faaaadb3d8
@@@ -145,148 -118,9 +145,148 @@@ static int decode_nal_sei_display_orien
      return 0;
  }
  
-     if (active_seq_parameter_set_id >= MAX_SPS_COUNT) {
 +static int decode_pic_timing(HEVCContext *s)
 +{
 +    GetBitContext *gb = &s->HEVClc->gb;
 +    HEVCSPS *sps;
 +
 +    if (!s->ps.sps_list[s->active_seq_parameter_set_id])
 +        return(AVERROR(ENOMEM));
 +    sps = (HEVCSPS*)s->ps.sps_list[s->active_seq_parameter_set_id]->data;
 +
 +    if (sps->vui.frame_field_info_present_flag) {
 +        int pic_struct = get_bits(gb, 4);
 +        s->picture_struct = AV_PICTURE_STRUCTURE_UNKNOWN;
 +        if (pic_struct == 2) {
 +            av_log(s->avctx, AV_LOG_DEBUG, "BOTTOM Field\n");
 +            s->picture_struct = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
 +        } else if (pic_struct == 1) {
 +            av_log(s->avctx, AV_LOG_DEBUG, "TOP Field\n");
 +            s->picture_struct = AV_PICTURE_STRUCTURE_TOP_FIELD;
 +        }
 +        get_bits(gb, 2);                   // source_scan_type
 +        get_bits(gb, 1);                   // duplicate_flag
 +    }
 +    return 1;
 +}
 +
 +static int decode_registered_user_data_closed_caption(HEVCContext *s, int size)
 +{
 +    int flag;
 +    int user_data_type_code;
 +    int cc_count;
 +
 +    GetBitContext *gb = &s->HEVClc->gb;
 +
 +    if (size < 3)
 +       return AVERROR(EINVAL);
 +
 +    user_data_type_code = get_bits(gb, 8);
 +    if (user_data_type_code == 0x3) {
 +        skip_bits(gb, 1); // reserved
 +
 +        flag = get_bits(gb, 1); // process_cc_data_flag
 +        if (flag) {
 +            skip_bits(gb, 1);
 +            cc_count = get_bits(gb, 5);
 +            skip_bits(gb, 8); // reserved
 +            size -= 2;
 +
 +            if (cc_count && size >= cc_count * 3) {
 +                const uint64_t new_size = (s->a53_caption_size + cc_count
 +                                           * UINT64_C(3));
 +                int i, ret;
 +
 +                if (new_size > INT_MAX)
 +                    return AVERROR(EINVAL);
 +
 +                /* Allow merging of the cc data from two fields. */
 +                ret = av_reallocp(&s->a53_caption, new_size);
 +                if (ret < 0)
 +                    return ret;
 +
 +                for (i = 0; i < cc_count; i++) {
 +                    s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8);
 +                    s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8);
 +                    s->a53_caption[s->a53_caption_size++] = get_bits(gb, 8);
 +                }
 +                skip_bits(gb, 8); // marker_bits
 +            }
 +        }
 +    } else {
 +        int i;
 +        for (i = 0; i < size - 1; i++)
 +            skip_bits(gb, 8);
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCContext *s, int size)
 +{
 +    uint32_t country_code;
 +    uint32_t user_identifier;
 +
 +    GetBitContext *gb = &s->HEVClc->gb;
 +
 +    if (size < 7)
 +        return AVERROR(EINVAL);
 +    size -= 7;
 +
 +    country_code = get_bits(gb, 8);
 +    if (country_code == 0xFF) {
 +        skip_bits(gb, 8);
 +        size--;
 +    }
 +
 +    skip_bits(gb, 8);
 +    skip_bits(gb, 8);
 +
 +    user_identifier = get_bits_long(gb, 32);
 +
 +    switch (user_identifier) {
 +        case MKBETAG('G', 'A', '9', '4'):
 +            return decode_registered_user_data_closed_caption(s, size);
 +        default:
 +            skip_bits_long(gb, size * 8);
 +            break;
 +    }
 +    return 0;
 +}
 +
 +static int active_parameter_sets(HEVCContext *s)
 +{
 +    GetBitContext *gb = &s->HEVClc->gb;
 +    int num_sps_ids_minus1;
 +    int i;
 +    unsigned active_seq_parameter_set_id;
 +
 +    get_bits(gb, 4); // active_video_parameter_set_id
 +    get_bits(gb, 1); // self_contained_cvs_flag
 +    get_bits(gb, 1); // num_sps_ids_minus1
 +    num_sps_ids_minus1 = get_ue_golomb_long(gb); // num_sps_ids_minus1
 +
 +    if (num_sps_ids_minus1 < 0 || num_sps_ids_minus1 > 15) {
 +        av_log(s->avctx, AV_LOG_ERROR, "num_sps_ids_minus1 %d invalid\n", num_sps_ids_minus1);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    active_seq_parameter_set_id = get_ue_golomb_long(gb);
++    if (active_seq_parameter_set_id >= HEVC_MAX_SPS_COUNT) {
 +        av_log(s->avctx, AV_LOG_ERROR, "active_parameter_set_id %d invalid\n", active_seq_parameter_set_id);
 +        return AVERROR_INVALIDDATA;
 +    }
 +    s->active_seq_parameter_set_id = active_seq_parameter_set_id;
 +
 +    for (i = 1; i <= num_sps_ids_minus1; i++)
 +        get_ue_golomb_long(gb); // active_seq_parameter_set_id[i]
 +
 +    return 0;
 +}
 +
  static int decode_nal_sei_prefix(HEVCContext *s, int type, int size)
  {
 -    GetBitContext *gb = &s->HEVClc.gb;
 +    GetBitContext *gb = &s->HEVClc->gb;
  
      switch (type) {
      case 256:  // Mismatched value from HM 8.1
index 8893648e0a490bbe17fbf063a046e1206f71c80d,1da43344a4cab8beeb33d43ff6ed8e3f668443dc..aa54142da2624aa347775248bdb4fc9c4e7c6db5
@@@ -453,20 -472,12 +454,20 @@@ static int hls_slice_header(HEVCContex
          return AVERROR_INVALIDDATA;
      }
      s->ps.pps = (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data;
-     if (s->nal_unit_type == NAL_CRA_NUT && s->last_eos == 1)
++    if (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos == 1)
 +        sh->no_output_of_prior_pics_flag = 1;
  
      if (s->ps.sps != (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data) {
 +        const HEVCSPS* last_sps = s->ps.sps;
          s->ps.sps = (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data;
-         if (last_sps && IS_IRAP(s) && s->nal_unit_type != NAL_CRA_NUT) {
 -
++        if (last_sps && IS_IRAP(s) && s->nal_unit_type != HEVC_NAL_CRA_NUT) {
 +            if (s->ps.sps->width !=  last_sps->width || s->ps.sps->height != last_sps->height ||
 +                s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].max_dec_pic_buffering !=
 +                last_sps->temporal_layer[last_sps->max_sub_layers - 1].max_dec_pic_buffering)
 +                sh->no_output_of_prior_pics_flag = 0;
 +        }
          ff_hevc_clear_refs(s);
 -        ret = set_sps(s, s->ps.sps);
 +        ret = set_sps(s, s->ps.sps, AV_PIX_FMT_NONE);
          if (ret < 0)
              return ret;
  
          return AVERROR_INVALIDDATA;
      }
  
 -    s->HEVClc.first_qp_group = !s->sh.dependent_slice_segment_flag;
 +    if (get_bits_left(gb) < 0) {
 +        av_log(s->avctx, AV_LOG_ERROR,
 +               "Overread slice header by %d bits\n", -get_bits_left(gb));
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    s->HEVClc->first_qp_group = !s->sh.dependent_slice_segment_flag;
  
      if (!s->ps.pps->cu_qp_delta_enabled_flag)
 -        s->HEVClc.qp_y = FFUMOD(s->sh.slice_qp + 52 + 2 * s->ps.sps->qp_bd_offset,
 -                                52 + s->ps.sps->qp_bd_offset) - s->ps.sps->qp_bd_offset;
 +        s->HEVClc->qp_y = s->sh.slice_qp;
  
      s->slice_initialized = 1;
-     s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == NAL_CRA_NUT && s->last_eos);
 +    s->HEVClc->tu.cu_qp_offset_cb = 0;
 +    s->HEVClc->tu.cu_qp_offset_cr = 0;
 +
++    s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos);
  
      return 0;
  }
index 519c7a634c7ca18c597e7389b79ee5817e1b5b94,df81e55ed872ae5b3c6114790f4b5a2654a2593d..0866461c006e6544093eb479676e6db08a49fa72
@@@ -32,8 -33,8 +32,9 @@@
  #include "bswapdsp.h"
  #include "cabac.h"
  #include "get_bits.h"
 +#include "hevcpred.h"
  #include "h2645_parse.h"
+ #include "hevc.h"
  #include "hevcdsp.h"
  #include "internal.h"
  #include "thread.h"
  #define MAX_DPB_SIZE 16 // A.4.1
  #define MAX_REFS 16
  
- /**
-  * 7.4.2.1
-  */
- #define MAX_SUB_LAYERS 7
- #define MAX_VPS_COUNT 16
- #define MAX_SPS_COUNT 32
- #define MAX_PPS_COUNT 256
- #define MAX_SHORT_TERM_RPS_COUNT 64
- #define MAX_CU_SIZE 128
 +#define MAX_NB_THREADS 16
 +#define SHIFT_CTB_WPP 2
 +
  //TODO: check if this is really the maximum
  #define MAX_TRANSFORM_DEPTH 5
  
  #define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)])
  #define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)])
  
- #define IS_IDR(s) ((s)->nal_unit_type == NAL_IDR_W_RADL || (s)->nal_unit_type == NAL_IDR_N_LP)
- #define IS_BLA(s) ((s)->nal_unit_type == NAL_BLA_W_RADL || (s)->nal_unit_type == NAL_BLA_W_LP || \
-                    (s)->nal_unit_type == NAL_BLA_N_LP)
 -#define IS_IDR(s) (s->nal_unit_type == HEVC_NAL_IDR_W_RADL || s->nal_unit_type == HEVC_NAL_IDR_N_LP)
 -#define IS_BLA(s) (s->nal_unit_type == HEVC_NAL_BLA_W_RADL || s->nal_unit_type == HEVC_NAL_BLA_W_LP || \
 -                   s->nal_unit_type == HEVC_NAL_BLA_N_LP)
 -#define IS_IRAP(s) (s->nal_unit_type >= 16 && s->nal_unit_type <= 23)
 -
 -#define FFUDIV(a,b) (((a) > 0 ? (a) : (a) - (b) + 1) / (b))
 -#define FFUMOD(a,b) ((a) - (b) * FFUDIV(a,b))
++#define IS_IDR(s) ((s)->nal_unit_type == HEVC_NAL_IDR_W_RADL || (s)->nal_unit_type == HEVC_NAL_IDR_N_LP)
++#define IS_BLA(s) ((s)->nal_unit_type == HEVC_NAL_BLA_W_RADL || (s)->nal_unit_type == HEVC_NAL_BLA_W_LP || \
++                   (s)->nal_unit_type == HEVC_NAL_BLA_N_LP)
 +#define IS_IRAP(s) ((s)->nal_unit_type >= 16 && (s)->nal_unit_type <= 23)
  
- /**
-  * Table 7-3: NAL unit type codes
-  */
- enum NALUnitType {
-     NAL_TRAIL_N    = 0,
-     NAL_TRAIL_R    = 1,
-     NAL_TSA_N      = 2,
-     NAL_TSA_R      = 3,
-     NAL_STSA_N     = 4,
-     NAL_STSA_R     = 5,
-     NAL_RADL_N     = 6,
-     NAL_RADL_R     = 7,
-     NAL_RASL_N     = 8,
-     NAL_RASL_R     = 9,
-     NAL_BLA_W_LP   = 16,
-     NAL_BLA_W_RADL = 17,
-     NAL_BLA_N_LP   = 18,
-     NAL_IDR_W_RADL = 19,
-     NAL_IDR_N_LP   = 20,
-     NAL_CRA_NUT    = 21,
-     NAL_VPS        = 32,
-     NAL_SPS        = 33,
-     NAL_PPS        = 34,
-     NAL_AUD        = 35,
-     NAL_EOS_NUT    = 36,
-     NAL_EOB_NUT    = 37,
-     NAL_FD_NUT     = 38,
-     NAL_SEI_PREFIX = 39,
-     NAL_SEI_SUFFIX = 40,
- };
  enum RPSType {
      ST_CURR_BEF = 0,
      ST_CURR_AFT,
@@@ -886,14 -790,9 +846,14 @@@ typedef struct HEVCContext 
      uint16_t seq_decode;
      uint16_t seq_output;
  
 +    int enable_parallel_tiles;
 +    atomic_int wpp_err;
 +
 +    const uint8_t *data;
 +
      H2645Packet pkt;
      // type of the first VCL NAL of the current frame
-     enum NALUnitType first_nal_type;
+     enum HEVCNALUnitType first_nal_type;
  
      // for checking the frame checksums
      struct AVMD5 *md5_ctx;
index 3ada3fa6985dcb9c6054893717b7e24ca2a311c5,0000000000000000000000000000000000000000..79a51ec68406b7668fede5a88c0b59b457ddf189
mode 100644,000000..100644
--- /dev/null
@@@ -1,622 -1,0 +1,622 @@@
-     for (i = 0; i < MAX_VPS_COUNT; i++) {
 +/*
 + * Android MediaCodec H.264 / H.265 / MPEG-4 / VP8 / VP9 decoders
 + *
 + * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
 + *
 + * This file is part of FFmpeg.
 + *
 + * 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.
 + *
 + * 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 FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include <stdint.h>
 +#include <string.h>
 +
 +#include "libavutil/avassert.h"
 +#include "libavutil/common.h"
 +#include "libavutil/fifo.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/intreadwrite.h"
 +#include "libavutil/pixfmt.h"
 +
 +#include "avcodec.h"
 +#include "h264_parse.h"
 +#include "hevc_parse.h"
 +#include "internal.h"
 +#include "mediacodec_wrapper.h"
 +#include "mediacodecdec_common.h"
 +
 +typedef struct MediaCodecH264DecContext {
 +
 +    MediaCodecDecContext *ctx;
 +
 +    AVBSFContext *bsf;
 +
 +    AVFifoBuffer *fifo;
 +
 +    AVPacket filtered_pkt;
 +
 +} MediaCodecH264DecContext;
 +
 +static av_cold int mediacodec_decode_close(AVCodecContext *avctx)
 +{
 +    MediaCodecH264DecContext *s = avctx->priv_data;
 +
 +    ff_mediacodec_dec_close(avctx, s->ctx);
 +    s->ctx = NULL;
 +
 +    av_fifo_free(s->fifo);
 +
 +    av_bsf_free(&s->bsf);
 +    av_packet_unref(&s->filtered_pkt);
 +
 +    return 0;
 +}
 +
 +#if CONFIG_H264_MEDIACODEC_DECODER || CONFIG_HEVC_MEDIACODEC_DECODER
 +static int h2645_ps_to_nalu(const uint8_t *src, int src_size, uint8_t **out, int *out_size)
 +{
 +    int i;
 +    int ret = 0;
 +    uint8_t *p = NULL;
 +    static const uint8_t nalu_header[] = { 0x00, 0x00, 0x00, 0x01 };
 +
 +    if (!out || !out_size) {
 +        return AVERROR(EINVAL);
 +    }
 +
 +    p = av_malloc(sizeof(nalu_header) + src_size);
 +    if (!p) {
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    *out = p;
 +    *out_size = sizeof(nalu_header) + src_size;
 +
 +    memcpy(p, nalu_header, sizeof(nalu_header));
 +    memcpy(p + sizeof(nalu_header), src, src_size);
 +
 +    /* Escape 0x00, 0x00, 0x0{0-3} pattern */
 +    for (i = 4; i < *out_size; i++) {
 +        if (i < *out_size - 3 &&
 +            p[i + 0] == 0 &&
 +            p[i + 1] == 0 &&
 +            p[i + 2] <= 3) {
 +            uint8_t *new;
 +
 +            *out_size += 1;
 +            new = av_realloc(*out, *out_size);
 +            if (!new) {
 +                ret = AVERROR(ENOMEM);
 +                goto done;
 +            }
 +            *out = p = new;
 +
 +            i = i + 2;
 +            memmove(p + i + 1, p + i, *out_size - (i + 1));
 +            p[i] = 0x03;
 +        }
 +    }
 +done:
 +    if (ret < 0) {
 +        av_freep(out);
 +        *out_size = 0;
 +    }
 +
 +    return ret;
 +}
 +#endif
 +
 +#if CONFIG_H264_MEDIACODEC_DECODER
 +static int h264_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
 +{
 +    int i;
 +    int ret;
 +
 +    H264ParamSets ps;
 +    const PPS *pps = NULL;
 +    const SPS *sps = NULL;
 +    int is_avc = 0;
 +    int nal_length_size = 0;
 +
 +    memset(&ps, 0, sizeof(ps));
 +
 +    ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
 +                                   &ps, &is_avc, &nal_length_size, 0, avctx);
 +    if (ret < 0) {
 +        goto done;
 +    }
 +
 +    for (i = 0; i < MAX_PPS_COUNT; i++) {
 +        if (ps.pps_list[i]) {
 +            pps = (const PPS*)ps.pps_list[i]->data;
 +            break;
 +        }
 +    }
 +
 +    if (pps) {
 +        if (ps.sps_list[pps->sps_id]) {
 +            sps = (const SPS*)ps.sps_list[pps->sps_id]->data;
 +        }
 +    }
 +
 +    if (pps && sps) {
 +        uint8_t *data = NULL;
 +        int data_size = 0;
 +
 +        if ((ret = h2645_ps_to_nalu(sps->data, sps->data_size, &data, &data_size)) < 0) {
 +            goto done;
 +        }
 +        ff_AMediaFormat_setBuffer(format, "csd-0", (void*)data, data_size);
 +        av_freep(&data);
 +
 +        if ((ret = h2645_ps_to_nalu(pps->data, pps->data_size, &data, &data_size)) < 0) {
 +            goto done;
 +        }
 +        ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, data_size);
 +        av_freep(&data);
 +    } else {
 +        av_log(avctx, AV_LOG_ERROR, "Could not extract PPS/SPS from extradata");
 +        ret = AVERROR_INVALIDDATA;
 +    }
 +
 +done:
 +    ff_h264_ps_uninit(&ps);
 +
 +    return ret;
 +}
 +#endif
 +
 +#if CONFIG_HEVC_MEDIACODEC_DECODER
 +static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
 +{
 +    int i;
 +    int ret;
 +
 +    HEVCParamSets ps;
 +
 +    const HEVCVPS *vps = NULL;
 +    const HEVCPPS *pps = NULL;
 +    const HEVCSPS *sps = NULL;
 +    int is_nalff = 0;
 +    int nal_length_size = 0;
 +
 +    uint8_t *vps_data = NULL;
 +    uint8_t *sps_data = NULL;
 +    uint8_t *pps_data = NULL;
 +    int vps_data_size = 0;
 +    int sps_data_size = 0;
 +    int pps_data_size = 0;
 +
 +    memset(&ps, 0, sizeof(ps));
 +
 +    ret = ff_hevc_decode_extradata(avctx->extradata, avctx->extradata_size,
 +                                &ps, &is_nalff, &nal_length_size, 0, avctx);
 +    if (ret < 0) {
 +        goto done;
 +    }
 +
-     for (i = 0; i < MAX_PPS_COUNT; i++) {
++    for (i = 0; i < HEVC_MAX_VPS_COUNT; i++) {
 +        if (ps.vps_list[i]) {
 +            vps = (const HEVCVPS*)ps.vps_list[i]->data;
 +            break;
 +        }
 +    }
 +
++    for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
 +        if (ps.pps_list[i]) {
 +            pps = (const HEVCPPS*)ps.pps_list[i]->data;
 +            break;
 +        }
 +    }
 +
 +    if (pps) {
 +        if (ps.sps_list[pps->sps_id]) {
 +            sps = (const HEVCSPS*)ps.sps_list[pps->sps_id]->data;
 +        }
 +    }
 +
 +    if (vps && pps && sps) {
 +        uint8_t *data;
 +        int data_size;
 +
 +        if ((ret = h2645_ps_to_nalu(vps->data, vps->data_size, &vps_data, &vps_data_size)) < 0 ||
 +            (ret = h2645_ps_to_nalu(sps->data, sps->data_size, &sps_data, &sps_data_size)) < 0 ||
 +            (ret = h2645_ps_to_nalu(pps->data, pps->data_size, &pps_data, &pps_data_size)) < 0) {
 +            goto done;
 +        }
 +
 +        data_size = vps_data_size + sps_data_size + pps_data_size;
 +        data = av_mallocz(data_size);
 +        if (!data) {
 +            ret = AVERROR(ENOMEM);
 +            goto done;
 +        }
 +
 +        memcpy(data                                , vps_data, vps_data_size);
 +        memcpy(data + vps_data_size                , sps_data, sps_data_size);
 +        memcpy(data + vps_data_size + sps_data_size, pps_data, pps_data_size);
 +
 +        ff_AMediaFormat_setBuffer(format, "csd-0", data, data_size);
 +
 +        av_freep(&data);
 +    } else {
 +        av_log(avctx, AV_LOG_ERROR, "Could not extract VPS/PPS/SPS from extradata");
 +        ret = AVERROR_INVALIDDATA;
 +    }
 +
 +done:
 +    av_freep(&vps_data);
 +    av_freep(&sps_data);
 +    av_freep(&pps_data);
 +
 +    return ret;
 +}
 +#endif
 +
 +#if CONFIG_MPEG4_MEDIACODEC_DECODER
 +static int mpeg4_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
 +{
 +    int ret = 0;
 +
 +    if (avctx->extradata) {
 +        ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size);
 +    }
 +
 +    return ret;
 +}
 +#endif
 +
 +#if CONFIG_VP8_MEDIACODEC_DECODER || CONFIG_VP9_MEDIACODEC_DECODER
 +static int vpx_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
 +{
 +    int ret = 0;
 +
 +    if (avctx->extradata) {
 +        ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size);
 +    }
 +
 +    return ret;
 +}
 +#endif
 +
 +static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
 +{
 +    int ret;
 +
 +    const char *codec_mime = NULL;
 +
 +    const char *bsf_name = NULL;
 +    const AVBitStreamFilter *bsf = NULL;
 +
 +    FFAMediaFormat *format = NULL;
 +    MediaCodecH264DecContext *s = avctx->priv_data;
 +
 +    format = ff_AMediaFormat_new();
 +    if (!format) {
 +        av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n");
 +        ret = AVERROR_EXTERNAL;
 +        goto done;
 +    }
 +
 +    switch (avctx->codec_id) {
 +#if CONFIG_H264_MEDIACODEC_DECODER
 +    case AV_CODEC_ID_H264:
 +        codec_mime = "video/avc";
 +        bsf_name = "h264_mp4toannexb";
 +
 +        ret = h264_set_extradata(avctx, format);
 +        if (ret < 0)
 +            goto done;
 +        break;
 +#endif
 +#if CONFIG_HEVC_MEDIACODEC_DECODER
 +    case AV_CODEC_ID_HEVC:
 +        codec_mime = "video/hevc";
 +        bsf_name = "hevc_mp4toannexb";
 +
 +        ret = hevc_set_extradata(avctx, format);
 +        if (ret < 0)
 +            goto done;
 +        break;
 +#endif
 +#if CONFIG_MPEG4_MEDIACODEC_DECODER
 +    case AV_CODEC_ID_MPEG4:
 +        codec_mime = "video/mp4v-es",
 +
 +        ret = mpeg4_set_extradata(avctx, format);
 +        if (ret < 0)
 +            goto done;
 +        break;
 +#endif
 +#if CONFIG_VP8_MEDIACODEC_DECODER
 +    case AV_CODEC_ID_VP8:
 +        codec_mime = "video/x-vnd.on2.vp8";
 +
 +        ret = vpx_set_extradata(avctx, format);
 +        if (ret < 0)
 +            goto done;
 +        break;
 +#endif
 +#if CONFIG_VP9_MEDIACODEC_DECODER
 +    case AV_CODEC_ID_VP9:
 +        codec_mime = "video/x-vnd.on2.vp9";
 +
 +        ret = vpx_set_extradata(avctx, format);
 +        if (ret < 0)
 +            goto done;
 +        break;
 +#endif
 +    default:
 +        av_assert0(0);
 +    }
 +
 +    ff_AMediaFormat_setString(format, "mime", codec_mime);
 +    ff_AMediaFormat_setInt32(format, "width", avctx->width);
 +    ff_AMediaFormat_setInt32(format, "height", avctx->height);
 +
 +    s->ctx = av_mallocz(sizeof(*s->ctx));
 +    if (!s->ctx) {
 +        av_log(avctx, AV_LOG_ERROR, "Failed to allocate MediaCodecDecContext\n");
 +        ret = AVERROR(ENOMEM);
 +        goto done;
 +    }
 +
 +    if ((ret = ff_mediacodec_dec_init(avctx, s->ctx, codec_mime, format)) < 0) {
 +        s->ctx = NULL;
 +        goto done;
 +    }
 +
 +    av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret);
 +
 +    s->fifo = av_fifo_alloc(sizeof(AVPacket));
 +    if (!s->fifo) {
 +        ret = AVERROR(ENOMEM);
 +        goto done;
 +    }
 +
 +    if (bsf_name) {
 +    bsf = av_bsf_get_by_name(bsf_name);
 +    if(!bsf) {
 +        ret = AVERROR_BSF_NOT_FOUND;
 +        goto done;
 +    }
 +
 +    if ((ret = av_bsf_alloc(bsf, &s->bsf))) {
 +        goto done;
 +    }
 +
 +    if (((ret = avcodec_parameters_from_context(s->bsf->par_in, avctx)) < 0) ||
 +        ((ret = av_bsf_init(s->bsf)) < 0)) {
 +          goto done;
 +    }
 +    }
 +
 +    av_init_packet(&s->filtered_pkt);
 +
 +done:
 +    if (format) {
 +        ff_AMediaFormat_delete(format);
 +    }
 +
 +    if (ret < 0) {
 +        mediacodec_decode_close(avctx);
 +    }
 +
 +    return ret;
 +}
 +
 +
 +static int mediacodec_process_data(AVCodecContext *avctx, AVFrame *frame,
 +                                   int *got_frame, AVPacket *pkt)
 +{
 +    MediaCodecH264DecContext *s = avctx->priv_data;
 +
 +    return ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, pkt);
 +}
 +
 +static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
 +                                   int *got_frame, AVPacket *avpkt)
 +{
 +    MediaCodecH264DecContext *s = avctx->priv_data;
 +    AVFrame *frame    = data;
 +    int ret;
 +
 +    /* buffer the input packet */
 +    if (avpkt->size) {
 +        AVPacket input_pkt = { 0 };
 +
 +        if (av_fifo_space(s->fifo) < sizeof(input_pkt)) {
 +            ret = av_fifo_realloc2(s->fifo,
 +                                   av_fifo_size(s->fifo) + sizeof(input_pkt));
 +            if (ret < 0)
 +                return ret;
 +        }
 +
 +        ret = av_packet_ref(&input_pkt, avpkt);
 +        if (ret < 0)
 +            return ret;
 +        av_fifo_generic_write(s->fifo, &input_pkt, sizeof(input_pkt), NULL);
 +    }
 +
 +    /*
 +     * MediaCodec.flush() discards both input and output buffers, thus we
 +     * need to delay the call to this function until the user has released or
 +     * renderered the frames he retains.
 +     *
 +     * After we have buffered an input packet, check if the codec is in the
 +     * flushing state. If it is, we need to call ff_mediacodec_dec_flush.
 +     *
 +     * ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
 +     * the codec (because the user retains frames). The codec stays in the
 +     * flushing state.
 +     *
 +     * ff_mediacodec_dec_flush returns 1 if the flush can actually be
 +     * performed on the codec. The codec leaves the flushing state and can
 +     * process again packets.
 +     *
 +     * ff_mediacodec_dec_flush returns a negative value if an error has
 +     * occurred.
 +     *
 +     */
 +    if (ff_mediacodec_dec_is_flushing(avctx, s->ctx)) {
 +        if (!ff_mediacodec_dec_flush(avctx, s->ctx)) {
 +            return avpkt->size;
 +        }
 +    }
 +
 +    /* process buffered data */
 +    while (!*got_frame) {
 +        /* prepare the input data -- convert to Annex B if needed */
 +        if (s->filtered_pkt.size <= 0) {
 +            AVPacket input_pkt = { 0 };
 +
 +            av_packet_unref(&s->filtered_pkt);
 +
 +            /* no more data */
 +            if (av_fifo_size(s->fifo) < sizeof(AVPacket)) {
 +                return avpkt->size ? avpkt->size :
 +                    ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, avpkt);
 +            }
 +
 +            av_fifo_generic_read(s->fifo, &input_pkt, sizeof(input_pkt), NULL);
 +
 +            if (s->bsf) {
 +            ret = av_bsf_send_packet(s->bsf, &input_pkt);
 +            if (ret < 0) {
 +                return ret;
 +            }
 +
 +            ret = av_bsf_receive_packet(s->bsf, &s->filtered_pkt);
 +            if (ret == AVERROR(EAGAIN)) {
 +                goto done;
 +            }
 +            } else {
 +                av_packet_move_ref(&s->filtered_pkt, &input_pkt);
 +            }
 +
 +            /* {h264,hevc}_mp4toannexb are used here and do not require flushing */
 +            av_assert0(ret != AVERROR_EOF);
 +
 +            if (ret < 0) {
 +                return ret;
 +            }
 +        }
 +
 +        ret = mediacodec_process_data(avctx, frame, got_frame, &s->filtered_pkt);
 +        if (ret < 0)
 +            return ret;
 +
 +        s->filtered_pkt.size -= ret;
 +        s->filtered_pkt.data += ret;
 +    }
 +done:
 +    return avpkt->size;
 +}
 +
 +static void mediacodec_decode_flush(AVCodecContext *avctx)
 +{
 +    MediaCodecH264DecContext *s = avctx->priv_data;
 +
 +    while (av_fifo_size(s->fifo)) {
 +        AVPacket pkt;
 +        av_fifo_generic_read(s->fifo, &pkt, sizeof(pkt), NULL);
 +        av_packet_unref(&pkt);
 +    }
 +    av_fifo_reset(s->fifo);
 +
 +    av_packet_unref(&s->filtered_pkt);
 +
 +    ff_mediacodec_dec_flush(avctx, s->ctx);
 +}
 +
 +#if CONFIG_H264_MEDIACODEC_DECODER
 +AVCodec ff_h264_mediacodec_decoder = {
 +    .name           = "h264_mediacodec",
 +    .long_name      = NULL_IF_CONFIG_SMALL("H.264 Android MediaCodec decoder"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_H264,
 +    .priv_data_size = sizeof(MediaCodecH264DecContext),
 +    .init           = mediacodec_decode_init,
 +    .decode         = mediacodec_decode_frame,
 +    .flush          = mediacodec_decode_flush,
 +    .close          = mediacodec_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
 +};
 +#endif
 +
 +#if CONFIG_HEVC_MEDIACODEC_DECODER
 +AVCodec ff_hevc_mediacodec_decoder = {
 +    .name           = "hevc_mediacodec",
 +    .long_name      = NULL_IF_CONFIG_SMALL("H.265 Android MediaCodec decoder"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_HEVC,
 +    .priv_data_size = sizeof(MediaCodecH264DecContext),
 +    .init           = mediacodec_decode_init,
 +    .decode         = mediacodec_decode_frame,
 +    .flush          = mediacodec_decode_flush,
 +    .close          = mediacodec_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
 +};
 +#endif
 +
 +#if CONFIG_MPEG4_MEDIACODEC_DECODER
 +AVCodec ff_mpeg4_mediacodec_decoder = {
 +    .name           = "mpeg4_mediacodec",
 +    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 Android MediaCodec decoder"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MPEG4,
 +    .priv_data_size = sizeof(MediaCodecH264DecContext),
 +    .init           = mediacodec_decode_init,
 +    .decode         = mediacodec_decode_frame,
 +    .flush          = mediacodec_decode_flush,
 +    .close          = mediacodec_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
 +};
 +#endif
 +
 +#if CONFIG_VP8_MEDIACODEC_DECODER
 +AVCodec ff_vp8_mediacodec_decoder = {
 +    .name           = "vp8_mediacodec",
 +    .long_name      = NULL_IF_CONFIG_SMALL("VP8 Android MediaCodec decoder"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_VP8,
 +    .priv_data_size = sizeof(MediaCodecH264DecContext),
 +    .init           = mediacodec_decode_init,
 +    .decode         = mediacodec_decode_frame,
 +    .flush          = mediacodec_decode_flush,
 +    .close          = mediacodec_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
 +};
 +#endif
 +
 +#if CONFIG_VP9_MEDIACODEC_DECODER
 +AVCodec ff_vp9_mediacodec_decoder = {
 +    .name           = "vp9_mediacodec",
 +    .long_name      = NULL_IF_CONFIG_SMALL("VP9 Android MediaCodec decoder"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_VP9,
 +    .priv_data_size = sizeof(MediaCodecH264DecContext),
 +    .init           = mediacodec_decode_init,
 +    .decode         = mediacodec_decode_frame,
 +    .flush          = mediacodec_decode_flush,
 +    .close          = mediacodec_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
 +};
 +#endif
Simple merge
Simple merge
Simple merge
Simple merge