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 |
|
|
static int FUNC(filler_payload) |
20 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
21 |
|
|
SEIRawFillerPayload *current, SEIMessageState *state) |
22 |
|
|
{ |
23 |
|
|
int err, i; |
24 |
|
|
|
25 |
|
|
HEADER("Filler Payload"); |
26 |
|
|
|
27 |
|
|
#ifdef READ |
28 |
|
|
current->payload_size = state->payload_size; |
29 |
|
|
#endif |
30 |
|
|
|
31 |
|
|
for (i = 0; i < current->payload_size; i++) |
32 |
|
|
fixed(8, ff_byte, 0xff); |
33 |
|
|
|
34 |
|
|
return 0; |
35 |
|
|
} |
36 |
|
|
|
37 |
|
150 |
static int FUNC(user_data_registered) |
38 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
39 |
|
|
SEIRawUserDataRegistered *current, SEIMessageState *state) |
40 |
|
|
{ |
41 |
|
|
int err, i, j; |
42 |
|
|
|
43 |
|
150 |
HEADER("User Data Registered ITU-T T.35"); |
44 |
|
|
|
45 |
✗✓ |
150 |
u(8, itu_t_t35_country_code, 0x00, 0xff); |
46 |
✓✗ |
150 |
if (current->itu_t_t35_country_code != 0xff) |
47 |
|
150 |
i = 1; |
48 |
|
|
else { |
49 |
|
|
u(8, itu_t_t35_country_code_extension_byte, 0x00, 0xff); |
50 |
|
|
i = 2; |
51 |
|
|
} |
52 |
|
|
|
53 |
|
|
#ifdef READ |
54 |
✗✓ |
50 |
if (state->payload_size < i) { |
55 |
|
|
av_log(ctx->log_ctx, AV_LOG_ERROR, |
56 |
|
|
"Invalid SEI user data registered payload.\n"); |
57 |
|
|
return AVERROR_INVALIDDATA; |
58 |
|
|
} |
59 |
|
50 |
current->data_length = state->payload_size - i; |
60 |
|
|
#endif |
61 |
|
|
|
62 |
✗✓✓ |
150 |
allocate(current->data, current->data_length); |
63 |
✓✓ |
1608 |
for (j = 0; j < current->data_length; j++) |
64 |
✗✓ |
1458 |
xu(8, itu_t_t35_payload_byte[], current->data[j], 0x00, 0xff, 1, i + j); |
65 |
|
|
|
66 |
|
150 |
return 0; |
67 |
|
|
} |
68 |
|
|
|
69 |
|
|
static int FUNC(user_data_unregistered) |
70 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
71 |
|
|
SEIRawUserDataUnregistered *current, SEIMessageState *state) |
72 |
|
|
{ |
73 |
|
|
int err, i; |
74 |
|
|
|
75 |
|
|
HEADER("User Data Unregistered"); |
76 |
|
|
|
77 |
|
|
#ifdef READ |
78 |
|
|
if (state->payload_size < 16) { |
79 |
|
|
av_log(ctx->log_ctx, AV_LOG_ERROR, |
80 |
|
|
"Invalid SEI user data unregistered payload.\n"); |
81 |
|
|
return AVERROR_INVALIDDATA; |
82 |
|
|
} |
83 |
|
|
current->data_length = state->payload_size - 16; |
84 |
|
|
#endif |
85 |
|
|
|
86 |
|
|
for (i = 0; i < 16; i++) |
87 |
|
|
us(8, uuid_iso_iec_11578[i], 0x00, 0xff, 1, i); |
88 |
|
|
|
89 |
|
|
allocate(current->data, current->data_length); |
90 |
|
|
|
91 |
|
|
for (i = 0; i < current->data_length; i++) |
92 |
|
|
xu(8, user_data_payload_byte[i], current->data[i], 0x00, 0xff, 1, i); |
93 |
|
|
|
94 |
|
|
return 0; |
95 |
|
|
} |
96 |
|
|
|
97 |
|
6 |
static int FUNC(mastering_display_colour_volume) |
98 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
99 |
|
|
SEIRawMasteringDisplayColourVolume *current, SEIMessageState *state) |
100 |
|
|
{ |
101 |
|
|
int err, c; |
102 |
|
|
|
103 |
|
6 |
HEADER("Mastering Display Colour Volume"); |
104 |
|
|
|
105 |
✓✓ |
24 |
for (c = 0; c < 3; c++) { |
106 |
✗✓ |
18 |
ubs(16, display_primaries_x[c], 1, c); |
107 |
✗✓ |
18 |
ubs(16, display_primaries_y[c], 1, c); |
108 |
|
|
} |
109 |
|
|
|
110 |
✗✓ |
6 |
ub(16, white_point_x); |
111 |
✗✓ |
6 |
ub(16, white_point_y); |
112 |
|
|
|
113 |
✗✓ |
6 |
ub(32, max_display_mastering_luminance); |
114 |
✗✓ |
6 |
ub(32, min_display_mastering_luminance); |
115 |
|
|
|
116 |
|
6 |
return 0; |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
static int FUNC(content_light_level_info) |
120 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
121 |
|
|
SEIRawContentLightLevelInfo *current, SEIMessageState *state) |
122 |
|
|
{ |
123 |
|
|
int err; |
124 |
|
|
|
125 |
|
|
HEADER("Content Light Level Information"); |
126 |
|
|
|
127 |
|
|
ub(16, max_content_light_level); |
128 |
|
|
ub(16, max_pic_average_light_level); |
129 |
|
|
|
130 |
|
|
return 0; |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
static int FUNC(alternative_transfer_characteristics) |
134 |
|
|
(CodedBitstreamContext *ctx, RWContext *rw, |
135 |
|
|
SEIRawAlternativeTransferCharacteristics *current, |
136 |
|
|
SEIMessageState *state) |
137 |
|
|
{ |
138 |
|
|
int err; |
139 |
|
|
|
140 |
|
|
HEADER("Alternative Transfer Characteristics"); |
141 |
|
|
|
142 |
|
|
ub(8, preferred_transfer_characteristics); |
143 |
|
|
|
144 |
|
|
return 0; |
145 |
|
|
} |
146 |
|
|
|
147 |
|
11396 |
static int FUNC(message)(CodedBitstreamContext *ctx, RWContext *rw, |
148 |
|
|
SEIRawMessage *current) |
149 |
|
|
{ |
150 |
|
|
const SEIMessageTypeDescriptor *desc; |
151 |
|
|
int err, i; |
152 |
|
|
|
153 |
|
11396 |
desc = ff_cbs_sei_find_type(ctx, current->payload_type); |
154 |
✓✓ |
11396 |
if (desc) { |
155 |
|
11366 |
SEIMessageState state = { |
156 |
|
11366 |
.payload_type = current->payload_type, |
157 |
|
11366 |
.payload_size = current->payload_size, |
158 |
|
11366 |
.extension_present = current->extension_bit_length > 0, |
159 |
|
|
}; |
160 |
|
|
int start_position, current_position, bits_written; |
161 |
|
|
|
162 |
|
|
#ifdef READ |
163 |
✗✓ |
3790 |
CHECK(ff_cbs_sei_alloc_message_payload(current, desc)); |
164 |
|
|
#endif |
165 |
|
|
|
166 |
|
11366 |
start_position = bit_position(rw); |
167 |
|
|
|
168 |
✗✓ |
11366 |
CHECK(desc->READWRITE(ctx, rw, current->payload, &state)); |
169 |
|
|
|
170 |
|
11366 |
current_position = bit_position(rw); |
171 |
|
11366 |
bits_written = current_position - start_position; |
172 |
|
|
|
173 |
✓✓✓✗
|
11366 |
if (byte_alignment(rw) || state.extension_present || |
174 |
✗✓ |
8460 |
bits_written < 8 * current->payload_size) { |
175 |
|
|
size_t bits_left; |
176 |
|
|
|
177 |
|
|
#ifdef READ |
178 |
|
970 |
GetBitContext tmp = *rw; |
179 |
|
|
int trailing_bits, trailing_zero_bits; |
180 |
|
|
|
181 |
|
970 |
bits_left = 8 * current->payload_size - bits_written; |
182 |
✗✓ |
970 |
if (bits_left > 8) |
183 |
|
|
skip_bits_long(&tmp, bits_left - 8); |
184 |
|
970 |
trailing_bits = get_bits(&tmp, FFMIN(bits_left, 8)); |
185 |
✗✓ |
970 |
if (trailing_bits == 0) { |
186 |
|
|
// The trailing bits must contain a bit_equal_to_one, so |
187 |
|
|
// they can't all be zero. |
188 |
|
|
return AVERROR_INVALIDDATA; |
189 |
|
|
} |
190 |
|
970 |
trailing_zero_bits = ff_ctz(trailing_bits); |
191 |
|
970 |
current->extension_bit_length = |
192 |
|
970 |
bits_left - 1 - trailing_zero_bits; |
193 |
|
|
#endif |
194 |
|
|
|
195 |
✗✓ |
2906 |
if (current->extension_bit_length > 0) { |
196 |
|
|
allocate(current->extension_data, |
197 |
|
|
(current->extension_bit_length + 7) / 8); |
198 |
|
|
|
199 |
|
|
bits_left = current->extension_bit_length; |
200 |
|
|
for (i = 0; bits_left > 0; i++) { |
201 |
|
|
int length = FFMIN(bits_left, 8); |
202 |
|
|
xu(length, reserved_payload_extension_data, |
203 |
|
|
current->extension_data[i], |
204 |
|
|
0, MAX_UINT_BITS(length), 0); |
205 |
|
|
bits_left -= length; |
206 |
|
|
} |
207 |
|
|
} |
208 |
|
|
|
209 |
✗✓ |
2906 |
fixed(1, bit_equal_to_one, 1); |
210 |
✓✓ |
8910 |
while (byte_alignment(rw)) |
211 |
✗✓ |
6004 |
fixed(1, bit_equal_to_zero, 0); |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
#ifdef WRITE |
215 |
|
7576 |
current->payload_size = (put_bits_count(rw) - start_position) / 8; |
216 |
|
|
#endif |
217 |
|
|
} else { |
218 |
|
|
uint8_t *data; |
219 |
|
|
|
220 |
✗✓✓ |
30 |
allocate(current->payload, current->payload_size); |
221 |
|
30 |
data = current->payload; |
222 |
|
|
|
223 |
✓✓ |
10494 |
for (i = 0; i < current->payload_size; i++) |
224 |
✗✓ |
10464 |
xu(8, payload_byte[i], data[i], 0, 255, 1, i); |
225 |
|
|
} |
226 |
|
|
|
227 |
|
11396 |
return 0; |
228 |
|
|
} |
229 |
|
|
|
230 |
|
3759 |
static int FUNC(message_list)(CodedBitstreamContext *ctx, RWContext *rw, |
231 |
|
|
SEIRawMessageList *current, int prefix) |
232 |
|
|
{ |
233 |
|
|
SEIRawMessage *message; |
234 |
|
|
int err, k; |
235 |
|
|
|
236 |
|
|
#ifdef READ |
237 |
|
1900 |
for (k = 0;; k++) { |
238 |
|
1900 |
uint32_t payload_type = 0; |
239 |
|
1900 |
uint32_t payload_size = 0; |
240 |
|
|
uint32_t tmp; |
241 |
|
|
GetBitContext payload_gbc; |
242 |
|
|
|
243 |
|
1920 |
while (show_bits(rw, 8) == 0xff) { |
244 |
|
20 |
fixed(8, ff_byte, 0xff); |
245 |
|
20 |
payload_type += 255; |
246 |
|
|
} |
247 |
|
1900 |
xu(8, last_payload_type_byte, tmp, 0, 254, 0); |
248 |
|
1900 |
payload_type += tmp; |
249 |
|
|
|
250 |
|
1905 |
while (show_bits(rw, 8) == 0xff) { |
251 |
|
5 |
fixed(8, ff_byte, 0xff); |
252 |
|
5 |
payload_size += 255; |
253 |
|
|
} |
254 |
|
1900 |
xu(8, last_payload_size_byte, tmp, 0, 254, 0); |
255 |
|
1900 |
payload_size += tmp; |
256 |
|
|
|
257 |
|
|
// There must be space remaining for both the payload and |
258 |
|
|
// the trailing bits on the SEI NAL unit. |
259 |
|
1900 |
if (payload_size + 1 > get_bits_left(rw) / 8) { |
260 |
|
|
av_log(ctx->log_ctx, AV_LOG_ERROR, |
261 |
|
|
"Invalid SEI message: payload_size too large " |
262 |
|
|
"(%"PRIu32" bytes).\n", payload_size); |
263 |
|
|
return AVERROR_INVALIDDATA; |
264 |
|
|
} |
265 |
|
1900 |
CHECK(init_get_bits(&payload_gbc, rw->buffer, |
266 |
|
|
get_bits_count(rw) + 8 * payload_size)); |
267 |
|
1900 |
skip_bits_long(&payload_gbc, get_bits_count(rw)); |
268 |
|
|
|
269 |
|
1900 |
CHECK(ff_cbs_sei_list_add(current)); |
270 |
|
1900 |
message = ¤t->messages[k]; |
271 |
|
|
|
272 |
|
1900 |
message->payload_type = payload_type; |
273 |
|
1900 |
message->payload_size = payload_size; |
274 |
|
|
|
275 |
|
1900 |
CHECK(FUNC(message)(ctx, &payload_gbc, message)); |
276 |
|
|
|
277 |
|
1900 |
skip_bits_long(rw, 8 * payload_size); |
278 |
|
|
|
279 |
|
1900 |
if (!cbs_h2645_read_more_rbsp_data(rw)) |
280 |
|
1880 |
break; |
281 |
|
|
} |
282 |
|
|
#else |
283 |
|
3778 |
for (k = 0; k < current->nb_messages; k++) { |
284 |
|
|
PutBitContext start_state; |
285 |
|
|
uint32_t tmp; |
286 |
|
|
int trace, i; |
287 |
|
|
|
288 |
|
1899 |
message = ¤t->messages[k]; |
289 |
|
|
|
290 |
|
|
// We write the payload twice in order to find the size. Trace |
291 |
|
|
// output is switched off for the first write. |
292 |
|
1899 |
trace = ctx->trace_enable; |
293 |
|
1899 |
ctx->trace_enable = 0; |
294 |
|
|
|
295 |
|
1899 |
start_state = *rw; |
296 |
|
5697 |
for (i = 0; i < 2; i++) { |
297 |
|
3798 |
*rw = start_state; |
298 |
|
|
|
299 |
|
3798 |
tmp = message->payload_type; |
300 |
|
3838 |
while (tmp >= 255) { |
301 |
|
40 |
fixed(8, ff_byte, 0xff); |
302 |
|
40 |
tmp -= 255; |
303 |
|
|
} |
304 |
|
3798 |
xu(8, last_payload_type_byte, tmp, 0, 254, 0); |
305 |
|
|
|
306 |
|
3798 |
tmp = message->payload_size; |
307 |
|
3808 |
while (tmp >= 255) { |
308 |
|
10 |
fixed(8, ff_byte, 0xff); |
309 |
|
10 |
tmp -= 255; |
310 |
|
|
} |
311 |
|
3798 |
xu(8, last_payload_size_byte, tmp, 0, 254, 0); |
312 |
|
|
|
313 |
|
3798 |
err = FUNC(message)(ctx, rw, message); |
314 |
|
3798 |
ctx->trace_enable = trace; |
315 |
|
3798 |
if (err < 0) |
316 |
|
|
return err; |
317 |
|
|
} |
318 |
|
|
} |
319 |
|
|
#endif |
320 |
|
|
|
321 |
|
3759 |
return 0; |
322 |
|
|
} |