From: Guillaume Martres <[email protected]>
---
doc/general.texi | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/hevc_parser.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 158 insertions(+)
create mode 100644 libavcodec/hevc_parser.c
diff --git a/doc/general.texi b/doc/general.texi
index a14e888..836e8c4 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -262,6 +262,7 @@ library:
@item raw H.261 @tab X @tab X
@item raw H.263 @tab X @tab X
@item raw H.264 @tab X @tab X
+@item raw HEVC @tab @tab X
@item raw Ingenient MJPEG @tab @tab X
@item raw MJPEG @tab X @tab X
@item raw MLP @tab @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 51a45bd..e8fda89 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -624,6 +624,7 @@ OBJS-$(CONFIG_H264_PARSER) += h264_parser.o
h264.o \
h264_refs.o h264_sei.o h264_direct.o
\
h264_loopfilter.o h264_cabac.o \
h264_cavlc.o h264_ps.o
+OBJS-$(CONFIG_HEVC_PARSER) += hevc_parser.o
OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o
OBJS-$(CONFIG_MJPEG_PARSER) += mjpeg_parser.o
OBJS-$(CONFIG_MLP_PARSER) += mlp_parser.o mlp.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 755b4ab..6542b5d 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -420,6 +420,7 @@ void avcodec_register_all(void)
REGISTER_PARSER (H261, h261);
REGISTER_PARSER (H263, h263);
REGISTER_PARSER (H264, h264);
+ REGISTER_PARSER (HEVC, hevc);
REGISTER_PARSER (MJPEG, mjpeg);
REGISTER_PARSER (MLP, mlp);
REGISTER_PARSER (MPEG4VIDEO, mpeg4video);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 9658b67..82bda0c 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -261,6 +261,7 @@ enum AVCodecID {
AV_CODEC_ID_TSCC2,
AV_CODEC_ID_MTS2,
AV_CODEC_ID_CLLC,
+ AV_CODEC_ID_HEVC,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the
start of audio codecs
diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c
new file mode 100644
index 0000000..33fe78d
--- /dev/null
+++ b/libavcodec/hevc_parser.c
@@ -0,0 +1,154 @@
+/*
+ * HEVC Annex B format parser
+ *
+ * Copyright (C) 2012 Guillaume Martres
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/common.h"
+#include "parser.h"
+
+#define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
+#define EMULATION_CODE 0x03 ///< emulation_prevention_three_byte
+
+typedef struct HEVCParserContext {
+ ParseContext pc;
+ uint8_t *nal_buffer;
+ unsigned int nal_buffer_size;
+} HEVCParserContext;
+
+/**
+ * Annex B.1: Byte stream NAL unit syntax and semantics
+ */
+static int hevc_parse_nal_unit(HEVCParserContext *hpc, uint8_t **poutbuf,
+ int *poutbuf_size, const uint8_t *buf,
+ int buf_size)
+{
+ int i;
+ ParseContext *pc = &hpc->pc;
+ int mask = 0xFFFFFF;
+ int skipped = 0;
+ int header = 0;
+
+ // skip leading zeroes
+ if (!pc->frame_start_found) {
+ for (i = 0; i < buf_size; i++) {
+ pc->state = (pc->state << 8) | buf[i];
+ if ((pc->state & mask) == START_CODE) {
+ pc->frame_start_found = 1;
+ // the frame starts one byte after the start code
+ header = i + 1;
+ break;
+ } else if (buf[i] != 0) {
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ }
+
+ buf += header;
+ buf_size -= header;
+ *poutbuf = (uint8_t*)buf;
+
+ // Remove emulation bytes and find the frame end
+ if (pc->frame_start_found) {
+ for (i = 0; i < buf_size; i++) {
+ pc->state = (pc->state << 8) | buf[i];
+ switch (pc->state & mask) {
+ case START_CODE:
+ pc->frame_start_found = 0;
+ pc->state = -1;
+ // The start code is three bytes long
+ *poutbuf_size = i - 2 - skipped;
+ return header + i - 2;
+ case EMULATION_CODE:
+ skipped++;
+
+ if (*poutbuf != hpc->nal_buffer) {
+ hpc->nal_buffer = av_fast_realloc(hpc->nal_buffer,
+ &hpc->nal_buffer_size,
+ buf_size - skipped);
+ if (!hpc->nal_buffer)
+ return END_NOT_FOUND;
+ *poutbuf = hpc->nal_buffer;
+ memcpy(*poutbuf, buf, i - skipped + 1);
+ }
+ break;
+ default:
+ if (*poutbuf == hpc->nal_buffer)
+ (*poutbuf)[i-skipped] = buf[i];
+ }
+ }
+ }
+
+ *poutbuf_size = buf_size - skipped;
+ if (buf_size == 0)
+ return 0;
+ return END_NOT_FOUND;
+}
+
+static int hevc_parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ const uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ HEVCParserContext *hpc = s->priv_data;
+ ParseContext *pc = &hpc->pc;
+ int combine_next = 0;
+ int next = hevc_parse_nal_unit(hpc, (uint8_t**)poutbuf, poutbuf_size, buf,
buf_size);
+
+ if (next == AVERROR_INVALIDDATA) {
+ av_log(NULL, AV_LOG_ERROR, "Data fed to parser isn't a NAL unit\n");
+ return next;
+ }
+
+ // next is an offset in buf, but we want to combine frames from *poutbuf
+ combine_next = (next != END_NOT_FOUND) ? *poutbuf_size : next;
+
+ if (ff_combine_frame(pc, combine_next, poutbuf, poutbuf_size) < 0) {
+ *poutbuf = NULL;
+ *poutbuf_size = 0;
+ return buf_size;
+ }
+
+ return next;
+}
+
+static int hevc_init(AVCodecParserContext *s)
+{
+ HEVCParserContext *hpc = s->priv_data;
+ hpc->nal_buffer_size = 0;
+ hpc->nal_buffer = NULL;
+ return 0;
+}
+
+static void hevc_close(AVCodecParserContext *s)
+{
+ HEVCParserContext *hpc = s->priv_data;
+ av_free(hpc->nal_buffer);
+
+ ff_parse_close(s);
+}
+
+
+AVCodecParser ff_hevc_parser = {
+ .codec_ids = { AV_CODEC_ID_HEVC },
+ .priv_data_size = sizeof(HEVCParserContext),
+ .parser_init = hevc_init,
+ .parser_parse = hevc_parse,
+ .parser_close = hevc_close
+};
--
1.7.9.5
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel