avformat/av1: return an error when no data is provided to ff_isom_write_av1c()
[ffmpeg.git] / libavformat / av1.c
1 /*
2  * AV1 helper functions for muxers
3  * Copyright (c) 2018 James Almer <jamrial@gmail.com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "libavutil/mem.h"
23 #include "libavcodec/av1.h"
24 #include "libavcodec/av1_parse.h"
25 #include "av1.h"
26 #include "avio.h"
27
28 int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size)
29 {
30     const uint8_t *end = buf + size;
31     int64_t obu_size;
32     int start_pos, type, temporal_id, spatial_id;
33
34     size = 0;
35     while (buf < end) {
36         int ret = parse_obu_header(buf, end - buf, &obu_size, &start_pos,
37                                    &type, &temporal_id, &spatial_id);
38         if (ret < 0)
39             return ret;
40
41         obu_size += start_pos;
42         if (obu_size > INT_MAX)
43             return AVERROR_INVALIDDATA;
44
45         switch (type) {
46         case AV1_OBU_TEMPORAL_DELIMITER:
47         case AV1_OBU_REDUNDANT_FRAME_HEADER:
48         case AV1_OBU_PADDING:
49             break;
50         default:
51             avio_write(pb, buf, obu_size);
52             size += obu_size;
53             break;
54         }
55         buf += obu_size;
56     }
57
58     return size;
59 }
60
61 int ff_av1_filter_obus_buf(const uint8_t *buf, uint8_t **out, int *size)
62 {
63     AVIOContext *pb;
64     int ret;
65
66     ret = avio_open_dyn_buf(&pb);
67     if (ret < 0)
68         return ret;
69
70     ret = ff_av1_filter_obus(pb, buf, *size);
71     if (ret < 0)
72         return ret;
73
74     av_freep(out);
75     *size = avio_close_dyn_buf(pb, out);
76
77     return ret;
78 }
79
80 int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size)
81 {
82     int64_t obu_size;
83     int start_pos, type, temporal_id, spatial_id;
84
85     if (size <= 0)
86         return AVERROR_INVALIDDATA;
87
88     while (size > 0) {
89         int ret = parse_obu_header(buf, size, &obu_size, &start_pos,
90                                    &type, &temporal_id, &spatial_id);
91         if (ret < 0)
92             return ret;
93
94         obu_size += start_pos;
95         if (obu_size > INT_MAX)
96             return AVERROR_INVALIDDATA;
97
98         switch (type) {
99         case AV1_OBU_SEQUENCE_HEADER:
100         case AV1_OBU_METADATA:
101             avio_write(pb, buf, obu_size);
102             break;
103         default:
104             break;
105         }
106         size -= obu_size;
107         buf  += obu_size;
108     }
109
110     return 0;
111 }