1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdint.h>
20 
21 #include "libavutil/log.h"
22 #include "libavutil/opt.h"
23 
24 #include "av1.h"
25 #include "av1_parse.h"
26 #include "bsf.h"
27 #include "bsf_internal.h"
28 #include "bytestream.h"
29 #include "h2645_parse.h"
30 #include "h264.h"
31 #include "hevc.h"
32 #include "startcode.h"
33 #include "vc1_common.h"
34 
35 typedef struct ExtractExtradataContext {
36     const AVClass *class;
37 
38     int (*extract)(AVBSFContext *ctx, AVPacket *pkt,
39                    uint8_t **data, int *size);
40 
41     /* AV1 specific fields */
42     AV1Packet av1_pkt;
43 
44     /* H264/HEVC specific fields */
45     H2645Packet h2645_pkt;
46 
47     /* AVOptions */
48     int remove;
49 } ExtractExtradataContext;
50 
val_in_array(const int *arr, int len, int val)51 static int val_in_array(const int *arr, int len, int val)
52 {
53     int i;
54     for (i = 0; i < len; i++)
55         if (arr[i] == val)
56             return 1;
57     return 0;
58 }
59 
extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)60 static int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt,
61                                  uint8_t **data, int *size)
62 {
63     static const int extradata_obu_types[] = {
64         AV1_OBU_SEQUENCE_HEADER, AV1_OBU_METADATA,
65     };
66     ExtractExtradataContext *s = ctx->priv_data;
67 
68     int extradata_size = 0, filtered_size = 0;
69     int nb_extradata_obu_types = FF_ARRAY_ELEMS(extradata_obu_types);
70     int i, has_seq = 0, ret = 0;
71 
72     ret = ff_av1_packet_split(&s->av1_pkt, pkt->data, pkt->size, ctx);
73     if (ret < 0)
74         return ret;
75 
76     for (i = 0; i < s->av1_pkt.nb_obus; i++) {
77         AV1OBU *obu = &s->av1_pkt.obus[i];
78         if (val_in_array(extradata_obu_types, nb_extradata_obu_types, obu->type)) {
79             extradata_size += obu->raw_size;
80             if (obu->type == AV1_OBU_SEQUENCE_HEADER)
81                 has_seq = 1;
82         } else if (s->remove) {
83             filtered_size += obu->raw_size;
84         }
85     }
86 
87     if (extradata_size && has_seq) {
88         AVBufferRef *filtered_buf = NULL;
89         PutByteContext pb_filtered_data, pb_extradata;
90         uint8_t *extradata;
91 
92         if (s->remove) {
93             filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
94             if (!filtered_buf) {
95                 return AVERROR(ENOMEM);
96             }
97             memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
98         }
99 
100         extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
101         if (!extradata) {
102             av_buffer_unref(&filtered_buf);
103             return AVERROR(ENOMEM);
104         }
105 
106         *data = extradata;
107         *size = extradata_size;
108 
109         bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
110         if (s->remove)
111             bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
112 
113         for (i = 0; i < s->av1_pkt.nb_obus; i++) {
114             AV1OBU *obu = &s->av1_pkt.obus[i];
115             if (val_in_array(extradata_obu_types, nb_extradata_obu_types,
116                              obu->type)) {
117                 bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size);
118             } else if (s->remove) {
119                 bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size);
120             }
121         }
122 
123         if (s->remove) {
124             av_buffer_unref(&pkt->buf);
125             pkt->buf  = filtered_buf;
126             pkt->data = filtered_buf->data;
127             pkt->size = filtered_size;
128         }
129     }
130 
131     return 0;
132 }
133 
extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)134 static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt,
135                                    uint8_t **data, int *size)
136 {
137     static const int extradata_nal_types_hevc[] = {
138         HEVC_NAL_VPS, HEVC_NAL_SPS, HEVC_NAL_PPS,
139     };
140     static const int extradata_nal_types_h264[] = {
141         H264_NAL_SPS, H264_NAL_PPS,
142     };
143 
144     ExtractExtradataContext *s = ctx->priv_data;
145 
146     int extradata_size = 0, filtered_size = 0;
147     const int *extradata_nal_types;
148     int nb_extradata_nal_types;
149     int i, has_sps = 0, has_vps = 0, ret = 0;
150 
151     if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
152         extradata_nal_types    = extradata_nal_types_hevc;
153         nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc);
154     } else {
155         extradata_nal_types    = extradata_nal_types_h264;
156         nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264);
157     }
158 
159     ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size,
160                                 ctx, 0, 0, ctx->par_in->codec_id, 1, 0);
161     if (ret < 0)
162         return ret;
163 
164     for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
165         H2645NAL *nal = &s->h2645_pkt.nals[i];
166         if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) {
167             extradata_size += nal->raw_size + 3;
168             if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
169                 if (nal->type == HEVC_NAL_SPS) has_sps = 1;
170                 if (nal->type == HEVC_NAL_VPS) has_vps = 1;
171             } else {
172                 if (nal->type == H264_NAL_SPS) has_sps = 1;
173             }
174         } else if (s->remove) {
175             filtered_size += nal->raw_size + 3;
176         }
177     }
178 
179     if (extradata_size &&
180         ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) ||
181          (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) {
182         AVBufferRef *filtered_buf = NULL;
183         PutByteContext pb_filtered_data, pb_extradata;
184         uint8_t *extradata;
185 
186         if (s->remove) {
187             filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
188             if (!filtered_buf) {
189                 return AVERROR(ENOMEM);
190             }
191             memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
192         }
193 
194         extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
195         if (!extradata) {
196             av_buffer_unref(&filtered_buf);
197             return AVERROR(ENOMEM);
198         }
199 
200         *data = extradata;
201         *size = extradata_size;
202 
203         bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
204         if (s->remove)
205             bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
206 
207         for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
208             H2645NAL *nal = &s->h2645_pkt.nals[i];
209             if (val_in_array(extradata_nal_types, nb_extradata_nal_types,
210                              nal->type)) {
211                 bytestream2_put_be24u(&pb_extradata, 1); //startcode
212                 bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size);
213             } else if (s->remove) {
214                 bytestream2_put_be24u(&pb_filtered_data, 1); // startcode
215                 bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size);
216             }
217         }
218 
219         if (s->remove) {
220             av_buffer_unref(&pkt->buf);
221             pkt->buf  = filtered_buf;
222             pkt->data = filtered_buf->data;
223             pkt->size = filtered_size;
224         }
225     }
226 
227     return 0;
228 }
229 
extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)230 static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt,
231                                  uint8_t **data, int *size)
232 {
233     ExtractExtradataContext *s = ctx->priv_data;
234     const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
235     uint32_t state = UINT32_MAX;
236     int has_extradata = 0, extradata_size = 0;
237 
238     while (ptr < end) {
239         ptr = avpriv_find_start_code(ptr, end, &state);
240         if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) {
241             has_extradata = 1;
242         } else if (has_extradata && IS_MARKER(state)) {
243             extradata_size = ptr - 4 - pkt->data;
244             break;
245         }
246     }
247 
248     if (extradata_size) {
249         *data = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
250         if (!*data)
251             return AVERROR(ENOMEM);
252 
253         memcpy(*data, pkt->data, extradata_size);
254         *size = extradata_size;
255 
256         if (s->remove) {
257             pkt->data += extradata_size;
258             pkt->size -= extradata_size;
259         }
260     }
261 
262     return 0;
263 }
264 
extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)265 static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt,
266                                      uint8_t **data, int *size)
267 {
268     ExtractExtradataContext *s = ctx->priv_data;
269     uint32_t state = UINT32_MAX;
270     int i, found = 0;
271 
272     for (i = 0; i < pkt->size; i++) {
273         state = (state << 8) | pkt->data[i];
274         if (state == 0x1B3)
275             found = 1;
276         else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) {
277             *size = i - 3;
278             *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
279             if (!*data)
280                 return AVERROR(ENOMEM);
281 
282             memcpy(*data, pkt->data, *size);
283 
284             if (s->remove) {
285                 pkt->data += *size;
286                 pkt->size -= *size;
287             }
288             break;
289         }
290     }
291     return 0;
292 }
293 
extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)294 static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt,
295                                    uint8_t **data, int *size)
296 {
297     ExtractExtradataContext *s = ctx->priv_data;
298     const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
299     uint32_t state = UINT32_MAX;
300 
301     while (ptr < end) {
302         ptr = avpriv_find_start_code(ptr, end, &state);
303         if (state == 0x1B3 || state == 0x1B6) {
304             if (ptr - pkt->data > 4) {
305                 *size = ptr - 4 - pkt->data;
306                 *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
307                 if (!*data)
308                     return AVERROR(ENOMEM);
309 
310                 memcpy(*data, pkt->data, *size);
311 
312                 if (s->remove) {
313                     pkt->data += *size;
314                     pkt->size -= *size;
315                 }
316             }
317             break;
318         }
319     }
320     return 0;
321 }
322 
323 static const struct {
324     enum AVCodecID id;
325     int (*extract)(AVBSFContext *ctx, AVPacket *pkt,
326                    uint8_t **data, int *size);
327 } extract_tab[] = {
328     { AV_CODEC_ID_AV1,        extract_extradata_av1     },
329     { AV_CODEC_ID_AVS2,       extract_extradata_mpeg4   },
330     { AV_CODEC_ID_AVS3,       extract_extradata_mpeg4   },
331     { AV_CODEC_ID_CAVS,       extract_extradata_mpeg4   },
332     { AV_CODEC_ID_H264,       extract_extradata_h2645   },
333     { AV_CODEC_ID_HEVC,       extract_extradata_h2645   },
334     { AV_CODEC_ID_MPEG1VIDEO, extract_extradata_mpeg12  },
335     { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12  },
336     { AV_CODEC_ID_MPEG4,      extract_extradata_mpeg4   },
337     { AV_CODEC_ID_VC1,        extract_extradata_vc1     },
338 };
339 
extract_extradata_init(AVBSFContext *ctx)340 static int extract_extradata_init(AVBSFContext *ctx)
341 {
342     ExtractExtradataContext *s = ctx->priv_data;
343     int i;
344 
345     for (i = 0; i < FF_ARRAY_ELEMS(extract_tab); i++) {
346         if (extract_tab[i].id == ctx->par_in->codec_id) {
347             s->extract = extract_tab[i].extract;
348             break;
349         }
350     }
351     if (!s->extract)
352         return AVERROR_BUG;
353 
354     return 0;
355 }
356 
extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt)357 static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt)
358 {
359     ExtractExtradataContext *s = ctx->priv_data;
360     uint8_t *extradata = NULL;
361     int extradata_size;
362     int ret = 0;
363 
364     ret = ff_bsf_get_packet_ref(ctx, pkt);
365     if (ret < 0)
366         return ret;
367 
368     ret = s->extract(ctx, pkt, &extradata, &extradata_size);
369     if (ret < 0)
370         goto fail;
371 
372     if (extradata) {
373         memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
374         ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
375                                       extradata, extradata_size);
376         if (ret < 0) {
377             av_freep(&extradata);
378             goto fail;
379         }
380     }
381 
382     return 0;
383 
384 fail:
385     av_packet_unref(pkt);
386     return ret;
387 }
388 
extract_extradata_close(AVBSFContext *ctx)389 static void extract_extradata_close(AVBSFContext *ctx)
390 {
391     ExtractExtradataContext *s = ctx->priv_data;
392     ff_av1_packet_uninit(&s->av1_pkt);
393     ff_h2645_packet_uninit(&s->h2645_pkt);
394 }
395 
396 static const enum AVCodecID codec_ids[] = {
397     AV_CODEC_ID_AV1,
398     AV_CODEC_ID_AVS2,
399     AV_CODEC_ID_AVS3,
400     AV_CODEC_ID_CAVS,
401     AV_CODEC_ID_H264,
402     AV_CODEC_ID_HEVC,
403     AV_CODEC_ID_MPEG1VIDEO,
404     AV_CODEC_ID_MPEG2VIDEO,
405     AV_CODEC_ID_MPEG4,
406     AV_CODEC_ID_VC1,
407     AV_CODEC_ID_NONE,
408 };
409 
410 #define OFFSET(x) offsetof(ExtractExtradataContext, x)
411 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
412 static const AVOption options[] = {
413     { "remove", "remove the extradata from the bitstream", OFFSET(remove), AV_OPT_TYPE_INT,
414         { .i64 = 0 }, 0, 1, FLAGS },
415     { NULL },
416 };
417 
418 static const AVClass extract_extradata_class = {
419     .class_name = "extract_extradata",
420     .item_name  = av_default_item_name,
421     .option     = options,
422     .version    = LIBAVUTIL_VERSION_INT,
423 };
424 
425 const FFBitStreamFilter ff_extract_extradata_bsf = {
426     .p.name         = "extract_extradata",
427     .p.codec_ids    = codec_ids,
428     .p.priv_class   = &extract_extradata_class,
429     .priv_data_size = sizeof(ExtractExtradataContext),
430     .init           = extract_extradata_init,
431     .filter         = extract_extradata_filter,
432     .close          = extract_extradata_close,
433 };
434