diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index a3798e6189..9d99cba4c8 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -2505,32 +2505,6 @@ static int hls_slice_data_wpp(HEVCContext *s, const uint8_t *nal, int length) return res; } -/** - * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, - * 0 if the unit should be skipped, 1 otherwise - */ -static int hls_nal_unit(HEVCNAL *nal, AVCodecContext *avctx) -{ - GetBitContext *gb = &nal->gb; - int nuh_layer_id; - - if (get_bits1(gb) != 0) - return AVERROR_INVALIDDATA; - - nal->type = get_bits(gb, 6); - - nuh_layer_id = get_bits(gb, 6); - nal->temporal_id = get_bits(gb, 3) - 1; - if (nal->temporal_id < 0) - return AVERROR_INVALIDDATA; - - av_log(avctx, AV_LOG_DEBUG, - "nal_unit_type: %d, nuh_layer_id: %d, temporal_id: %d\n", - nal->type, nuh_layer_id, nal->temporal_id); - - return nuh_layer_id == 0; -} - static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; @@ -2781,7 +2755,7 @@ fail: static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) { - int i, consumed, ret = 0; + int i, ret = 0; s->ref = NULL; s->last_eos = s->eos; @@ -2789,117 +2763,26 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) /* split the input packet into NAL units, so we know the upper bound on the * number of slices in the frame */ - s->nb_nals = 0; - while (length >= 4) { - HEVCNAL *nal; - int extract_length = 0; + ret = ff_hevc_split_packet(s, &s->pkt, buf, length, s->avctx, s->is_nalff, + s->nal_length_size); + if (ret < 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Error splitting the input into NAL units.\n"); + return ret; + } - if (s->is_nalff) { - int i; - for (i = 0; i < s->nal_length_size; i++) - extract_length = (extract_length << 8) | buf[i]; - buf += s->nal_length_size; - length -= s->nal_length_size; - - if (extract_length > length) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n"); - ret = AVERROR_INVALIDDATA; - goto fail; - } - } else { - /* search start code */ - while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { - ++buf; - --length; - if (length < 4) { - av_log(s->avctx, AV_LOG_ERROR, "No start code is found.\n"); - ret = AVERROR_INVALIDDATA; - goto fail; - } - } - - buf += 3; - length -= 3; - } - - if (!s->is_nalff) - extract_length = length; - - if (s->nals_allocated < s->nb_nals + 1) { - int new_size = s->nals_allocated + 1; - void *tmp = av_realloc_array(s->nals, new_size, sizeof(*s->nals)); - ret = AVERROR(ENOMEM); - if (!tmp) { - goto fail; - } - s->nals = tmp; - memset(s->nals + s->nals_allocated, 0, - (new_size - s->nals_allocated) * sizeof(*s->nals)); - - tmp = av_realloc_array(s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal)); - if (!tmp) - goto fail; - s->skipped_bytes_nal = tmp; - - tmp = av_realloc_array(s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal)); - if (!tmp) - goto fail; - s->skipped_bytes_pos_size_nal = tmp; - - tmp = av_realloc_array(s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal)); - if (!tmp) - goto fail; - s->skipped_bytes_pos_nal = tmp; - - s->skipped_bytes_pos_size_nal[s->nals_allocated] = 1024; // initial buffer size - s->skipped_bytes_pos_nal[s->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[s->nals_allocated], sizeof(*s->skipped_bytes_pos)); - if (!s->skipped_bytes_pos_nal[s->nals_allocated]) - goto fail; - s->nals_allocated = new_size; - } - s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[s->nb_nals]; - s->skipped_bytes_pos = s->skipped_bytes_pos_nal[s->nb_nals]; - nal = &s->nals[s->nb_nals]; - - consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal); - if (consumed < 0) { - ret = consumed; - goto fail; - } - - s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes; - s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size; - s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos; - - ret = init_get_bits8(&nal->gb, nal->data, nal->size); - if (ret < 0) - goto fail; - - ret = hls_nal_unit(nal, s->avctx); - if (ret <= 0) { - if (ret < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", - nal->type); - } - s->nb_nals--; - goto skip_nal; - } - - if (nal->type == NAL_EOB_NUT || - nal->type == NAL_EOS_NUT) + for (i = 0; i < s->pkt.nb_nals; i++) { + if (s->pkt.nals[i].type == NAL_EOB_NUT || + s->pkt.nals[i].type == NAL_EOS_NUT) s->eos = 1; - -skip_nal: - buf += consumed; - length -= consumed; } /* parse the NAL units */ - for (i = 0; i < s->nb_nals; i++) { + for (i = 0; i < s->pkt.nb_nals; i++) { s->skipped_bytes = s->skipped_bytes_nal[i]; s->skipped_bytes_pos = s->skipped_bytes_pos_nal[i]; - ret = decode_nal_unit(s, &s->nals[i]); + ret = decode_nal_unit(s, &s->pkt.nals[i]); if (ret < 0) { av_log(s->avctx, AV_LOG_WARNING, "Error parsing NAL unit #%d.\n", i); @@ -3087,7 +2970,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) av_freep(&s->md5_ctx); - for(i=0; i < s->nals_allocated; i++) { + for(i=0; i < s->pkt.nals_allocated; i++) { av_freep(&s->skipped_bytes_pos_nal[i]); } av_freep(&s->skipped_bytes_pos_size_nal); @@ -3132,10 +3015,10 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) s->HEVClc = NULL; av_freep(&s->HEVClcList[0]); - for (i = 0; i < s->nals_allocated; i++) - av_freep(&s->nals[i].rbsp_buffer); - av_freep(&s->nals); - s->nals_allocated = 0; + for (i = 0; i < s->pkt.nals_allocated; i++) + av_freep(&s->pkt.nals[i].rbsp_buffer); + av_freep(&s->pkt.nals); + s->pkt.nals_allocated = 0; return 0; } diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 8f4346efa2..a774c6b0bc 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -761,6 +761,13 @@ typedef struct HEVCNAL { int temporal_id; } HEVCNAL; +/* an input packet split into unescaped NAL units */ +typedef struct HEVCPacket { + HEVCNAL *nals; + int nb_nals; + int nals_allocated; +} HEVCPacket; + typedef struct HEVCLocalContext { uint8_t cabac_state[HEVC_CONTEXTS]; @@ -900,9 +907,7 @@ typedef struct HEVCContext { const uint8_t *data; - HEVCNAL *nals; - int nb_nals; - int nals_allocated; + HEVCPacket pkt; // type of the first VCL NAL of the current frame enum NALUnitType first_nal_type; @@ -1068,6 +1073,12 @@ void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size); int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length, HEVCNAL *nal); +/** + * Split an input packet into NAL units. + */ +int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length, + AVCodecContext *avctx, int is_nalff, int nal_length_size); + int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id, uint8_t *buf, int buf_size); diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index 260f1e1aa6..ee9a9d9e96 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -143,3 +143,132 @@ nsc: return si; } +/** + * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit, + * 0 if the unit should be skipped, 1 otherwise + */ +static int hls_nal_unit(HEVCNAL *nal, AVCodecContext *avctx) +{ + GetBitContext *gb = &nal->gb; + int nuh_layer_id; + + if (get_bits1(gb) != 0) + return AVERROR_INVALIDDATA; + + nal->type = get_bits(gb, 6); + + nuh_layer_id = get_bits(gb, 6); + nal->temporal_id = get_bits(gb, 3) - 1; + if (nal->temporal_id < 0) + return AVERROR_INVALIDDATA; + + av_log(avctx, AV_LOG_DEBUG, + "nal_unit_type: %d, nuh_layer_id: %d, temporal_id: %d\n", + nal->type, nuh_layer_id, nal->temporal_id); + + return nuh_layer_id == 0; +} + + +int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length, + AVCodecContext *avctx, int is_nalff, int nal_length_size) +{ + int consumed, ret = 0; + + pkt->nb_nals = 0; + while (length >= 4) { + HEVCNAL *nal; + int extract_length = 0; + + if (is_nalff) { + int i; + for (i = 0; i < nal_length_size; i++) + extract_length = (extract_length << 8) | buf[i]; + buf += nal_length_size; + length -= nal_length_size; + + if (extract_length > length) { + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n"); + return AVERROR_INVALIDDATA; + } + } else { + /* search start code */ + while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { + ++buf; + --length; + if (length < 4) { + av_log(avctx, AV_LOG_ERROR, "No start code is found.\n"); + return AVERROR_INVALIDDATA; + } + } + + buf += 3; + length -= 3; + extract_length = length; + } + + if (pkt->nals_allocated < pkt->nb_nals + 1) { + int new_size = pkt->nals_allocated + 1; + void *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*pkt->nals)); + + if (!tmp) + return AVERROR(ENOMEM); + + pkt->nals = tmp; + memset(pkt->nals + pkt->nals_allocated, 0, + (new_size - pkt->nals_allocated) * sizeof(*pkt->nals)); + + tmp = av_realloc_array(s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal)); + if (!tmp) + return AVERROR(ENOMEM); + s->skipped_bytes_nal = tmp; + + tmp = av_realloc_array(s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal)); + if (!tmp) + return AVERROR(ENOMEM); + s->skipped_bytes_pos_size_nal = tmp; + + tmp = av_realloc_array(s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal)); + if (!tmp) + return AVERROR(ENOMEM); + s->skipped_bytes_pos_nal = tmp; + + s->skipped_bytes_pos_size_nal[pkt->nals_allocated] = 1024; // initial buffer size + s->skipped_bytes_pos_nal[pkt->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[pkt->nals_allocated], sizeof(*s->skipped_bytes_pos)); + if (!s->skipped_bytes_pos_nal[pkt->nals_allocated]) + return AVERROR(ENOMEM); + + pkt->nals_allocated = new_size; + } + s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[pkt->nb_nals]; + s->skipped_bytes_pos = s->skipped_bytes_pos_nal[pkt->nb_nals]; + nal = &pkt->nals[pkt->nb_nals]; + + consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal); + if (consumed < 0) + return consumed; + + s->skipped_bytes_nal[pkt->nb_nals] = s->skipped_bytes; + s->skipped_bytes_pos_size_nal[pkt->nb_nals] = s->skipped_bytes_pos_size; + s->skipped_bytes_pos_nal[pkt->nb_nals++] = s->skipped_bytes_pos; + + ret = init_get_bits8(&nal->gb, nal->data, nal->size); + if (ret < 0) + return ret; + + ret = hls_nal_unit(nal, avctx); + if (ret <= 0) { + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", + nal->type); + } + pkt->nb_nals--; + } + + buf += consumed; + length -= consumed; + } + + return 0; +} + diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index d27af31cac..d6171b0472 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -91,6 +91,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx GetBitContext *gb = &h->HEVClc->gb; SliceHeader *sh = &h->sh; HEVCParamSets *ps = &h->ps; + HEVCPacket *pkt = &h->pkt; const uint8_t *buf_end = buf + buf_size; int state = -1, i; HEVCNAL *nal; @@ -105,16 +106,16 @@ static inline int parse_nal_units(AVCodecParserContext *s, AVCodecContext *avctx if (!buf_size) return 0; - if (h->nals_allocated < 1) { - HEVCNAL *tmp = av_realloc_array(h->nals, 1, sizeof(*tmp)); + if (pkt->nals_allocated < 1) { + HEVCNAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp)); if (!tmp) return AVERROR(ENOMEM); - h->nals = tmp; - memset(h->nals, 0, sizeof(*tmp)); - h->nals_allocated = 1; + pkt->nals = tmp; + memset(pkt->nals, 0, sizeof(*tmp)); + pkt->nals_allocated = 1; } - nal = &h->nals[0]; + nal = &pkt->nals[0]; for (;;) { int src_length, consumed; @@ -323,6 +324,7 @@ static void hevc_close(AVCodecParserContext *s) HEVCContext *h = &((HEVCParseContext *)s->priv_data)->h; ParseContext *pc = &((HEVCParseContext *)s->priv_data)->pc; HEVCParamSets *ps = &h->ps; + HEVCPacket *pkt = &h->pkt; av_freep(&h->skipped_bytes_pos); av_freep(&h->HEVClc); @@ -337,10 +339,10 @@ static void hevc_close(AVCodecParserContext *s) ps->sps = NULL; - for (i = 0; i < h->nals_allocated; i++) - av_freep(&h->nals[i].rbsp_buffer); - av_freep(&h->nals); - h->nals_allocated = 0; + for (i = 0; i < pkt->nals_allocated; i++) + av_freep(&pkt->nals[i].rbsp_buffer); + av_freep(&pkt->nals); + pkt->nals_allocated = 0; } AVCodecParser ff_hevc_parser = { diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 147877d32f..0c1dbb2486 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -91,7 +91,7 @@ static HEVCFrame *alloc_frame(HEVCContext *s) if (ret < 0) return NULL; - frame->rpl_buf = av_buffer_allocz(s->nb_nals * sizeof(RefPicListTab)); + frame->rpl_buf = av_buffer_allocz(s->pkt.nb_nals * sizeof(RefPicListTab)); if (!frame->rpl_buf) goto fail;