X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhevc_parser.c;h=d6102f3ab922a0734e437150da76fd17b0ab2253;hb=99c4c76cfbc4ae56dc8c37f5fab02f88f6b2cb48;hp=310428d0ffe900e807fe460bcd2841e6ad71ed03;hpb=3675f545e720dc0ea5090e53b796e8bdfc03b57a;p=ffmpeg diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index 310428d0ffe..d6102f3ab92 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -24,72 +24,171 @@ #include "golomb.h" #include "hevc.h" -#include "hevcdec.h" +#include "hevc_ps.h" +#include "hevc_sei.h" #include "h2645_parse.h" +#include "internal.h" #include "parser.h" #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes #define IS_IRAP_NAL(nal) (nal->type >= 16 && nal->type <= 23) - -#define ADVANCED_PARSER CONFIG_HEVC_DECODER +#define IS_IDR_NAL(nal) (nal->type == HEVC_NAL_IDR_W_RADL || nal->type == HEVC_NAL_IDR_N_LP) typedef struct HEVCParserContext { ParseContext pc; H2645Packet pkt; HEVCParamSets ps; + HEVCSEIContext sei; + SliceHeader sh; int parsed_extradata; -#if ADVANCED_PARSER - HEVCContext h; -#endif + int poc; + int pocTid0; } HEVCParserContext; -#if !ADVANCED_PARSER static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal, AVCodecContext *avctx) { HEVCParserContext *ctx = s->priv_data; + HEVCParamSets *ps = &ctx->ps; + HEVCSEIContext *sei = &ctx->sei; + SliceHeader *sh = &ctx->sh; GetBitContext *gb = &nal->gb; + int i, num = 0, den = 0; - HEVCPPS *pps; - HEVCSPS *sps; - unsigned int pps_id; + sh->first_slice_in_pic_flag = get_bits1(gb); + s->picture_structure = sei->picture_timing.picture_struct; + s->field_order = sei->picture_timing.picture_struct; - get_bits1(gb); // first slice in pic - if (IS_IRAP_NAL(nal)) - get_bits1(gb); // no output of prior pics + if (IS_IRAP_NAL(nal)) { + s->key_frame = 1; + sh->no_output_of_prior_pics_flag = get_bits1(gb); + } - pps_id = get_ue_golomb_long(gb); - 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); + sh->pps_id = get_ue_golomb(gb); + 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; } - pps = (HEVCPPS*)ctx->ps.pps_list[pps_id]->data; - sps = (HEVCSPS*)ctx->ps.sps_list[pps->sps_id]->data; + ps->pps = (HEVCPPS*)ps->pps_list[sh->pps_id]->data; - /* export the stream parameters */ - s->coded_width = sps->width; - s->coded_height = sps->height; - s->width = sps->output_width; - s->height = sps->output_height; - s->format = sps->pix_fmt; - avctx->profile = sps->ptl.general_ptl.profile_idc; - avctx->level = sps->ptl.general_ptl.level_idc; + 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; + } - /* ignore the rest for now*/ + 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; + } - return 0; + 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) + return 0; /* 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 == HEVC_SLICE_I || sh->slice_type == HEVC_SLICE_P || + sh->slice_type == HEVC_SLICE_B)) { + av_log(avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n", + sh->slice_type); + return AVERROR_INVALIDDATA; + } + s->pict_type = sh->slice_type == HEVC_SLICE_B ? AV_PICTURE_TYPE_B : + sh->slice_type == HEVC_SLICE_P ? 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_NAL(nal)) { + sh->pic_order_cnt_lsb = get_bits(gb, ps->sps->log2_max_poc_lsb); + s->output_picture_number = ctx->poc = ff_hevc_compute_poc(ps->sps, ctx->pocTid0, sh->pic_order_cnt_lsb, nal->type); + } else + s->output_picture_number = ctx->poc = 0; + + if (nal->temporal_id == 0 && + nal->type != HEVC_NAL_TRAIL_N && + nal->type != HEVC_NAL_TSA_N && + nal->type != HEVC_NAL_STSA_N && + nal->type != HEVC_NAL_RADL_N && + nal->type != HEVC_NAL_RASL_N && + nal->type != HEVC_NAL_RADL_R && + nal->type != HEVC_NAL_RASL_R) + ctx->pocTid0 = ctx->poc; + + return 1; /* no need to evaluate the rest */ } +/** + * 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 int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, int buf_size, AVCodecContext *avctx) { HEVCParserContext *ctx = s->priv_data; + HEVCParamSets *ps = &ctx->ps; + HEVCSEIContext *sei = &ctx->sei; + int is_global = buf == avctx->extradata; int ret, i; + /* set some sane default values */ + s->pict_type = AV_PICTURE_TYPE_I; + s->key_frame = 0; + s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN; + + ff_hevc_reset_sei(sei); + ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0, AV_CODEC_ID_HEVC, 1); if (ret < 0) @@ -97,14 +196,24 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, for (i = 0; i < ctx->pkt.nb_nals; i++) { H2645NAL *nal = &ctx->pkt.nals[i]; + GetBitContext *gb = &nal->gb; - /* ignore everything except parameter sets and VCL NALUs */ switch (nal->type) { - 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_VPS: + ff_hevc_decode_nal_vps(gb, avctx, ps); + break; + case HEVC_NAL_SPS: + ff_hevc_decode_nal_sps(gb, avctx, ps, 1); + break; + case HEVC_NAL_PPS: + ff_hevc_decode_nal_pps(gb, avctx, ps); + break; + case HEVC_NAL_SEI_PREFIX: + case HEVC_NAL_SEI_SUFFIX: + ff_hevc_decode_nal_sei(gb, avctx, sei, ps, nal->type); + break; 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: @@ -119,18 +228,23 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, case HEVC_NAL_RADL_R: case HEVC_NAL_RASL_N: case HEVC_NAL_RASL_R: - if (buf == avctx->extradata) { + + if (is_global) { av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit: %d\n", nal->type); return AVERROR_INVALIDDATA; } - hevc_parse_slice_header(s, nal, avctx); + + ret = hevc_parse_slice_header(s, nal, avctx); + if (ret) + return ret; break; } } - - return 0; + /* didn't find a picture! */ + if (!is_global) + av_log(avctx, AV_LOG_ERROR, "missing picture in access unit\n"); + return -1; } -#endif /** * Find the end of the current frame in the bitstream. @@ -139,8 +253,9 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, int buf_size) { + HEVCParserContext *ctx = s->priv_data; + ParseContext *pc = &ctx->pc; int i; - ParseContext *pc = s->priv_data; for (i = 0; i < buf_size; i++) { int nut; @@ -175,236 +290,7 @@ static int hevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, return END_NOT_FOUND; } -#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 <= 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 HEVC_NAL_VPS: - ff_hevc_decode_nal_vps(gb, avctx, ps); - break; - case HEVC_NAL_SPS: - ff_hevc_decode_nal_sps(gb, avctx, ps, 1); - break; - case HEVC_NAL_PPS: - ff_hevc_decode_nal_pps(gb, avctx, ps); - break; - case HEVC_NAL_SEI_PREFIX: - case HEVC_NAL_SEI_SUFFIX: - ff_hevc_decode_nal_sei(h); - break; - 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 >= 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 >= 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 == HEVC_SLICE_I || sh->slice_type == HEVC_SLICE_P || - sh->slice_type == HEVC_SLICE_B)) { - av_log(avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n", - sh->slice_type); - return AVERROR_INVALIDDATA; - } - s->pict_type = sh->slice_type == HEVC_SLICE_B ? AV_PICTURE_TYPE_B : - sh->slice_type == HEVC_SLICE_P ? 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 != 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, +static int hevc_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { @@ -473,21 +359,6 @@ static void hevc_parser_close(AVCodecParserContext *s) HEVCParserContext *ctx = s->priv_data; int i; -#if ADVANCED_PARSER - HEVCContext *h = &ctx->h; - - for (i = 0; i < FF_ARRAY_ELEMS(h->ps.vps_list); i++) - av_buffer_unref(&h->ps.vps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) - av_buffer_unref(&h->ps.sps_list[i]); - for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) - av_buffer_unref(&h->ps.pps_list[i]); - - h->ps.sps = NULL; - - av_freep(&h->HEVClc); -#endif - for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.vps_list); i++) av_buffer_unref(&ctx->ps.vps_list[i]); for (i = 0; i < FF_ARRAY_ELEMS(ctx->ps.sps_list); i++)