1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
|
/*
* MXF SMPTE-436M VBI/ANC parsing functions
* Copyright (c) 2025 Jacob Lifshay
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavcodec/smpte_436m.h"
#include "bytestream.h"
#include "libavcodec/packet.h"
#include "libavutil/avassert.h"
#include "libavutil/error.h"
#include "libavutil/intreadwrite.h"
static int validate_smpte_436m_anc_wrapping_type(AVSmpte436mWrappingType wrapping_type)
{
switch (wrapping_type) {
case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME:
case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1:
case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2:
case AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME:
case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FRAME:
case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_1:
case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_2:
case AV_SMPTE_436M_WRAPPING_TYPE_HANC_PROGRESSIVE_FRAME:
return 0;
default:
return AVERROR_INVALIDDATA;
}
}
static int validate_smpte_436m_anc_payload_sample_coding(AVSmpte436mPayloadSampleCoding payload_sample_coding)
{
switch (payload_sample_coding) {
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
// not allowed for ANC packets
return AVERROR_INVALIDDATA;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
return 0;
default:
return AVERROR_INVALIDDATA;
}
}
int av_smpte_436m_coded_anc_validate(const AVSmpte436mCodedAnc *anc)
{
int ret = validate_smpte_436m_anc_wrapping_type(anc->wrapping_type);
if (ret < 0)
return ret;
ret = validate_smpte_436m_anc_payload_sample_coding(anc->payload_sample_coding);
if (ret < 0)
return ret;
if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
return AVERROR_INVALIDDATA;
ret = av_smpte_436m_coded_anc_payload_size(anc->payload_sample_coding, anc->payload_sample_count);
if (ret < 0)
return ret;
if (anc->payload_array_length < ret)
return AVERROR_INVALIDDATA;
return 0;
}
// Based off Table 7 (page 13) of:
// https://pub.smpte.org/latest/st436/s436m-2006.pdf
#define SMPTE_436M_ANC_ENTRY_HEADER_SIZE ( \
2 /* line_number */ \
+ 1 /* wrapping_type */ \
+ 1 /* payload_sample_coding */ \
+ 2 /* payload_sample_count */ \
+ 4 /* payload_array_length */ \
+ 4 /* payload_array_element_size */ \
)
/**
* Decode an ANC packet.
* @param[in] in Input bytes.
* @param[in] size the size of in.
* @param[out] anc the decoded ANC packet
* @return The number of read bytes on success, AVERROR_INVALIDDATA otherwise.
*/
static int smpte_436m_anc_decode_entry(const uint8_t *in, int size, AVSmpte436mCodedAnc *anc)
{
// Based off Table 7 (page 13) of:
// https://pub.smpte.org/latest/st436/s436m-2006.pdf
if (SMPTE_436M_ANC_ENTRY_HEADER_SIZE > size)
return AVERROR_INVALIDDATA;
int needed_size = SMPTE_436M_ANC_ENTRY_HEADER_SIZE;
anc->line_number = AV_RB16(in);
in += 2;
anc->wrapping_type = AV_RB8(in);
in++;
anc->payload_sample_coding = AV_RB8(in);
in++;
anc->payload_sample_count = AV_RB16(in);
in += 2;
anc->payload_array_length = AV_RB32(in);
in += 4;
uint32_t payload_array_element_size = AV_RB32(in);
in += 4;
if (payload_array_element_size != 1)
return AVERROR_INVALIDDATA;
needed_size += anc->payload_array_length;
if (needed_size > size)
return AVERROR_INVALIDDATA;
if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
return AVERROR_INVALIDDATA;
memcpy(anc->payload, in, anc->payload_array_length);
int ret = av_smpte_436m_coded_anc_validate(anc);
if (ret < 0)
return ret;
return needed_size;
}
/**
* Encode an ANC packet.
* @param[in] anc the ANC packet to encode
* @param[in] size the size of out. ignored if out is NULL.
* @param[out] out Output bytes. Doesn't write anything if out is NULL.
* @return the number of bytes written on success, AVERROR codes otherwise.
* If out is NULL, returns the number of bytes it would have written.
*/
static int smpte_436m_anc_encode_entry(uint8_t *out, int size, const AVSmpte436mCodedAnc *anc)
{
// Based off Table 7 (page 13) of:
// https://pub.smpte.org/latest/st436/s436m-2006.pdf
if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
return AVERROR_INVALIDDATA;
int needed_size = SMPTE_436M_ANC_ENTRY_HEADER_SIZE + (int)anc->payload_array_length;
if (!out)
return needed_size;
if (needed_size > size)
return AVERROR_BUFFER_TOO_SMALL;
AV_WB16(out, anc->line_number);
out += 2;
AV_WB8(out, anc->wrapping_type);
out++;
AV_WB8(out, anc->payload_sample_coding);
out++;
AV_WB16(out, anc->payload_sample_count);
out += 2;
AV_WB32(out, anc->payload_array_length);
out += 4;
AV_WB32(out, 1); // payload_array_element_size
out += 4;
memcpy(out, anc->payload, anc->payload_array_length);
return needed_size;
}
int av_smpte_436m_anc_encode(uint8_t *out, int size, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
{
// Based off Table 7 (page 13) of:
// https://pub.smpte.org/latest/st436/s436m-2006.pdf
if (anc_packet_count < 0 || anc_packet_count >= (1L << 16) || size < 0)
return AVERROR_INVALIDDATA;
int needed_size = 2;
if (out) {
if (size < needed_size)
return AVERROR_BUFFER_TOO_SMALL;
AV_WB16(out, anc_packet_count);
out += 2;
size -= 2;
}
for (int i = 0; i < anc_packet_count; i++) {
int ret = smpte_436m_anc_encode_entry(out, size, &anc_packets[i]);
if (ret < 0)
return ret;
needed_size += ret;
if (out) {
size -= ret;
out += ret;
}
}
return needed_size;
}
int av_smpte_436m_anc_append(AVPacket *pkt, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
{
int final_packet_count = 0;
int write_start = 2;
if (pkt->size >= 2) {
final_packet_count = AV_RB16(pkt->data);
write_start = pkt->size;
} else if (pkt->size != 0) // if packet isn't empty
return AVERROR_INVALIDDATA;
if (anc_packet_count < 0 || anc_packet_count >= (1L << 16))
return AVERROR_INVALIDDATA;
final_packet_count += anc_packet_count;
if (final_packet_count >= (1L << 16))
return AVERROR_INVALIDDATA;
int ret, additional_size = write_start - pkt->size;
for (int i = 0; i < anc_packet_count; i++) {
ret = smpte_436m_anc_encode_entry(NULL, 0, &anc_packets[i]);
if (ret < 0)
return ret;
additional_size += ret;
}
ret = av_grow_packet(pkt, additional_size);
if (ret < 0)
return ret;
for (int i = 0; i < anc_packet_count; i++) {
ret = smpte_436m_anc_encode_entry(pkt->data + write_start, pkt->size - write_start, &anc_packets[i]);
av_assert0(ret >= 0);
write_start += ret;
}
AV_WB16(pkt->data, final_packet_count);
return 0;
}
int av_smpte_436m_anc_iter_init(AVSmpte436mAncIterator *iter, const uint8_t *buf, int buf_size)
{
// Based off Table 7 (page 13) of:
// https://pub.smpte.org/latest/st436/s436m-2006.pdf
if (buf_size < 2)
return AVERROR_INVALIDDATA;
*iter = (AVSmpte436mAncIterator){
.anc_packets_left = AV_RB16(buf),
.size_left = buf_size - 2,
.data_left = buf + 2,
};
if (iter->anc_packets_left > iter->size_left)
return AVERROR_INVALIDDATA;
return 0;
}
int av_smpte_436m_anc_iter_next(AVSmpte436mAncIterator *iter, AVSmpte436mCodedAnc *anc)
{
if (iter->anc_packets_left <= 0)
return AVERROR_EOF;
iter->anc_packets_left--;
int ret = smpte_436m_anc_decode_entry(iter->data_left, iter->size_left, anc);
if (ret < 0) {
iter->anc_packets_left = 0;
return ret;
}
iter->data_left += ret;
iter->size_left -= ret;
return 0;
}
int av_smpte_436m_coded_anc_payload_size(AVSmpte436mPayloadSampleCoding sample_coding, uint16_t sample_count)
{
if (sample_count > AV_SMPTE_436M_CODED_ANC_SAMPLE_CAPACITY)
return AVERROR_INVALIDDATA;
switch (sample_coding) {
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
return AVERROR_INVALIDDATA;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
// "The Payload Byte Array shall be padded to achieve UInt32 alignment."
// section 4.4 of https://pub.smpte.org/latest/st436/s436m-2006.pdf
return (sample_count + 3) & -4;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
// encoded with 3 10-bit samples in a UInt32.
// "The Payload Byte Array shall be padded to achieve UInt32 alignment."
// section 4.4 of https://pub.smpte.org/latest/st436/s436m-2006.pdf
return 4 * ((sample_count + 2) / 3);
default:
return AVERROR_INVALIDDATA;
}
}
int av_smpte_291m_anc_8bit_decode(AVSmpte291mAnc8bit *out,
AVSmpte436mPayloadSampleCoding sample_coding,
uint16_t sample_count,
const uint8_t *payload,
void *log_ctx)
{
switch (sample_coding) {
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
return AVERROR_INVALIDDATA;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
{
if (sample_count < 3)
return AVERROR_INVALIDDATA;
out->did = *payload++;
out->sdid_or_dbn = *payload++;
out->data_count = *payload++;
if (sample_count < out->data_count + 3)
return AVERROR_INVALIDDATA;
memcpy(out->payload, payload, out->data_count);
// the checksum isn't stored in 8-bit mode, so calculate it.
av_smpte_291m_anc_8bit_fill_checksum(out);
return 0;
}
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
av_log(log_ctx,
AV_LOG_ERROR,
"decoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
return AVERROR_PATCHWELCOME;
default:
return AVERROR_INVALIDDATA;
}
}
void av_smpte_291m_anc_8bit_fill_checksum(AVSmpte291mAnc8bit *anc)
{
uint8_t checksum = anc->did + anc->sdid_or_dbn + anc->data_count;
for (unsigned i = 0; i < anc->data_count; i++) {
checksum += anc->payload[i];
}
anc->checksum = checksum;
}
int av_smpte_291m_anc_8bit_get_sample_count(const AVSmpte291mAnc8bit *anc,
AVSmpte436mPayloadSampleCoding sample_coding,
void *log_ctx)
{
switch (sample_coding) {
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
return AVERROR_INVALIDDATA;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
// 3 for did, sdid_or_dbn, and data_count; checksum isn't stored in 8-bit modes
return 3 + anc->data_count;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
av_log(log_ctx,
AV_LOG_ERROR,
"encoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
return AVERROR_PATCHWELCOME;
default:
return AVERROR_INVALIDDATA;
}
}
int av_smpte_291m_anc_8bit_encode(AVSmpte436mCodedAnc *out,
uint16_t line_number,
AVSmpte436mWrappingType wrapping_type,
AVSmpte436mPayloadSampleCoding sample_coding,
const AVSmpte291mAnc8bit *payload,
void *log_ctx)
{
out->line_number = line_number;
out->wrapping_type = wrapping_type;
out->payload_sample_coding = sample_coding;
int ret = av_smpte_291m_anc_8bit_get_sample_count(payload, sample_coding, log_ctx);
if (ret < 0)
return ret;
out->payload_sample_count = ret;
ret = av_smpte_436m_coded_anc_payload_size(sample_coding, out->payload_sample_count);
if (ret < 0)
return ret;
out->payload_array_length = ret;
switch (sample_coding) {
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
return AVERROR_INVALIDDATA;
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
{
// fill trailing padding with zeros
av_assert0(out->payload_array_length >= 4);
memset(out->payload + out->payload_array_length - 4, 0, 4);
out->payload[0] = payload->did;
out->payload[1] = payload->sdid_or_dbn;
out->payload[2] = payload->data_count;
memcpy(out->payload + 3, payload->payload, payload->data_count);
return 0;
}
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
av_log(log_ctx,
AV_LOG_ERROR,
"encoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
return AVERROR_PATCHWELCOME;
default:
return AVERROR_INVALIDDATA;
}
}
int av_smpte_291m_anc_8bit_extract_cta_708(const AVSmpte291mAnc8bit *anc, uint8_t *cc_data, void *log_ctx)
{
if (anc->did != AV_SMPTE_291M_ANC_DID_CTA_708 || anc->sdid_or_dbn != AV_SMPTE_291M_ANC_SDID_CTA_708)
return AVERROR(EAGAIN);
GetByteContext gb;
bytestream2_init(&gb, anc->payload, anc->data_count);
// based on Caption Distribution Packet (CDP) Definition:
// https://pub.smpte.org/latest/st334-2/st0334-2-2015.pdf
uint16_t cdp_identifier = bytestream2_get_be16(&gb);
if (cdp_identifier != 0x9669) { // CDPs always have this value
av_log(log_ctx, AV_LOG_ERROR, "wrong cdp identifier %x\n", cdp_identifier);
return AVERROR_INVALIDDATA;
}
bytestream2_get_byte(&gb); // cdp_length
bytestream2_get_byte(&gb); // cdp_frame_rate and reserved
bytestream2_get_byte(&gb); // flags
bytestream2_get_be16(&gb); // cdp_hdr_sequence_cntr
unsigned section_id = bytestream2_get_byte(&gb);
const unsigned TIME_CODE_SECTION_ID = 0x71;
if (section_id == TIME_CODE_SECTION_ID) {
bytestream2_skip(&gb, 4); // skip time code section
section_id = bytestream2_get_byte(&gb);
}
const unsigned CC_DATA_SECTION_ID = 0x72;
if (section_id == CC_DATA_SECTION_ID) {
if (bytestream2_get_bytes_left(&gb) < 1)
goto too_short;
// 0x1F for lower 5 bits, upper 3 bits are marker bits
unsigned cc_count = bytestream2_get_byte(&gb) & 0x1F;
unsigned data_length = cc_count * 3; // EIA-608/CTA-708 triples are 3 bytes long
if (bytestream2_get_bytes_left(&gb) < data_length)
goto too_short;
if (cc_data)
bytestream2_get_bufferu(&gb, cc_data, data_length);
return cc_count;
}
return AVERROR(EAGAIN);
too_short:
av_log(log_ctx, AV_LOG_ERROR, "not enough bytes in cdp\n");
return AVERROR_INVALIDDATA;
}
|