hevc: move splitting the packet into NALUs into a separate function
[ffmpeg.git] / libavcodec / hevc_parse.c
index 32a440b..93c8175 100644 (file)
@@ -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;
+}