diff options
author | Anton Khirnov <anton@khirnov.net> | 2015-07-09 18:33:52 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2015-07-12 18:15:39 +0200 |
commit | d82e1adc2019135a2fc45372e0ed0b5ef107cdd0 (patch) | |
tree | 7a881512bdb58ae40f9c3096207d007089f37331 /libavcodec/hevc_parse.c | |
parent | ae05b4865514fd71b5e9431e93aa0d03d7ba7751 (diff) | |
download | ffmpeg-d82e1adc2019135a2fc45372e0ed0b5ef107cdd0.tar.gz |
hevc: move splitting the packet into NALUs into a separate function
This function is independent of the decoding context, so we'll be able
to use it in the parser.
Diffstat (limited to 'libavcodec/hevc_parse.c')
-rw-r--r-- | libavcodec/hevc_parse.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c index 32a440bf92..93c8175702 100644 --- a/libavcodec/hevc_parse.c +++ b/libavcodec/hevc_parse.c @@ -127,3 +127,102 @@ nsc: nal->raw_size = si; 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: %dtemporal_id: %d\n", + nal->type, nuh_layer_id, nal->temporal_id); + + return nuh_layer_id == 0; +} + + +int ff_hevc_split_packet(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 { + if (buf[2] == 0) { + length--; + buf++; + continue; + } + if (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) + 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; + HEVCNAL *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*tmp)); + if (!tmp) + return AVERROR(ENOMEM); + + pkt->nals = tmp; + memset(pkt->nals + pkt->nals_allocated, 0, + (new_size - pkt->nals_allocated) * sizeof(*tmp)); + pkt->nals_allocated = new_size; + } + nal = &pkt->nals[pkt->nb_nals++]; + + consumed = ff_hevc_extract_rbsp(buf, extract_length, nal); + if (consumed < 0) + return consumed; + + 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; +} |