Browse code

Merge commit 'f89f78c1c563d98f10ee1d7e1ed67c9f9e03b741'

* commit 'f89f78c1c563d98f10ee1d7e1ed67c9f9e03b741':
lavc: add a HEVC mp4->annex B bitstream filter

Conflicts:
Changelog

Merged-by: Michael Niedermayer <michael@niedermayer.cc>

Michael Niedermayer authored on 2015/07/26 07:34:12
Showing 4 changed files
... ...
@@ -25,6 +25,7 @@ version <next>:
25 25
 - deband filter
26 26
 - AAC fixed-point decoding
27 27
 - sidechaincompress audio filter
28
+- bitstream filter for converting HEVC from MP4 to Annex B
28 29
 
29 30
 
30 31
 version 2.7:
... ...
@@ -871,6 +871,7 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF)          += aac_adtstoasc_bsf.o aacadtsdec.o \
871 871
 OBJS-$(CONFIG_CHOMP_BSF)                  += chomp_bsf.o
872 872
 OBJS-$(CONFIG_DUMP_EXTRADATA_BSF)         += dump_extradata_bsf.o
873 873
 OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF)       += h264_mp4toannexb_bsf.o
874
+OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF)       += hevc_mp4toannexb_bsf.o
874 875
 OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF)        += imx_dump_header_bsf.o
875 876
 OBJS-$(CONFIG_MJPEG2JPEG_BSF)             += mjpeg2jpeg_bsf.o
876 877
 OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF)     += mjpega_dump_header_bsf.o
... ...
@@ -622,6 +622,7 @@ void avcodec_register_all(void)
622 622
     REGISTER_BSF(CHOMP,                 chomp);
623 623
     REGISTER_BSF(DUMP_EXTRADATA,        dump_extradata);
624 624
     REGISTER_BSF(H264_MP4TOANNEXB,      h264_mp4toannexb);
625
+    REGISTER_BSF(HEVC_MP4TOANNEXB,      hevc_mp4toannexb);
625 626
     REGISTER_BSF(IMX_DUMP_HEADER,       imx_dump_header);
626 627
     REGISTER_BSF(MJPEG2JPEG,            mjpeg2jpeg);
627 628
     REGISTER_BSF(MJPEGA_DUMP_HEADER,    mjpega_dump_header);
628 629
new file mode 100644
... ...
@@ -0,0 +1,186 @@
0
+/*
1
+ * HEVC MP4 to Annex B byte stream format filter
2
+ * copyright (c) 2015 Anton Khirnov
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include <string.h>
22
+
23
+#include "libavutil/intreadwrite.h"
24
+#include "libavutil/mem.h"
25
+
26
+#include "avcodec.h"
27
+#include "bytestream.h"
28
+#include "hevc.h"
29
+
30
+#define MIN_HEVCC_LENGTH 23
31
+
32
+typedef struct HEVCBSFContext {
33
+    uint8_t  length_size;
34
+    int      extradata_parsed;
35
+
36
+    int logged_nonmp4_warning;
37
+} HEVCBSFContext;
38
+
39
+static int hevc_extradata_to_annexb(AVCodecContext *avctx)
40
+{
41
+    GetByteContext gb;
42
+    int length_size, num_arrays, i, j;
43
+    int ret = 0;
44
+
45
+    uint8_t *new_extradata = NULL;
46
+    size_t   new_extradata_size = 0;;
47
+
48
+    bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
49
+
50
+    bytestream2_skip(&gb, 21);
51
+    length_size = (bytestream2_get_byte(&gb) & 3) + 1;
52
+    num_arrays  = bytestream2_get_byte(&gb);
53
+
54
+    for (i = 0; i < num_arrays; i++) {
55
+        int type = bytestream2_get_byte(&gb) & 0x3f;
56
+        int cnt  = bytestream2_get_be16(&gb);
57
+
58
+        if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS ||
59
+              type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) {
60
+            av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
61
+                   type);
62
+            ret = AVERROR_INVALIDDATA;
63
+            goto fail;
64
+        }
65
+
66
+        for (j = 0; j < cnt; j++) {
67
+            int nalu_len = bytestream2_get_be16(&gb);
68
+
69
+            if (4 + FF_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
70
+                ret = AVERROR_INVALIDDATA;
71
+                goto fail;
72
+            }
73
+            ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + FF_INPUT_BUFFER_PADDING_SIZE);
74
+            if (ret < 0)
75
+                goto fail;
76
+
77
+            AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
78
+            bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
79
+            new_extradata_size += 4 + nalu_len;
80
+            memset(new_extradata + new_extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
81
+        }
82
+    }
83
+
84
+    av_freep(&avctx->extradata);
85
+    avctx->extradata      = new_extradata;
86
+    avctx->extradata_size = new_extradata_size;
87
+
88
+    if (!new_extradata_size)
89
+        av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
90
+
91
+    return length_size;
92
+fail:
93
+    av_freep(&new_extradata);
94
+    return ret;
95
+}
96
+
97
+static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
98
+                                   AVCodecContext *avctx, const char *args,
99
+                                   uint8_t **poutbuf, int *poutbuf_size,
100
+                                   const uint8_t *buf, int buf_size,
101
+                                   int keyframe)
102
+{
103
+    HEVCBSFContext *ctx = bsfc->priv_data;
104
+    GetByteContext gb;
105
+
106
+    uint8_t *out = NULL;
107
+    size_t   out_size = 0;
108
+    int got_irap = 0;
109
+    int i, ret = 0;
110
+
111
+    if (!ctx->extradata_parsed) {
112
+        if (avctx->extradata_size < MIN_HEVCC_LENGTH ||
113
+            AV_RB24(avctx->extradata) == 1           ||
114
+            AV_RB32(avctx->extradata) == 1) {
115
+            if (!ctx->logged_nonmp4_warning) {
116
+                av_log(avctx, AV_LOG_VERBOSE,
117
+                       "The input looks like it is Annex B already\n");
118
+                ctx->logged_nonmp4_warning = 1;
119
+            }
120
+            *poutbuf      = buf;
121
+            *poutbuf_size = buf_size;
122
+            return 0;
123
+        }
124
+
125
+        ret = hevc_extradata_to_annexb(avctx);
126
+        if (ret < 0)
127
+            return ret;
128
+        ctx->length_size      = ret;
129
+        ctx->extradata_parsed = 1;
130
+    }
131
+
132
+    *poutbuf_size = 0;
133
+    *poutbuf      = NULL;
134
+
135
+    bytestream2_init(&gb, buf, buf_size);
136
+
137
+    while (bytestream2_get_bytes_left(&gb)) {
138
+        uint32_t nalu_size = 0;
139
+        int      nalu_type;
140
+        int is_irap, add_extradata, extra_size;
141
+
142
+        for (i = 0; i < ctx->length_size; i++)
143
+            nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
144
+
145
+        nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
146
+
147
+        /* prepend extradata to IRAP frames */
148
+        is_irap       = nalu_type >= 16 && nalu_type <= 23;
149
+        add_extradata = is_irap && !got_irap;
150
+        extra_size    = add_extradata * avctx->extradata_size;
151
+        got_irap     |= is_irap;
152
+
153
+        if (SIZE_MAX - out_size < 4             ||
154
+            SIZE_MAX - out_size - 4 < nalu_size ||
155
+            SIZE_MAX - out_size - 4 - nalu_size < extra_size) {
156
+            ret = AVERROR_INVALIDDATA;
157
+            goto fail;
158
+        }
159
+
160
+        ret = av_reallocp(&out, out_size + 4 + nalu_size + extra_size);
161
+        if (ret < 0)
162
+            goto fail;
163
+
164
+        if (add_extradata)
165
+            memcpy(out + out_size, avctx->extradata, extra_size);
166
+        AV_WB32(out + out_size + extra_size, 1);
167
+        bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size);
168
+        out_size += 4 + nalu_size + extra_size;
169
+    }
170
+
171
+    *poutbuf      = out;
172
+    *poutbuf_size = out_size;
173
+
174
+    return 1;
175
+
176
+fail:
177
+    av_freep(&out);
178
+    return ret;
179
+}
180
+
181
+AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
182
+    "hevc_mp4toannexb",
183
+    sizeof(HEVCBSFContext),
184
+    hevc_mp4toannexb_filter,
185
+};