* commit 'd82e1adc2019135a2fc45372e0ed0b5ef107cdd0': hevc: move splitting the packet into NALUs into a separate function Conflicts: libavcodec/hevc.c libavcodec/hevc.h libavcodec/hevc_parse.c Merged-by: Michael Niedermayer <michael@niedermayer.cc>tags/n2.8
| @@ -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; | |||
| if (s->is_nalff) { | |||
| int i; | |||
| for (i = 0; i < s->nal_length_size; i++) | |||
| extract_length = (extract_length << 8) | buf[i]; | |||
| buf += s->nal_length_size; | |||
| length -= s->nal_length_size; | |||
| if (extract_length > length) { | |||
| av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n"); | |||
| ret = AVERROR_INVALIDDATA; | |||
| goto fail; | |||
| } | |||
| } else { | |||
| /* search start code */ | |||
| while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) { | |||
| ++buf; | |||
| --length; | |||
| if (length < 4) { | |||
| av_log(s->avctx, AV_LOG_ERROR, "No start code is found.\n"); | |||
| ret = AVERROR_INVALIDDATA; | |||
| goto fail; | |||
| } | |||
| } | |||
| buf += 3; | |||
| length -= 3; | |||
| } | |||
| if (!s->is_nalff) | |||
| extract_length = length; | |||
| if (s->nals_allocated < s->nb_nals + 1) { | |||
| int new_size = s->nals_allocated + 1; | |||
| void *tmp = av_realloc_array(s->nals, new_size, sizeof(*s->nals)); | |||
| ret = AVERROR(ENOMEM); | |||
| if (!tmp) { | |||
| goto fail; | |||
| } | |||
| s->nals = tmp; | |||
| memset(s->nals + s->nals_allocated, 0, | |||
| (new_size - s->nals_allocated) * sizeof(*s->nals)); | |||
| tmp = av_realloc_array(s->skipped_bytes_nal, new_size, sizeof(*s->skipped_bytes_nal)); | |||
| if (!tmp) | |||
| goto fail; | |||
| s->skipped_bytes_nal = tmp; | |||
| tmp = av_realloc_array(s->skipped_bytes_pos_size_nal, new_size, sizeof(*s->skipped_bytes_pos_size_nal)); | |||
| if (!tmp) | |||
| goto fail; | |||
| s->skipped_bytes_pos_size_nal = tmp; | |||
| tmp = av_realloc_array(s->skipped_bytes_pos_nal, new_size, sizeof(*s->skipped_bytes_pos_nal)); | |||
| if (!tmp) | |||
| goto fail; | |||
| s->skipped_bytes_pos_nal = tmp; | |||
| s->skipped_bytes_pos_size_nal[s->nals_allocated] = 1024; // initial buffer size | |||
| s->skipped_bytes_pos_nal[s->nals_allocated] = av_malloc_array(s->skipped_bytes_pos_size_nal[s->nals_allocated], sizeof(*s->skipped_bytes_pos)); | |||
| if (!s->skipped_bytes_pos_nal[s->nals_allocated]) | |||
| goto fail; | |||
| s->nals_allocated = new_size; | |||
| } | |||
| s->skipped_bytes_pos_size = s->skipped_bytes_pos_size_nal[s->nb_nals]; | |||
| s->skipped_bytes_pos = s->skipped_bytes_pos_nal[s->nb_nals]; | |||
| nal = &s->nals[s->nb_nals]; | |||
| consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal); | |||
| if (consumed < 0) { | |||
| ret = consumed; | |||
| goto fail; | |||
| } | |||
| s->skipped_bytes_nal[s->nb_nals] = s->skipped_bytes; | |||
| s->skipped_bytes_pos_size_nal[s->nb_nals] = s->skipped_bytes_pos_size; | |||
| s->skipped_bytes_pos_nal[s->nb_nals++] = s->skipped_bytes_pos; | |||
| ret = init_get_bits8(&nal->gb, nal->data, nal->size); | |||
| if (ret < 0) | |||
| goto fail; | |||
| ret = hls_nal_unit(nal, s->avctx); | |||
| if (ret <= 0) { | |||
| if (ret < 0) { | |||
| av_log(s->avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n", | |||
| nal->type); | |||
| } | |||
| s->nb_nals--; | |||
| goto skip_nal; | |||
| } | |||
| ret = ff_hevc_split_packet(s, &s->pkt, buf, length, s->avctx, s->is_nalff, | |||
| s->nal_length_size); | |||
| if (ret < 0) { | |||
| av_log(s->avctx, AV_LOG_ERROR, | |||
| "Error splitting the input into NAL units.\n"); | |||
| return ret; | |||
| } | |||
| if (nal->type == NAL_EOB_NUT || | |||
| nal->type == NAL_EOS_NUT) | |||
| for (i = 0; i < s->pkt.nb_nals; i++) { | |||
| if (s->pkt.nals[i].type == NAL_EOB_NUT || | |||
| s->pkt.nals[i].type == NAL_EOS_NUT) | |||
| s->eos = 1; | |||
| skip_nal: | |||
| buf += consumed; | |||
| length -= consumed; | |||
| } | |||
| /* parse the NAL units */ | |||
| for (i = 0; i < s->nb_nals; i++) { | |||
| for (i = 0; i < s->pkt.nb_nals; i++) { | |||
| s->skipped_bytes = s->skipped_bytes_nal[i]; | |||
| s->skipped_bytes_pos = s->skipped_bytes_pos_nal[i]; | |||
| ret = decode_nal_unit(s, &s->nals[i]); | |||
| ret = decode_nal_unit(s, &s->pkt.nals[i]); | |||
| if (ret < 0) { | |||
| av_log(s->avctx, AV_LOG_WARNING, | |||
| "Error parsing NAL unit #%d.\n", i); | |||
| @@ -3087,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; | |||
| } | |||
| @@ -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); | |||
| @@ -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; | |||
| } | |||
| @@ -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 = { | |||
| @@ -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; | |||