/work/svt-av1/Source/Lib/Globals/metadata_handle.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, Alliance for Open Media. All rights reserved |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | |
12 | | #include <stdio.h> |
13 | | #include <stdlib.h> |
14 | | #include <math.h> |
15 | | #include <string.h> |
16 | | |
17 | | #include "EbSvtAv1Metadata.h" |
18 | | #include "EbSvtAv1Enc.h" |
19 | | #include "svt_log.h" |
20 | | #include "svt_malloc.h" |
21 | | |
22 | 0 | EB_API SvtMetadataT* svt_metadata_alloc(const uint32_t type, const uint8_t* data, const size_t sz) { |
23 | 0 | if (!data || sz == 0) { |
24 | 0 | return NULL; |
25 | 0 | } |
26 | 0 | SvtMetadataT* metadata; |
27 | 0 | EB_MALLOC_OBJECT_NO_CHECK(metadata); |
28 | 0 | if (!metadata) { |
29 | 0 | return NULL; |
30 | 0 | } |
31 | 0 | metadata->type = type; |
32 | 0 | EB_MALLOC_ARRAY_NO_CHECK(metadata->payload, sz); |
33 | 0 | if (!metadata->payload) { |
34 | 0 | EB_FREE(metadata); |
35 | 0 | return NULL; |
36 | 0 | } |
37 | 0 | memcpy(metadata->payload, data, sz); |
38 | 0 | metadata->sz = sz; |
39 | 0 | return metadata; |
40 | 0 | } |
41 | | |
42 | 0 | EB_API void svt_metadata_free(void* ptr) { |
43 | 0 | SvtMetadataT** metadata = (SvtMetadataT**)ptr; |
44 | 0 | if (*metadata) { |
45 | 0 | if ((*metadata)->payload) { |
46 | 0 | EB_FREE_ARRAY((*metadata)->payload); |
47 | 0 | (*metadata)->payload = NULL; |
48 | 0 | } |
49 | 0 | EB_FREE(*metadata); |
50 | 0 | *metadata = NULL; |
51 | 0 | } |
52 | 0 | } |
53 | | |
54 | 0 | EB_API SvtMetadataArrayT* svt_metadata_array_alloc(const size_t sz) { |
55 | 0 | SvtMetadataArrayT* arr; |
56 | 0 | EB_CALLOC_ARRAY_NO_CHECK(arr, 1); |
57 | 0 | if (!arr) { |
58 | 0 | return NULL; |
59 | 0 | } |
60 | 0 | if (sz > 0) { |
61 | 0 | EB_CALLOC_ARRAY_NO_CHECK(arr->metadata_array, sz); |
62 | 0 | if (!arr->metadata_array) { |
63 | 0 | svt_metadata_array_free(&arr); |
64 | 0 | return NULL; |
65 | 0 | } |
66 | 0 | arr->sz = sz; |
67 | 0 | } |
68 | 0 | return arr; |
69 | 0 | } |
70 | | |
71 | 474 | EB_API void svt_metadata_array_free(void* arr) { |
72 | 474 | SvtMetadataArrayT** metadata = (SvtMetadataArrayT**)arr; |
73 | 474 | if (*metadata) { |
74 | 0 | if ((*metadata)->metadata_array) { |
75 | 0 | for (size_t i = 0; i < (*metadata)->sz; i++) { |
76 | 0 | svt_metadata_free(&((*metadata)->metadata_array[i])); |
77 | 0 | } |
78 | 0 | EB_FREE((*metadata)->metadata_array); |
79 | 0 | } |
80 | 0 | EB_FREE(*metadata); |
81 | 0 | } |
82 | 474 | *metadata = NULL; |
83 | 474 | } |
84 | | |
85 | 0 | EB_API int svt_add_metadata(EbBufferHeaderType* buffer, const uint32_t type, const uint8_t* data, const size_t sz) { |
86 | 0 | if (!buffer) { |
87 | 0 | return -1; |
88 | 0 | } |
89 | 0 | if (!buffer->metadata) { |
90 | 0 | buffer->metadata = svt_metadata_array_alloc(0); |
91 | 0 | if (!buffer->metadata) { |
92 | 0 | return -1; |
93 | 0 | } |
94 | 0 | } |
95 | 0 | SvtMetadataT* metadata = svt_metadata_alloc(type, data, sz); |
96 | 0 | if (!metadata) { |
97 | 0 | return -1; |
98 | 0 | } |
99 | 0 | EB_REALLOC_ARRAY_NO_CHECK(buffer->metadata->metadata_array, buffer->metadata->sz + 1); |
100 | 0 | if (!buffer->metadata->metadata_array) { |
101 | 0 | svt_metadata_free(&metadata); |
102 | 0 | return -1; |
103 | 0 | } |
104 | 0 | buffer->metadata->metadata_array[buffer->metadata->sz] = metadata; |
105 | 0 | buffer->metadata->sz++; |
106 | 0 | return 0; |
107 | 0 | } |
108 | | |
109 | 474 | EbErrorType svt_aom_copy_metadata_buffer(EbBufferHeaderType* dst, const SvtMetadataArrayT* const src) { |
110 | 474 | if (!dst || !src) { |
111 | 474 | return EB_ErrorBadParameter; |
112 | 474 | } |
113 | 0 | EbErrorType return_error = EB_ErrorNone; |
114 | 0 | for (size_t i = 0; i < src->sz; ++i) { |
115 | 0 | SvtMetadataT* current_metadata = src->metadata_array[i]; |
116 | 0 | const uint32_t type = current_metadata->type; |
117 | 0 | const uint8_t* payload = current_metadata->payload; |
118 | 0 | const size_t sz = current_metadata->sz; |
119 | |
|
120 | 0 | if (svt_add_metadata(dst, type, payload, sz)) { |
121 | 0 | return_error = EB_ErrorInsufficientResources; |
122 | 0 | SVT_ERROR("Metadata of type %d could not be added to the buffer.\n", type); |
123 | 0 | } |
124 | 0 | } |
125 | 0 | return return_error; |
126 | 474 | } |
127 | | |
128 | 0 | EB_API size_t svt_metadata_size(SvtMetadataArrayT* metadata, const EbAv1MetadataType type) { |
129 | 0 | size_t sz = 0; |
130 | 0 | if (!metadata || !metadata->metadata_array || metadata->sz == 0) { |
131 | 0 | return 0; |
132 | 0 | } else { |
133 | 0 | for (size_t i = 0; i < metadata->sz; i++) { |
134 | 0 | SvtMetadataT* current_metadata = metadata->metadata_array[i]; |
135 | 0 | if (current_metadata && current_metadata->payload && current_metadata->type == type) { |
136 | 0 | sz += current_metadata->sz + 1 //obu type |
137 | 0 | + 1 //trailing byte |
138 | 0 | + 1 //header size |
139 | 0 | + 1; //length field size |
140 | 0 | } |
141 | 0 | } |
142 | 0 | } |
143 | 0 | return sz; |
144 | 0 | } |
145 | | |
146 | 0 | static inline uint16_t intswap16(uint16_t x) { |
147 | 0 | return x << 8 | x >> 8; |
148 | 0 | } |
149 | | |
150 | 0 | static inline uint32_t intswap32(uint32_t x) { |
151 | 0 | return x >> 24 | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | x << 24; |
152 | 0 | } |
153 | | |
154 | 0 | static inline uint16_t clip16be(double x) { |
155 | 0 | return intswap16(x > 65535 ? 65535 : (uint16_t)x); |
156 | 0 | } |
157 | | |
158 | | // Parses "(d1,d2)" into two double values and returns the pointer to after the closing parenthesis. |
159 | | // returns NULL if it fails |
160 | 0 | static inline char* parse_double(const char* p, double* d1, double* d2) { |
161 | 0 | char* endptr; |
162 | 0 | if (*p != '(') { |
163 | 0 | return NULL; |
164 | 0 | } |
165 | 0 | *d1 = strtod(p + 1, &endptr); |
166 | 0 | if (*endptr != ',') { |
167 | 0 | return NULL; |
168 | 0 | } |
169 | 0 | *d2 = strtod(endptr + 1, &endptr); |
170 | 0 | return *endptr == ')' ? endptr + 1 : NULL; |
171 | 0 | } |
172 | | |
173 | 0 | EB_API int svt_aom_parse_mastering_display(struct EbSvtAv1MasteringDisplayInfo* mdi, const char* md_str) { |
174 | 0 | if (!mdi || !md_str) { |
175 | 0 | return 0; |
176 | 0 | } |
177 | 0 | double gx = 0, gy = 0, bx = 0, by = 0, rx = 0, ry = 0, wx = 0, wy = 0, max_luma = 0, min_luma = 0; |
178 | 0 | while (md_str && *md_str) { |
179 | 0 | switch (*md_str) { |
180 | 0 | case 'G': |
181 | 0 | case 'g': |
182 | 0 | md_str = parse_double(md_str + 1, &gx, &gy); |
183 | 0 | break; |
184 | 0 | case 'B': |
185 | 0 | case 'b': |
186 | 0 | md_str = parse_double(md_str + 1, &bx, &by); |
187 | 0 | break; |
188 | 0 | case 'R': |
189 | 0 | case 'r': |
190 | 0 | md_str = parse_double(md_str + 1, &rx, &ry); |
191 | 0 | break; |
192 | 0 | case 'W': |
193 | 0 | case 'w': |
194 | 0 | md_str = parse_double(md_str + 2, &wx, &wy); |
195 | 0 | break; |
196 | 0 | case 'L': |
197 | 0 | case 'l': |
198 | 0 | md_str = parse_double(md_str + 1, &max_luma, &min_luma); |
199 | 0 | break; |
200 | 0 | default: |
201 | 0 | break; |
202 | 0 | } |
203 | 0 | } |
204 | 0 | #define between1(x) (x >= 0.0 && x <= 1.0) |
205 | 0 | if (!between1(gx) || !between1(gy) || !between1(bx) || !between1(by) || !between1(rx) || !between1(ry) || |
206 | 0 | !between1(wx) || !between1(wy)) { |
207 | 0 | SVT_WARN("Invalid mastering display info will be clipped to 0.0 to 1.0\n"); |
208 | 0 | } |
209 | 0 | #undef between1 |
210 | 0 | memset(mdi, 0, sizeof(*mdi)); |
211 | 0 | rx = round(rx * (1 << 16)); |
212 | 0 | ry = round(ry * (1 << 16)); |
213 | 0 | gx = round(gx * (1 << 16)); |
214 | 0 | gy = round(gy * (1 << 16)); |
215 | 0 | bx = round(bx * (1 << 16)); |
216 | 0 | by = round(by * (1 << 16)); |
217 | 0 | wx = round(wx * (1 << 16)); |
218 | 0 | wy = round(wy * (1 << 16)); |
219 | 0 | max_luma = round(max_luma * (1 << 8)); |
220 | 0 | min_luma = round(min_luma * (1 << 14)); |
221 | |
|
222 | 0 | mdi->r = (struct EbSvtAv1ChromaPoints){ |
223 | 0 | .x = clip16be(rx), |
224 | 0 | .y = clip16be(ry), |
225 | 0 | }; |
226 | 0 | mdi->g = (struct EbSvtAv1ChromaPoints){ |
227 | 0 | .x = clip16be(gx), |
228 | 0 | .y = clip16be(gy), |
229 | 0 | }; |
230 | 0 | mdi->b = (struct EbSvtAv1ChromaPoints){ |
231 | 0 | .x = clip16be(bx), |
232 | 0 | .y = clip16be(by), |
233 | 0 | }; |
234 | 0 | mdi->white_point = (struct EbSvtAv1ChromaPoints){ |
235 | 0 | .x = clip16be(wx), |
236 | 0 | .y = clip16be(wy), |
237 | 0 | }; |
238 | 0 | mdi->max_luma = intswap32((uint32_t)max_luma); |
239 | 0 | mdi->min_luma = intswap32((uint32_t)min_luma); |
240 | 0 | return 1; |
241 | 0 | } |
242 | | |
243 | 0 | EB_API int svt_aom_parse_content_light_level(struct EbContentLightLevel* cll, const char* cll_str) { |
244 | 0 | if (!cll || !cll_str) { |
245 | 0 | return 0; |
246 | 0 | } |
247 | 0 | char* endptr; |
248 | 0 | double max_cll = strtod(cll_str, &endptr); |
249 | 0 | if (*endptr != ',') { |
250 | 0 | goto fail; |
251 | 0 | } |
252 | 0 | double max_fall = strtod(endptr + 1, &endptr); |
253 | 0 | if (*endptr) { |
254 | 0 | goto fail; |
255 | 0 | } |
256 | 0 | cll->max_cll = clip16be(max_cll); |
257 | 0 | cll->max_fall = clip16be(max_fall); |
258 | 0 | return 1; |
259 | | |
260 | 0 | fail: |
261 | 0 | SVT_WARN("Invalid cll provided\n"); |
262 | 0 | return 0; |
263 | 0 | } |