/src/ffmpeg/libavcodec/cbs_mpeg2.c
Line | Count | Source (jump to first uncovered line) |
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 "libavutil/avassert.h" |
20 | | |
21 | | #include "cbs.h" |
22 | | #include "cbs_internal.h" |
23 | | #include "cbs_mpeg2.h" |
24 | | #include "startcode.h" |
25 | | |
26 | | |
27 | 1.12M | #define HEADER(name) do { \ |
28 | 1.12M | ff_cbs_trace_header(ctx, name); \ |
29 | 1.12M | } while (0) |
30 | | |
31 | 34.6M | #define CHECK(call) do { \ |
32 | 65.5M | err = (call); \ |
33 | 34.6M | if (err < 0) \ |
34 | 34.6M | return err; \ |
35 | 34.6M | } while (0) |
36 | | |
37 | 55.4k | #define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name |
38 | 55.4k | #define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name) |
39 | 55.4k | #define FUNC(name) FUNC_MPEG2(READWRITE, name) |
40 | | |
41 | | #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) |
42 | | |
43 | | #define uir(width, name) \ |
44 | 295k | xui(width, name, current->name, 1, MAX_UINT_BITS(width), 0, ) |
45 | | #define uis(width, name, subs, ...) \ |
46 | 811k | xui(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__) |
47 | | #define uirs(width, name, subs, ...) \ |
48 | 19.6k | xui(width, name, current->name, 1, MAX_UINT_BITS(width), subs, __VA_ARGS__) |
49 | | #define xui(width, name, var, range_min, range_max, subs, ...) \ |
50 | 9.98M | xuia(width, #name, var, range_min, range_max, subs, __VA_ARGS__) |
51 | | #define sis(width, name, subs, ...) \ |
52 | 8.37k | xsi(width, name, current->name, subs, __VA_ARGS__) |
53 | | |
54 | | #define marker_bit() \ |
55 | 35.5k | bit("marker_bit", 1) |
56 | 11.4M | #define bit(string, value) do { \ |
57 | 11.4M | av_unused uint32_t bit = value; \ |
58 | 11.4M | xuia(1, string, bit, value, value, 0, ); \ |
59 | 11.4M | } while (0) |
60 | | |
61 | | |
62 | | #define READ |
63 | | #define READWRITE read |
64 | | #define RWContext GetBitContext |
65 | | |
66 | 1.31M | #define ui(width, name) do { \ |
67 | 1.31M | uint32_t value; \ |
68 | 1.31M | CHECK(ff_cbs_read_simple_unsigned(ctx, rw, width, #name, \ |
69 | 1.31M | &value)); \ |
70 | 1.31M | current->name = value; \ |
71 | 1.28M | } while (0) |
72 | 17.3M | #define xuia(width, string, var, range_min, range_max, subs, ...) do { \ |
73 | 16.8M | uint32_t value; \ |
74 | 16.8M | CHECK(ff_cbs_read_unsigned(ctx, rw, width, string, \ |
75 | 16.8M | SUBSCRIPTS(subs, __VA_ARGS__), \ |
76 | 16.8M | &value, range_min, range_max)); \ |
77 | 16.8M | var = value; \ |
78 | 16.7M | } while (0) |
79 | | |
80 | 5.99k | #define xsi(width, name, var, subs, ...) do { \ |
81 | 5.99k | int32_t value; \ |
82 | 5.99k | CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \ |
83 | 5.99k | SUBSCRIPTS(subs, __VA_ARGS__), &value, \ |
84 | 5.99k | MIN_INT_BITS(width), \ |
85 | 5.99k | MAX_INT_BITS(width))); \ |
86 | 5.99k | var = value; \ |
87 | 5.31k | } while (0) |
88 | | |
89 | | #define nextbits(width, compare, var) \ |
90 | 5.88M | (get_bits_left(rw) >= width && \ |
91 | 5.88M | (var = show_bits(rw, width)) == (compare)) |
92 | | |
93 | 4.80k | #define infer(name, value) do { \ |
94 | 4.80k | current->name = value; \ |
95 | 4.80k | } while (0) |
96 | | |
97 | | #include "cbs_mpeg2_syntax_template.c" |
98 | | |
99 | | #undef READ |
100 | | #undef READWRITE |
101 | | #undef RWContext |
102 | | #undef ui |
103 | | #undef xuia |
104 | | #undef xsi |
105 | | #undef nextbits |
106 | | #undef infer |
107 | | |
108 | | |
109 | | #define WRITE |
110 | | #define READWRITE write |
111 | | #define RWContext PutBitContext |
112 | | |
113 | 483k | #define ui(width, name) do { \ |
114 | 483k | CHECK(ff_cbs_write_simple_unsigned(ctx, rw, width, #name, \ |
115 | 483k | current->name)); \ |
116 | 483k | } while (0) |
117 | | |
118 | 16.2M | #define xuia(width, string, var, range_min, range_max, subs, ...) do { \ |
119 | 15.8M | CHECK(ff_cbs_write_unsigned(ctx, rw, width, string, \ |
120 | 15.8M | SUBSCRIPTS(subs, __VA_ARGS__), \ |
121 | 15.8M | var, range_min, range_max)); \ |
122 | 15.8M | } while (0) |
123 | | |
124 | 2.38k | #define xsi(width, name, var, subs, ...) do { \ |
125 | 2.38k | CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \ |
126 | 2.38k | SUBSCRIPTS(subs, __VA_ARGS__), var, \ |
127 | 2.38k | MIN_INT_BITS(width), \ |
128 | 2.38k | MAX_INT_BITS(width))); \ |
129 | 2.38k | } while (0) |
130 | | |
131 | 3.75k | #define nextbits(width, compare, var) (var) |
132 | | |
133 | 1.02k | #define infer(name, value) do { \ |
134 | 1.02k | if (current->name != (value)) { \ |
135 | 0 | av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ |
136 | 0 | "%s does not match inferred value: " \ |
137 | 0 | "%"PRId64", but should be %"PRId64".\n", \ |
138 | 0 | #name, (int64_t)current->name, (int64_t)(value)); \ |
139 | 0 | } \ |
140 | 1.02k | } while (0) |
141 | | |
142 | | #include "cbs_mpeg2_syntax_template.c" |
143 | | |
144 | | #undef WRITE |
145 | | #undef READWRITE |
146 | | #undef RWContext |
147 | | #undef ui |
148 | | #undef xuia |
149 | | #undef xsi |
150 | | #undef nextbits |
151 | | #undef infer |
152 | | |
153 | | |
154 | | static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, |
155 | | CodedBitstreamFragment *frag, |
156 | | int header) |
157 | 344k | { |
158 | 344k | const uint8_t *start; |
159 | 344k | uint32_t start_code = -1; |
160 | 344k | int err; |
161 | | |
162 | 344k | start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, |
163 | 344k | &start_code); |
164 | 344k | if (start_code >> 8 != 0x000001) { |
165 | | // No start code found. |
166 | 169k | return AVERROR_INVALIDDATA; |
167 | 169k | } |
168 | | |
169 | 1.76M | do { |
170 | 1.76M | CodedBitstreamUnitType unit_type = start_code & 0xff; |
171 | 1.76M | const uint8_t *end; |
172 | 1.76M | size_t unit_size; |
173 | | |
174 | | // Reset start_code to ensure that avpriv_find_start_code() |
175 | | // really reads a new start code and does not reuse the old |
176 | | // start code in any way (as e.g. happens when there is a |
177 | | // Sequence End unit at the very end of a packet). |
178 | 1.76M | start_code = UINT32_MAX; |
179 | 1.76M | end = avpriv_find_start_code(start--, frag->data + frag->data_size, |
180 | 1.76M | &start_code); |
181 | | |
182 | | // start points to the byte containing the start_code_identifier |
183 | | // (may be the last byte of fragment->data); end points to the byte |
184 | | // following the byte containing the start code identifier (or to |
185 | | // the end of fragment->data). |
186 | 1.76M | if (start_code >> 8 == 0x000001) { |
187 | | // Unit runs from start to the beginning of the start code |
188 | | // pointed to by end (including any padding zeroes). |
189 | 1.58M | unit_size = (end - 4) - start; |
190 | 1.58M | } else { |
191 | | // We didn't find a start code, so this is the final unit. |
192 | 174k | unit_size = end - start; |
193 | 174k | } |
194 | | |
195 | 1.76M | err = ff_cbs_append_unit_data(frag, unit_type, (uint8_t*)start, |
196 | 1.76M | unit_size, frag->data_ref); |
197 | 1.76M | if (err < 0) |
198 | 0 | return err; |
199 | | |
200 | 1.76M | start = end; |
201 | | |
202 | | // Do we have a further unit to add to the fragment? |
203 | 1.76M | } while ((start_code >> 8) == 0x000001); |
204 | | |
205 | 174k | return 0; |
206 | 174k | } |
207 | | |
208 | | static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, |
209 | | CodedBitstreamUnit *unit) |
210 | 688k | { |
211 | 688k | GetBitContext gbc; |
212 | 688k | int err; |
213 | | |
214 | 688k | err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); |
215 | 688k | if (err < 0) |
216 | 0 | return err; |
217 | | |
218 | 688k | err = ff_cbs_alloc_unit_content(ctx, unit); |
219 | 688k | if (err < 0) |
220 | 17.5k | return err; |
221 | | |
222 | 670k | if (MPEG2_START_IS_SLICE(unit->type)) { |
223 | 131k | MPEG2RawSlice *slice = unit->content; |
224 | 131k | int pos, len; |
225 | | |
226 | 131k | err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header); |
227 | 131k | if (err < 0) |
228 | 50.5k | return err; |
229 | | |
230 | 80.7k | if (!get_bits_left(&gbc)) |
231 | 738 | return AVERROR_INVALIDDATA; |
232 | | |
233 | 79.9k | pos = get_bits_count(&gbc); |
234 | 79.9k | len = unit->data_size; |
235 | | |
236 | 79.9k | slice->data_size = len - pos / 8; |
237 | 79.9k | slice->data_ref = av_buffer_ref(unit->data_ref); |
238 | 79.9k | if (!slice->data_ref) |
239 | 0 | return AVERROR(ENOMEM); |
240 | 79.9k | slice->data = unit->data + pos / 8; |
241 | | |
242 | 79.9k | slice->data_bit_start = pos % 8; |
243 | | |
244 | 539k | } else { |
245 | 539k | switch (unit->type) { |
246 | 0 | #define START(start_code, type, read_func, free_func) \ |
247 | 468k | case start_code: \ |
248 | 468k | { \ |
249 | 468k | type *header = unit->content; \ |
250 | 468k | err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \ |
251 | 539k | if (err < 0) \ |
252 | 468k | return err; \ |
253 | 468k | } \ |
254 | 468k | break; |
255 | 35.7k | START(MPEG2_START_PICTURE, MPEG2RawPictureHeader, |
256 | 35.7k | picture_header, &cbs_mpeg2_free_picture_header); |
257 | 424k | START(MPEG2_START_USER_DATA, MPEG2RawUserData, |
258 | 424k | user_data, &cbs_mpeg2_free_user_data); |
259 | 27.3k | START(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader, |
260 | 27.3k | sequence_header, NULL); |
261 | 48.2k | START(MPEG2_START_EXTENSION, MPEG2RawExtensionData, |
262 | 48.2k | extension_data, NULL); |
263 | 2.63k | START(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader, |
264 | 2.63k | group_of_pictures_header, NULL); |
265 | 1.27k | START(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd, |
266 | 1.27k | sequence_end, NULL); |
267 | 0 | #undef START |
268 | 0 | default: |
269 | 0 | return AVERROR(ENOSYS); |
270 | 539k | } |
271 | 539k | } |
272 | | |
273 | 548k | return 0; |
274 | 670k | } |
275 | | |
276 | | static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx, |
277 | | CodedBitstreamUnit *unit, |
278 | | PutBitContext *pbc) |
279 | 399k | { |
280 | 399k | int err; |
281 | | |
282 | 399k | switch (unit->type) { |
283 | 0 | #define START(start_code, type, func) \ |
284 | 399k | case start_code: \ |
285 | 399k | err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \ |
286 | 399k | break; |
287 | 955 | START(MPEG2_START_PICTURE, MPEG2RawPictureHeader, picture_header); |
288 | 387k | START(MPEG2_START_USER_DATA, MPEG2RawUserData, user_data); |
289 | 2.18k | START(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader, sequence_header); |
290 | 8.26k | START(MPEG2_START_EXTENSION, MPEG2RawExtensionData, extension_data); |
291 | 272 | START(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader, |
292 | 0 | group_of_pictures_header); |
293 | 229 | START(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd, sequence_end); |
294 | 0 | #undef START |
295 | 0 | default: |
296 | 0 | av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start " |
297 | 0 | "code %02"PRIx32".\n", unit->type); |
298 | 0 | return AVERROR_PATCHWELCOME; |
299 | 399k | } |
300 | | |
301 | 399k | return err; |
302 | 399k | } |
303 | | |
304 | | static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, |
305 | | CodedBitstreamUnit *unit, |
306 | | PutBitContext *pbc) |
307 | 3.75k | { |
308 | 3.75k | MPEG2RawSlice *slice = unit->content; |
309 | 3.75k | int err; |
310 | | |
311 | 3.75k | err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header); |
312 | 3.75k | if (err < 0) |
313 | 0 | return err; |
314 | | |
315 | 3.75k | if (slice->data) { |
316 | 3.75k | size_t rest = slice->data_size - (slice->data_bit_start + 7) / 8; |
317 | 3.75k | uint8_t *pos = slice->data + slice->data_bit_start / 8; |
318 | | |
319 | 3.75k | av_assert0(slice->data_bit_start >= 0 && |
320 | 3.75k | slice->data_size > slice->data_bit_start / 8); |
321 | | |
322 | 3.75k | if (slice->data_size * 8 + 8 > put_bits_left(pbc)) |
323 | 0 | return AVERROR(ENOSPC); |
324 | | |
325 | | // First copy the remaining bits of the first byte |
326 | 3.75k | if (slice->data_bit_start % 8) |
327 | 3.34k | put_bits(pbc, 8 - slice->data_bit_start % 8, |
328 | 3.34k | *pos++ & MAX_UINT_BITS(8 - slice->data_bit_start % 8)); |
329 | | |
330 | 3.75k | if (put_bits_count(pbc) % 8 == 0) { |
331 | | // If the writer is aligned at this point, |
332 | | // memcpy can be used to improve performance. |
333 | | // This is the normal case. |
334 | 2.48k | flush_put_bits(pbc); |
335 | 2.48k | memcpy(put_bits_ptr(pbc), pos, rest); |
336 | 2.48k | skip_put_bytes(pbc, rest); |
337 | 2.48k | } else { |
338 | | // If not, we have to copy manually: |
339 | 807k | for (; rest > 3; rest -= 4, pos += 4) |
340 | 806k | put_bits32(pbc, AV_RB32(pos)); |
341 | | |
342 | 2.74k | for (; rest; rest--, pos++) |
343 | 1.48k | put_bits(pbc, 8, *pos); |
344 | | |
345 | | // Align with zeros |
346 | 1.26k | put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0); |
347 | 1.26k | } |
348 | 3.75k | } |
349 | | |
350 | 3.75k | return 0; |
351 | 3.75k | } |
352 | | |
353 | | static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, |
354 | | CodedBitstreamUnit *unit, |
355 | | PutBitContext *pbc) |
356 | 403k | { |
357 | 403k | if (MPEG2_START_IS_SLICE(unit->type)) |
358 | 3.75k | return cbs_mpeg2_write_slice (ctx, unit, pbc); |
359 | 399k | else |
360 | 399k | return cbs_mpeg2_write_header(ctx, unit, pbc); |
361 | 403k | } |
362 | | |
363 | | static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, |
364 | | CodedBitstreamFragment *frag) |
365 | 2.25k | { |
366 | 2.25k | uint8_t *data; |
367 | 2.25k | size_t size, dp; |
368 | 2.25k | int i; |
369 | | |
370 | 2.25k | size = 0; |
371 | 406k | for (i = 0; i < frag->nb_units; i++) |
372 | 404k | size += 3 + frag->units[i].data_size; |
373 | | |
374 | 2.25k | frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); |
375 | 2.25k | if (!frag->data_ref) |
376 | 0 | return AVERROR(ENOMEM); |
377 | 2.25k | data = frag->data_ref->data; |
378 | | |
379 | 2.25k | dp = 0; |
380 | 406k | for (i = 0; i < frag->nb_units; i++) { |
381 | 404k | CodedBitstreamUnit *unit = &frag->units[i]; |
382 | | |
383 | 404k | data[dp++] = 0; |
384 | 404k | data[dp++] = 0; |
385 | 404k | data[dp++] = 1; |
386 | | |
387 | 404k | memcpy(data + dp, unit->data, unit->data_size); |
388 | 404k | dp += unit->data_size; |
389 | 404k | } |
390 | | |
391 | 2.25k | av_assert0(dp == size); |
392 | | |
393 | 2.25k | memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); |
394 | 2.25k | frag->data = data; |
395 | 2.25k | frag->data_size = size; |
396 | | |
397 | 2.25k | return 0; |
398 | 2.25k | } |
399 | | |
400 | | static const CodedBitstreamUnitTypeDescriptor cbs_mpeg2_unit_types[] = { |
401 | | CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_PICTURE, MPEG2RawPictureHeader, |
402 | | extra_information_picture.extra_information), |
403 | | |
404 | | { |
405 | | .nb_unit_types = CBS_UNIT_TYPE_RANGE, |
406 | | .unit_type.range.start = 0x01, |
407 | | .unit_type.range.end = 0xaf, |
408 | | |
409 | | .content_type = CBS_CONTENT_TYPE_INTERNAL_REFS, |
410 | | .content_size = sizeof(MPEG2RawSlice), |
411 | | .type.ref = { .nb_offsets = 2, |
412 | | .offsets = { offsetof(MPEG2RawSlice, header.extra_information_slice.extra_information), |
413 | | offsetof(MPEG2RawSlice, data) } }, |
414 | | }, |
415 | | |
416 | | CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_USER_DATA, MPEG2RawUserData, |
417 | | user_data), |
418 | | |
419 | | CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader), |
420 | | CBS_UNIT_TYPE_POD(MPEG2_START_EXTENSION, MPEG2RawExtensionData), |
421 | | CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd), |
422 | | CBS_UNIT_TYPE_POD(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader), |
423 | | |
424 | | CBS_UNIT_TYPE_END_OF_LIST |
425 | | }; |
426 | | |
427 | | const CodedBitstreamType ff_cbs_type_mpeg2 = { |
428 | | .codec_id = AV_CODEC_ID_MPEG2VIDEO, |
429 | | |
430 | | .priv_data_size = sizeof(CodedBitstreamMPEG2Context), |
431 | | |
432 | | .unit_types = cbs_mpeg2_unit_types, |
433 | | |
434 | | .split_fragment = &cbs_mpeg2_split_fragment, |
435 | | .read_unit = &cbs_mpeg2_read_unit, |
436 | | .write_unit = &cbs_mpeg2_write_unit, |
437 | | .assemble_fragment = &cbs_mpeg2_assemble_fragment, |
438 | | }; |