ffmpeg | branch: master | James Almer <jamr...@gmail.com> | Thu Mar 23 14:27:48 2017 -0300| [6397815be0bee10948387fcb90ead36ec2834ef7] | committer: James Almer
Merge commit 'c359d624d3efc3fd1d83210d78c4152bd329b765' * commit 'c359d624d3efc3fd1d83210d78c4152bd329b765': hevcdec: move decoder-independent declarations into a separate header Merged-by: James Almer <jamr...@gmail.com> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=6397815be0bee10948387fcb90ead36ec2834ef7 --- libavcodec/h2645_parse.c | 52 ++++++++--------- libavcodec/hevc_mp4toannexb_bsf.c | 6 +- libavcodec/hevc_parse.c | 40 ++++++------- libavcodec/hevc_parser.c | 119 +++++++++++++++++++------------------- libavcodec/hevc_ps.c | 16 ++--- libavcodec/hevc_refs.c | 9 +-- libavcodec/hevc_sei.c | 4 +- libavcodec/hevcdec.c | 83 +++++++++++++------------- libavcodec/hevcdec.h | 74 ++++++------------------ libavcodec/mediacodecdec.c | 4 +- libavcodec/qsvenc_hevc.c | 11 ++-- libavcodec/vaapi_encode_h265.c | 22 +++---- libavformat/hevc.c | 59 +++++++++---------- libavformat/hevcdec.c | 20 +++---- 14 files changed, 242 insertions(+), 277 deletions(-) diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index c14c415..b0d9ff6 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -26,7 +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, @@ -150,31 +150,31 @@ nsc: static const char *nal_unit_name(int nal_type) { switch(nal_type) { - 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"; + 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 "?"; } } diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c index 9002a98..09bce5b 100644 --- a/libavcodec/hevc_mp4toannexb_bsf.c +++ b/libavcodec/hevc_mp4toannexb_bsf.c @@ -27,7 +27,7 @@ #include "avcodec.h" #include "bsf.h" #include "bytestream.h" -#include "hevcdec.h" +#include "hevc.h" #define MIN_HEVCC_LENGTH 23 @@ -55,8 +55,8 @@ static int hevc_extradata_to_annexb(AVBSFContext *ctx) int type = bytestream2_get_byte(&gb) & 0x3f; int cnt = bytestream2_get_be16(&gb); - if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS || - type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) { + if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS || + type == HEVC_NAL_SEI_PREFIX || type == HEVC_NAL_SEI_SUFFIX)) { av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n", type); ret = AVERROR_INVALIDDATA; diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index d6bf872..6c1138e 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -18,7 +18,7 @@ #include "bytestream.h" #include "h2645_parse.h" -#include "hevcdec.h" +#include "hevc.h" #include "hevc_parse.h" static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets *ps, @@ -38,25 +38,25 @@ static int hevc_decode_nal_units(const uint8_t *buf, int buf_size, HEVCParamSets /* ignore everything except parameter sets and VCL NALUs */ switch (nal->type) { - 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: + 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; diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index 22a9623..2a5190d 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "golomb.h" +#include "hevc.h" #include "hevcdec.h" #include "h2645_parse.h" #include "parser.h" @@ -62,7 +63,7 @@ static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, get_bits1(gb); // no output of prior pics pps_id = get_ue_golomb_long(gb); - if (pps_id >= MAX_PPS_COUNT || !ctx->ps.pps_list[pps_id]) { + if (pps_id >= HEVC_MAX_PPS_COUNT || !ctx->ps.pps_list[pps_id]) { av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); return AVERROR_INVALIDDATA; } @@ -99,25 +100,25 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, /* 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: if (buf == avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", nal->type); return AVERROR_INVALIDDATA; @@ -151,14 +152,14 @@ static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, nut = (pc->state64 >> 2 * 8 + 1) & 0x3F; // Beginning of access unit - if ((nut >= NAL_VPS && nut <= NAL_AUD) || nut == NAL_SEI_PREFIX || + if ((nut >= HEVC_NAL_VPS && nut <= HEVC_NAL_AUD) || nut == HEVC_NAL_SEI_PREFIX || (nut >= 41 && nut <= 44) || (nut >= 48 && nut <= 55)) { if (pc->frame_start_found) { pc->frame_start_found = 0; return i - 5; } - } else if (nut <= NAL_RASL_R || - (nut >= NAL_BLA_W_LP && nut <= NAL_CRA_NUT)) { + } else if (nut <= HEVC_NAL_RASL_R || + (nut >= HEVC_NAL_BLA_W_LP && nut <= HEVC_NAL_CRA_NUT)) { int first_slice_segment_in_pic_flag = buf[i] >> 7; if (first_slice_segment_in_pic_flag) { if (!pc->frame_start_found) { @@ -238,7 +239,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *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; @@ -253,35 +254,35 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, 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); @@ -298,13 +299,13 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, } 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; } @@ -382,13 +383,13 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, 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 */ @@ -449,14 +450,14 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size) 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--; diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 4a3091c..f9f04a5 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -421,7 +421,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, 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; } @@ -440,7 +440,7 @@ int ff_hevc_decode_nal_vps(GetBitContext *gb, AVCodecContext *avctx, goto err; } - if (vps->vps_max_sub_layers > MAX_SUB_LAYERS) { + if (vps->vps_max_sub_layers > HEVC_MAX_SUB_LAYERS) { av_log(avctx, AV_LOG_ERROR, "vps_max_sub_layers out of range: %d\n", vps->vps_max_sub_layers); goto err; @@ -833,7 +833,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, // 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); return AVERROR_INVALIDDATA; } @@ -845,7 +845,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_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); return AVERROR_INVALIDDATA; @@ -857,7 +857,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, 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); return AVERROR_INVALIDDATA; } @@ -1018,7 +1018,7 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id, } 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); return AVERROR_INVALIDDATA; @@ -1470,13 +1470,13 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, AVCodecContext *avctx, // Coded parameters pps_id = get_ue_golomb_long(gb); - if (pps_id >= MAX_PPS_COUNT) { + if (pps_id >= HEVC_MAX_PPS_COUNT) { av_log(avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", pps_id); ret = AVERROR_INVALIDDATA; goto err; } pps->sps_id = get_ue_golomb_long(gb); - if (pps->sps_id >= MAX_SPS_COUNT) { + if (pps->sps_id >= HEVC_MAX_SPS_COUNT) { av_log(avctx, AV_LOG_ERROR, "SPS id out of range: %d\n", pps->sps_id); ret = AVERROR_INVALIDDATA; goto err; diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index aa11627..db1ac2b 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -26,6 +26,7 @@ #include "internal.h" #include "thread.h" +#include "hevc.h" #include "hevcdec.h" void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) @@ -386,7 +387,7 @@ static HEVCFrame *find_ref_idx(HEVCContext *s, int poc) } } - if (s->nal_unit_type != NAL_CRA_NUT && !IS_BLA(s)) + 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; @@ -530,9 +531,9 @@ int ff_hevc_compute_poc(HEVCContext *s, int poc_lsb) poc_msb = prev_poc_msb; // For BLA picture types, POCmsb is set to 0. - if (s->nal_unit_type == NAL_BLA_W_LP || - s->nal_unit_type == NAL_BLA_W_RADL || - s->nal_unit_type == NAL_BLA_N_LP) + if (s->nal_unit_type == HEVC_NAL_BLA_W_LP || + s->nal_unit_type == HEVC_NAL_BLA_W_RADL || + s->nal_unit_type == HEVC_NAL_BLA_N_LP) poc_msb = 0; return poc_msb + poc_lsb; diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index bb44144..a4b93c2 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -272,7 +272,7 @@ static int active_parameter_sets(HEVCContext *s) } active_seq_parameter_set_id = get_ue_golomb_long(gb); - if (active_seq_parameter_set_id >= MAX_SPS_COUNT) { + 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; } @@ -349,7 +349,7 @@ static int decode_nal_sei_message(HEVCContext *s) byte = get_bits(gb, 8); payload_size += byte; } - if (s->nal_unit_type == NAL_SEI_PREFIX) { + if (s->nal_unit_type == HEVC_NAL_SEI_PREFIX) { return decode_nal_sei_prefix(s, payload_type, payload_size); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ return decode_nal_sei_suffix(s, payload_type, payload_size); diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 8893648..aa54142 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -37,6 +37,7 @@ #include "bytestream.h" #include "cabac_functions.h" #include "golomb.h" +#include "hevc.h" #include "hevcdec.h" #include "profiles.h" @@ -443,7 +444,7 @@ static int hls_slice_header(HEVCContext *s) sh->no_output_of_prior_pics_flag = get_bits1(gb); sh->pps_id = get_ue_golomb_long(gb); - if (sh->pps_id >= MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { + if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id); return AVERROR_INVALIDDATA; } @@ -453,13 +454,13 @@ static int hls_slice_header(HEVCContext *s) 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) @@ -584,13 +585,13 @@ static int hls_slice_header(HEVCContext *s) /* 8.3.1 */ if (s->temporal_id == 0 && - s->nal_unit_type != NAL_TRAIL_N && - s->nal_unit_type != NAL_TSA_N && - s->nal_unit_type != NAL_STSA_N && - s->nal_unit_type != NAL_RADL_N && - s->nal_unit_type != NAL_RADL_R && - s->nal_unit_type != NAL_RASL_N && - s->nal_unit_type != NAL_RASL_R) + s->nal_unit_type != HEVC_NAL_TRAIL_N && + s->nal_unit_type != HEVC_NAL_TSA_N && + s->nal_unit_type != HEVC_NAL_STSA_N && + s->nal_unit_type != HEVC_NAL_RADL_N && + s->nal_unit_type != HEVC_NAL_RADL_R && + s->nal_unit_type != HEVC_NAL_RASL_N && + s->nal_unit_type != HEVC_NAL_RASL_R) s->pocTid0 = s->poc; if (s->ps.sps->sao_enabled) { @@ -824,7 +825,7 @@ static int hls_slice_header(HEVCContext *s) 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 == NAL_CRA_NUT && s->last_eos); + s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos); return 0; } @@ -2727,50 +2728,50 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) s->temporal_id = nal->temporal_id; switch (s->nal_unit_type) { - case NAL_VPS: + case HEVC_NAL_VPS: ret = ff_hevc_decode_nal_vps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; - case NAL_SPS: + case HEVC_NAL_SPS: ret = ff_hevc_decode_nal_sps(gb, s->avctx, &s->ps, s->apply_defdispwin); if (ret < 0) goto fail; break; - case NAL_PPS: + case HEVC_NAL_PPS: ret = ff_hevc_decode_nal_pps(gb, s->avctx, &s->ps); if (ret < 0) goto fail; break; - case NAL_SEI_PREFIX: - case NAL_SEI_SUFFIX: + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: ret = ff_hevc_decode_nal_sei(s); if (ret < 0) goto fail; 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_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: ret = hls_slice_header(s); if (ret < 0) return ret; if (s->max_ra == INT_MAX) { - if (s->nal_unit_type == NAL_CRA_NUT || IS_BLA(s)) { + if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { s->max_ra = s->poc; } else { if (IS_IDR(s)) @@ -2778,12 +2779,12 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) } } - if ((s->nal_unit_type == NAL_RASL_R || s->nal_unit_type == NAL_RASL_N) && + if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) && s->poc <= s->max_ra) { s->is_decoded = 0; break; } else { - if (s->nal_unit_type == NAL_RASL_R && s->poc > s->max_ra) + if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra) s->max_ra = INT_MIN; } @@ -2838,13 +2839,13 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) } } break; - case NAL_EOS_NUT: - case NAL_EOB_NUT: + case HEVC_NAL_EOS_NUT: + case HEVC_NAL_EOB_NUT: s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; break; - case NAL_AUD: - case NAL_FD_NUT: + case HEVC_NAL_AUD: + case HEVC_NAL_FD_NUT: break; default: av_log(s->avctx, AV_LOG_INFO, @@ -2877,8 +2878,8 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) } 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) + if (s->pkt.nals[i].type == HEVC_NAL_EOB_NUT || + s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) s->eos = 1; } diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 519c7a6..0866461 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -34,6 +34,7 @@ #include "get_bits.h" #include "hevcpred.h" #include "h2645_parse.h" +#include "hevc.h" #include "hevcdsp.h" #include "internal.h" #include "thread.h" @@ -45,16 +46,6 @@ #define MAX_NB_THREADS 16 #define SHIFT_CTB_WPP 2 -/** - * 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 - //TODO: check if this is really the maximum #define MAX_TRANSFORM_DEPTH 5 @@ -85,42 +76,11 @@ #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) -/** - * 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, @@ -365,10 +325,10 @@ typedef struct PTLCommon { typedef struct PTL { PTLCommon general_ptl; - PTLCommon sub_layer_ptl[MAX_SUB_LAYERS]; + PTLCommon sub_layer_ptl[HEVC_MAX_SUB_LAYERS]; - uint8_t sub_layer_profile_present_flag[MAX_SUB_LAYERS]; - uint8_t sub_layer_level_present_flag[MAX_SUB_LAYERS]; + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; } PTL; typedef struct HEVCVPS { @@ -378,9 +338,9 @@ typedef struct HEVCVPS { PTL ptl; int vps_sub_layer_ordering_info_present_flag; - unsigned int vps_max_dec_pic_buffering[MAX_SUB_LAYERS]; - unsigned int vps_num_reorder_pics[MAX_SUB_LAYERS]; - unsigned int vps_max_latency_increase[MAX_SUB_LAYERS]; + unsigned int vps_max_dec_pic_buffering[HEVC_MAX_SUB_LAYERS]; + unsigned int vps_num_reorder_pics[HEVC_MAX_SUB_LAYERS]; + unsigned int vps_max_latency_increase[HEVC_MAX_SUB_LAYERS]; int vps_max_layer_id; int vps_num_layer_sets; ///< vps_num_layer_sets_minus1 + 1 uint8_t vps_timing_info_present_flag; @@ -424,7 +384,7 @@ typedef struct HEVCSPS { int max_dec_pic_buffering; int num_reorder_pics; int max_latency_increase; - } temporal_layer[MAX_SUB_LAYERS]; + } temporal_layer[HEVC_MAX_SUB_LAYERS]; VUI vui; PTL ptl; @@ -433,7 +393,7 @@ typedef struct HEVCSPS { ScalingList scaling_list; unsigned int nb_st_rps; - ShortTermRPS st_rps[MAX_SHORT_TERM_RPS_COUNT]; + ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_RPS_COUNT]; uint8_t amp_enabled_flag; uint8_t sao_enabled; @@ -571,9 +531,9 @@ typedef struct HEVCPPS { } HEVCPPS; typedef struct HEVCParamSets { - AVBufferRef *vps_list[MAX_VPS_COUNT]; - AVBufferRef *sps_list[MAX_SPS_COUNT]; - AVBufferRef *pps_list[MAX_PPS_COUNT]; + AVBufferRef *vps_list[HEVC_MAX_VPS_COUNT]; + AVBufferRef *sps_list[HEVC_MAX_SPS_COUNT]; + AVBufferRef *pps_list[HEVC_MAX_PPS_COUNT]; /* currently active parameter sets */ const HEVCVPS *vps; @@ -837,7 +797,7 @@ typedef struct HEVCContext { SliceHeader sh; SAOParams *sao; DBParams *deblock; - enum NALUnitType nal_unit_type; + enum HEVCNALUnitType nal_unit_type; int temporal_id; ///< temporal_id_plus1 - 1 HEVCFrame *ref; HEVCFrame DPB[32]; @@ -893,7 +853,7 @@ typedef struct HEVCContext { 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; diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 3ada3fa..79a51ec 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -207,14 +207,14 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) goto done; } - for (i = 0; i < MAX_VPS_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 < MAX_PPS_COUNT; i++) { + for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) { if (ps.pps_list[i]) { pps = (const HEVCPPS*)ps.pps_list[i]->data; break; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 8b63bdc..7d4d55b 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bytestream.h" #include "get_bits.h" +#include "hevc.h" #include "hevcdec.h" #include "h2645_parse.h" #include "internal.h" @@ -83,7 +84,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) get_bits(&gb, 1); type = get_bits(&gb, 6); - if (type != NAL_SPS) { + if (type != HEVC_NAL_SPS) { av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: %d\n", type); av_freep(&sps_nal.rbsp_buffer); @@ -103,7 +104,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) vps.vps_max_sub_layers = sps.max_sub_layers; memcpy(&vps.ptl, &sps.ptl, sizeof(vps.ptl)); vps.vps_sub_layer_ordering_info_present_flag = 1; - for (i = 0; i < MAX_SUB_LAYERS; i++) { + for (i = 0; i < HEVC_MAX_SUB_LAYERS; i++) { vps.vps_max_dec_pic_buffering[i] = sps.temporal_layer[i].max_dec_pic_buffering; vps.vps_num_reorder_pics[i] = sps.temporal_layer[i].num_reorder_pics; vps.vps_max_latency_increase[i] = sps.temporal_layer[i].max_latency_increase; @@ -127,9 +128,9 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx) bytestream2_init(&gbc, vps_rbsp_buf, ret); bytestream2_init_writer(&pbc, vps_buf, sizeof(vps_buf)); - bytestream2_put_be32(&pbc, 1); // startcode - bytestream2_put_byte(&pbc, NAL_VPS << 1); // NAL - bytestream2_put_byte(&pbc, 1); // header + bytestream2_put_be32(&pbc, 1); // startcode + bytestream2_put_byte(&pbc, HEVC_NAL_VPS << 1); // NAL + bytestream2_put_byte(&pbc, 1); // header while (bytestream2_get_bytes_left(&gbc)) { uint32_t b = bytestream2_peek_be24(&gbc); diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 1332c28..bd327ff 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -25,7 +25,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" -#include "hevcdec.h" +#include "hevc.h" #include "internal.h" #include "put_bits.h" #include "vaapi_encode.h" @@ -275,7 +275,7 @@ static void vaapi_encode_h265_write_vps(PutBitContext *pbc, VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; int i, j; - vaapi_encode_h265_write_nal_unit_header(pbc, NAL_VPS); + vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_VPS); u(4, mseq->video_parameter_set_id, vps_video_parameter_set_id); @@ -395,7 +395,7 @@ static void vaapi_encode_h265_write_sps(PutBitContext *pbc, VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; int i; - vaapi_encode_h265_write_nal_unit_header(pbc, NAL_SPS); + vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_SPS); u(4, mseq->video_parameter_set_id, sps_video_parameter_set_id); @@ -491,7 +491,7 @@ static void vaapi_encode_h265_write_pps(PutBitContext *pbc, VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params; int i; - vaapi_encode_h265_write_nal_unit_header(pbc, NAL_PPS); + vaapi_encode_h265_write_nal_unit_header(pbc, HEVC_NAL_PPS); ue(vpic->slice_pic_parameter_set_id, pps_pic_parameter_set_id); ue(mseq->seq_parameter_set_id, pps_seq_parameter_set_id); @@ -576,7 +576,7 @@ static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc, vaapi_encode_h265_write_nal_unit_header(pbc, vpic->nal_unit_type); u(1, mslice_var(first_slice_segment_in_pic_flag)); - if (vpic->nal_unit_type >= NAL_BLA_W_LP && + if (vpic->nal_unit_type >= HEVC_NAL_BLA_W_LP && vpic->nal_unit_type <= 23) u(1, mslice_var(no_output_of_prior_pics_flag)); @@ -597,8 +597,8 @@ static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc, u(1, 1, pic_output_flag); if (vseq->seq_fields.bits.separate_colour_plane_flag) u(2, vslice_field(colour_plane_id)); - if (vpic->nal_unit_type != NAL_IDR_W_RADL && - vpic->nal_unit_type != NAL_IDR_N_LP) { + if (vpic->nal_unit_type != HEVC_NAL_IDR_W_RADL && + vpic->nal_unit_type != HEVC_NAL_IDR_N_LP) { u(4 + mseq->log2_max_pic_order_cnt_lsb_minus4, (pslice->pic_order_cnt & ((1 << (mseq->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1)), @@ -998,25 +998,25 @@ static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx, switch (pic->type) { case PICTURE_TYPE_IDR: - vpic->nal_unit_type = NAL_IDR_W_RADL; + vpic->nal_unit_type = HEVC_NAL_IDR_W_RADL; vpic->pic_fields.bits.idr_pic_flag = 1; vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_I: - vpic->nal_unit_type = NAL_TRAIL_R; + vpic->nal_unit_type = HEVC_NAL_TRAIL_R; vpic->pic_fields.bits.idr_pic_flag = 0; vpic->pic_fields.bits.coding_type = 1; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_P: - vpic->nal_unit_type = NAL_TRAIL_R; + vpic->nal_unit_type = HEVC_NAL_TRAIL_R; vpic->pic_fields.bits.idr_pic_flag = 0; vpic->pic_fields.bits.coding_type = 2; vpic->pic_fields.bits.reference_pic_flag = 1; break; case PICTURE_TYPE_B: - vpic->nal_unit_type = NAL_TRAIL_R; + vpic->nal_unit_type = HEVC_NAL_TRAIL_R; vpic->pic_fields.bits.idr_pic_flag = 0; vpic->pic_fields.bits.coding_type = 3; vpic->pic_fields.bits.reference_pic_flag = 0; diff --git a/libavformat/hevc.c b/libavformat/hevc.c index f3e283c..1a2d6cd 100644 --- a/libavformat/hevc.c +++ b/libavformat/hevc.c @@ -18,9 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavcodec/avcodec.h" #include "libavcodec/get_bits.h" #include "libavcodec/golomb.h" -#include "libavcodec/hevcdec.h" +#include "libavcodec/hevc.h" #include "libavutil/intreadwrite.h" #include "avc.h" #include "avio.h" @@ -127,8 +128,8 @@ static void hvcc_parse_ptl(GetBitContext *gb, { unsigned int i; HVCCProfileTierLevel general_ptl; - uint8_t sub_layer_profile_present_flag[MAX_SUB_LAYERS]; - uint8_t sub_layer_level_present_flag[MAX_SUB_LAYERS]; + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; general_ptl.profile_space = get_bits(gb, 2); general_ptl.tier_flag = get_bits1(gb); @@ -416,7 +417,7 @@ static void skip_scaling_list_data(GetBitContext *gb) static int parse_rps(GetBitContext *gb, unsigned int rps_idx, unsigned int num_rps, - unsigned int num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT]) + unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]) { unsigned int i; @@ -485,7 +486,7 @@ static int hvcc_parse_sps(GetBitContext *gb, HEVCDecoderConfigurationRecord *hvcc) { unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; - unsigned int num_short_term_ref_pic_sets, num_delta_pocs[MAX_SHORT_TERM_RPS_COUNT]; + unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_RPS_COUNT]; skip_bits(gb, 4); // sps_video_parameter_set_id @@ -555,7 +556,7 @@ static int hvcc_parse_sps(GetBitContext *gb, } num_short_term_ref_pic_sets = get_ue_golomb_long(gb); - if (num_short_term_ref_pic_sets > MAX_SHORT_TERM_RPS_COUNT) + if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_RPS_COUNT) return AVERROR_INVALIDDATA; for (i = 0; i < num_short_term_ref_pic_sets; i++) { @@ -734,7 +735,7 @@ static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, * for all other arrays. When the sample entry name is ‘hev1’, the default * value of array_completeness is 0 for all arrays. */ - if (nal_type == NAL_VPS || nal_type == NAL_SPS || nal_type == NAL_PPS) + if (nal_type == HEVC_NAL_VPS || nal_type == HEVC_NAL_SPS || nal_type == HEVC_NAL_PPS) array->array_completeness = ps_array_completeness; return 0; @@ -768,20 +769,20 @@ static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, * and non-declarative SEI messages discarded? */ switch (nal_type) { - case NAL_VPS: - case NAL_SPS: - case NAL_PPS: - case NAL_SEI_PREFIX: - case NAL_SEI_SUFFIX: + case HEVC_NAL_VPS: + case HEVC_NAL_SPS: + case HEVC_NAL_PPS: + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type, ps_array_completeness, hvcc); if (ret < 0) goto end; - else if (nal_type == NAL_VPS) + else if (nal_type == HEVC_NAL_VPS) ret = hvcc_parse_vps(&gbc, hvcc); - else if (nal_type == NAL_SPS) + else if (nal_type == HEVC_NAL_SPS) ret = hvcc_parse_sps(&gbc, hvcc); - else if (nal_type == NAL_PPS) + else if (nal_type == HEVC_NAL_PPS) ret = hvcc_parse_pps(&gbc, hvcc); if (ret < 0) goto end; @@ -915,21 +916,21 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) */ for (i = 0; i < hvcc->numOfArrays; i++) switch (hvcc->array[i].NAL_unit_type) { - case NAL_VPS: + case HEVC_NAL_VPS: vps_count += hvcc->array[i].numNalus; break; - case NAL_SPS: + case HEVC_NAL_SPS: sps_count += hvcc->array[i].numNalus; break; - case NAL_PPS: + case HEVC_NAL_PPS: pps_count += hvcc->array[i].numNalus; break; default: break; } - if (!vps_count || vps_count > MAX_VPS_COUNT || - !sps_count || sps_count > MAX_SPS_COUNT || - !pps_count || pps_count > MAX_PPS_COUNT) + if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT || + !sps_count || sps_count > HEVC_MAX_SPS_COUNT || + !pps_count || pps_count > HEVC_MAX_PPS_COUNT) return AVERROR_INVALIDDATA; /* unsigned int(8) configurationVersion = 1; */ @@ -1052,9 +1053,9 @@ int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, buf += 4; switch (type) { - case NAL_VPS: - case NAL_SPS: - case NAL_PPS: + case HEVC_NAL_VPS: + case HEVC_NAL_SPS: + case HEVC_NAL_PPS: num_ps++; break; default: @@ -1127,11 +1128,11 @@ int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, buf += 4; switch (type) { - case NAL_VPS: - case NAL_SPS: - case NAL_PPS: - case NAL_SEI_PREFIX: - case NAL_SEI_SUFFIX: + case HEVC_NAL_VPS: + case HEVC_NAL_SPS: + case HEVC_NAL_PPS: + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: ret = hvcc_add_nal_unit(buf, len, ps_array_completeness, &hvcc); if (ret < 0) goto end; diff --git a/libavformat/hevcdec.c b/libavformat/hevcdec.c index 28500fb..aaab0ff 100644 --- a/libavformat/hevcdec.c +++ b/libavformat/hevcdec.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/hevcdec.h" +#include "libavcodec/hevc.h" #include "avformat.h" #include "rawdec.h" @@ -43,15 +43,15 @@ static int hevc_probe(AVProbeData *p) return 0; switch (type) { - case NAL_VPS: vps++; break; - case NAL_SPS: sps++; break; - case NAL_PPS: pps++; break; - case NAL_BLA_N_LP: - case NAL_BLA_W_LP: - case NAL_BLA_W_RADL: - case NAL_CRA_NUT: - case NAL_IDR_N_LP: - case NAL_IDR_W_RADL: irap++; break; + case HEVC_NAL_VPS: vps++; break; + case HEVC_NAL_SPS: sps++; break; + case HEVC_NAL_PPS: pps++; break; + case HEVC_NAL_BLA_N_LP: + case HEVC_NAL_BLA_W_LP: + case HEVC_NAL_BLA_W_RADL: + case HEVC_NAL_CRA_NUT: + case HEVC_NAL_IDR_N_LP: + case HEVC_NAL_IDR_W_RADL: irap++; break; } } } ====================================================================== diff --cc libavcodec/h2645_parse.c index c14c415,8492425..b0d9ff6 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@@ -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; } +static const char *nal_unit_name(int nal_type) +{ + switch(nal_type) { - 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"; ++ 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; diff --cc libavcodec/hevc_parse.c index d6bf872,0000000..6c1138e mode 100644,000000..100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@@ -1,134 -1,0 +1,134 @@@ +/* + * 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" - #include "hevcdec.h" ++#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 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: ++ 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; +} diff --cc libavcodec/hevc_parser.c index 22a9623,49e7122..2a5190d --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@@ -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) { @@@ -437,31 -198,20 +438,31 @@@ // 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; diff --cc libavcodec/hevc_ps.c index 4a3091c,520017b..f9f04a5 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@@ -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]) { @@@ -845,21 -704,22 +845,21 @@@ } 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); @@@ -1018,10 -867,11 +1018,10 @@@ } 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], diff --cc libavcodec/hevc_refs.c index aa11627,82a1157..db1ac2b --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@@ -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; } diff --cc libavcodec/hevc_sei.c index bb44144,8865cec..a4b93c2 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@@ -145,148 -118,9 +145,148 @@@ static int decode_nal_sei_display_orien return 0; } +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 >= MAX_SPS_COUNT) { ++ 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 diff --cc libavcodec/hevcdec.c index 8893648,1da4334..aa54142 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@@ -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; @@@ -809,22 -777,13 +810,22 @@@ 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->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 == NAL_CRA_NUT && s->last_eos); ++ s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos); return 0; } diff --cc libavcodec/hevcdec.h index 519c7a6,df81e55..0866461 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@@ -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" @@@ -42,19 -43,6 +43,9 @@@ #define MAX_DPB_SIZE 16 // A.4.1 #define MAX_REFS 16 +#define MAX_NB_THREADS 16 +#define SHIFT_CTB_WPP 2 + - /** - * 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 - //TODO: check if this is really the maximum #define MAX_TRANSFORM_DEPTH 5 @@@ -85,42 -71,14 +76,11 @@@ #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; diff --cc libavcodec/mediacodecdec.c index 3ada3fa,0000000..79a51ec mode 100644,000000..100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@@ -1,622 -1,0 +1,622 @@@ +/* + * 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_VPS_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 < MAX_PPS_COUNT; i++) { ++ 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 _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog