FFmpeg
Loading...
Searching...
No Matches
smpte_436m.c
Go to the documentation of this file.
1/*
2 * MXF SMPTE-436M VBI/ANC parsing functions
3 * Copyright (c) 2025 Jacob Lifshay
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
23#include "bytestream.h"
24#include "libavcodec/packet.h"
25#include "libavutil/avassert.h"
26#include "libavutil/error.h"
28
45
68
70{
72 if (ret < 0)
73 return ret;
75 if (ret < 0)
76 return ret;
80 if (ret < 0)
81 return ret;
82 if (anc->payload_array_length < ret)
84 return 0;
85}
86
87// Based off Table 7 (page 13) of:
88// https://pub.smpte.org/latest/st436/s436m-2006.pdf
89#define SMPTE_436M_ANC_ENTRY_HEADER_SIZE ( \
90 2 /* line_number */ \
91 + 1 /* wrapping_type */ \
92 + 1 /* payload_sample_coding */ \
93 + 2 /* payload_sample_count */ \
94 + 4 /* payload_array_length */ \
95 + 4 /* payload_array_element_size */ \
96)
97
98/**
99 * Decode an ANC packet.
100 * @param[in] in Input bytes.
101 * @param[in] size the size of in.
102 * @param[out] anc the decoded ANC packet
103 * @return The number of read bytes on success, AVERROR_INVALIDDATA otherwise.
104 */
105static int smpte_436m_anc_decode_entry(const uint8_t *in, int size, AVSmpte436mCodedAnc *anc)
106{
107 // Based off Table 7 (page 13) of:
108 // https://pub.smpte.org/latest/st436/s436m-2006.pdf
110 return AVERROR_INVALIDDATA;
111 int needed_size = SMPTE_436M_ANC_ENTRY_HEADER_SIZE;
112 anc->line_number = AV_RB16(in);
113 in += 2;
114 anc->wrapping_type = AV_RB8(in);
115 in++;
116 anc->payload_sample_coding = AV_RB8(in);
117 in++;
118 anc->payload_sample_count = AV_RB16(in);
119 in += 2;
120 anc->payload_array_length = AV_RB32(in);
121 in += 4;
122 uint32_t payload_array_element_size = AV_RB32(in);
123 in += 4;
124 if (payload_array_element_size != 1)
125 return AVERROR_INVALIDDATA;
126 needed_size += anc->payload_array_length;
127 if (needed_size > size)
128 return AVERROR_INVALIDDATA;
130 return AVERROR_INVALIDDATA;
131 memcpy(anc->payload, in, anc->payload_array_length);
133 if (ret < 0)
134 return ret;
135 return needed_size;
136}
137
138/**
139 * Encode an ANC packet.
140 * @param[in] anc the ANC packet to encode
141 * @param[in] size the size of out. ignored if out is NULL.
142 * @param[out] out Output bytes. Doesn't write anything if out is NULL.
143 * @return the number of bytes written on success, AVERROR codes otherwise.
144 * If out is NULL, returns the number of bytes it would have written.
145 */
146static int smpte_436m_anc_encode_entry(uint8_t *out, int size, const AVSmpte436mCodedAnc *anc)
147{
148 // Based off Table 7 (page 13) of:
149 // https://pub.smpte.org/latest/st436/s436m-2006.pdf
151 return AVERROR_INVALIDDATA;
152 int needed_size = SMPTE_436M_ANC_ENTRY_HEADER_SIZE + (int)anc->payload_array_length;
153 if (!out)
154 return needed_size;
155 if (needed_size > size)
157 AV_WB16(out, anc->line_number);
158 out += 2;
159 AV_WB8(out, anc->wrapping_type);
160 out++;
162 out++;
164 out += 2;
166 out += 4;
167 AV_WB32(out, 1); // payload_array_element_size
168 out += 4;
169 memcpy(out, anc->payload, anc->payload_array_length);
170 return needed_size;
171}
172
173int av_smpte_436m_anc_encode(uint8_t *out, int size, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
174{
175 // Based off Table 7 (page 13) of:
176 // https://pub.smpte.org/latest/st436/s436m-2006.pdf
177 if (anc_packet_count < 0 || anc_packet_count >= (1L << 16) || size < 0)
178 return AVERROR_INVALIDDATA;
179
180 int needed_size = 2;
181 if (out) {
182 if (size < needed_size)
184 AV_WB16(out, anc_packet_count);
185 out += 2;
186 size -= 2;
187 }
188 for (int i = 0; i < anc_packet_count; i++) {
189 int ret = smpte_436m_anc_encode_entry(out, size, &anc_packets[i]);
190 if (ret < 0)
191 return ret;
192 needed_size += ret;
193 if (out) {
194 size -= ret;
195 out += ret;
196 }
197 }
198 return needed_size;
199}
200
201int av_smpte_436m_anc_append(AVPacket *pkt, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
202{
203 int final_packet_count = 0;
204 int write_start = 2;
205 if (pkt->size >= 2) {
206 final_packet_count = AV_RB16(pkt->data);
207 write_start = pkt->size;
208 } else if (pkt->size != 0) // if packet isn't empty
209 return AVERROR_INVALIDDATA;
210 if (anc_packet_count < 0 || anc_packet_count >= (1L << 16))
211 return AVERROR_INVALIDDATA;
212 final_packet_count += anc_packet_count;
213 if (final_packet_count >= (1L << 16))
214 return AVERROR_INVALIDDATA;
215 int ret, additional_size = write_start - pkt->size;
216 for (int i = 0; i < anc_packet_count; i++) {
217 ret = smpte_436m_anc_encode_entry(NULL, 0, &anc_packets[i]);
218 if (ret < 0)
219 return ret;
220 additional_size += ret;
221 }
222 ret = av_grow_packet(pkt, additional_size);
223 if (ret < 0)
224 return ret;
225 for (int i = 0; i < anc_packet_count; i++) {
226 ret = smpte_436m_anc_encode_entry(pkt->data + write_start, pkt->size - write_start, &anc_packets[i]);
227 av_assert0(ret >= 0);
228 write_start += ret;
229 }
230 AV_WB16(pkt->data, final_packet_count);
231 return 0;
232}
233
234int av_smpte_436m_anc_iter_init(AVSmpte436mAncIterator *iter, const uint8_t *buf, int buf_size)
235{
236 // Based off Table 7 (page 13) of:
237 // https://pub.smpte.org/latest/st436/s436m-2006.pdf
238 if (buf_size < 2)
239 return AVERROR_INVALIDDATA;
240 *iter = (AVSmpte436mAncIterator){
241 .anc_packets_left = AV_RB16(buf),
242 .size_left = buf_size - 2,
243 .data_left = buf + 2,
244 };
245 if (iter->anc_packets_left > iter->size_left)
246 return AVERROR_INVALIDDATA;
247 return 0;
248}
249
251{
252 if (iter->anc_packets_left <= 0)
253 return AVERROR_EOF;
254 iter->anc_packets_left--;
255 int ret = smpte_436m_anc_decode_entry(iter->data_left, iter->size_left, anc);
256 if (ret < 0) {
257 iter->anc_packets_left = 0;
258 return ret;
259 }
260 iter->data_left += ret;
261 iter->size_left -= ret;
262 return 0;
263}
264
266{
268 return AVERROR_INVALIDDATA;
269 switch (sample_coding) {
273 return AVERROR_INVALIDDATA;
280 // "The Payload Byte Array shall be padded to achieve UInt32 alignment."
281 // section 4.4 of https://pub.smpte.org/latest/st436/s436m-2006.pdf
282 return (sample_count + 3) & -4;
286 // encoded with 3 10-bit samples in a UInt32.
287 // "The Payload Byte Array shall be padded to achieve UInt32 alignment."
288 // section 4.4 of https://pub.smpte.org/latest/st436/s436m-2006.pdf
289 return 4 * ((sample_count + 2) / 3);
290 default:
291 return AVERROR_INVALIDDATA;
292 }
293}
294
296 AVSmpte436mPayloadSampleCoding sample_coding,
297 uint16_t sample_count,
298 const uint8_t *payload,
299 void *log_ctx)
300{
301 switch (sample_coding) {
305 return AVERROR_INVALIDDATA;
312 {
313 if (sample_count < 3)
314 return AVERROR_INVALIDDATA;
315 out->did = *payload++;
316 out->sdid_or_dbn = *payload++;
317 out->data_count = *payload++;
318 if (sample_count < out->data_count + 3)
319 return AVERROR_INVALIDDATA;
320 memcpy(out->payload, payload, out->data_count);
321 // the checksum isn't stored in 8-bit mode, so calculate it.
323 return 0;
324 }
328 av_log(log_ctx,
330 "decoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
332 default:
333 return AVERROR_INVALIDDATA;
334 }
335}
336
338{
339 uint8_t checksum = anc->did + anc->sdid_or_dbn + anc->data_count;
340 for (unsigned i = 0; i < anc->data_count; i++) {
341 checksum += anc->payload[i];
342 }
343 anc->checksum = checksum;
344}
345
374
376 uint16_t line_number,
377 AVSmpte436mWrappingType wrapping_type,
378 AVSmpte436mPayloadSampleCoding sample_coding,
379 const AVSmpte291mAnc8bit *payload,
380 void *log_ctx)
381{
382 out->line_number = line_number;
383 out->wrapping_type = wrapping_type;
384 out->payload_sample_coding = sample_coding;
385
386 int ret = av_smpte_291m_anc_8bit_get_sample_count(payload, sample_coding, log_ctx);
387 if (ret < 0)
388 return ret;
389
390 out->payload_sample_count = ret;
391
392 ret = av_smpte_436m_coded_anc_payload_size(sample_coding, out->payload_sample_count);
393 if (ret < 0)
394 return ret;
395
396 out->payload_array_length = ret;
397
398 switch (sample_coding) {
402 return AVERROR_INVALIDDATA;
409 {
410 // fill trailing padding with zeros
411 av_assert0(out->payload_array_length >= 4);
412 memset(out->payload + out->payload_array_length - 4, 0, 4);
413
414 out->payload[0] = payload->did;
415 out->payload[1] = payload->sdid_or_dbn;
416 out->payload[2] = payload->data_count;
417
418 memcpy(out->payload + 3, payload->payload, payload->data_count);
419 return 0;
420 }
424 av_log(log_ctx,
426 "encoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
428 default:
429 return AVERROR_INVALIDDATA;
430 }
431}
432
433int av_smpte_291m_anc_8bit_extract_cta_708(const AVSmpte291mAnc8bit *anc, uint8_t *cc_data, void *log_ctx)
434{
436 return AVERROR(EAGAIN);
438 bytestream2_init(&gb, anc->payload, anc->data_count);
439 // based on Caption Distribution Packet (CDP) Definition:
440 // https://pub.smpte.org/latest/st334-2/st0334-2-2015.pdf
441 uint16_t cdp_identifier = bytestream2_get_be16(&gb);
442 if (cdp_identifier != 0x9669) { // CDPs always have this value
443 av_log(log_ctx, AV_LOG_ERROR, "wrong cdp identifier %x\n", cdp_identifier);
444 return AVERROR_INVALIDDATA;
445 }
446 bytestream2_get_byte(&gb); // cdp_length
447 bytestream2_get_byte(&gb); // cdp_frame_rate and reserved
448 bytestream2_get_byte(&gb); // flags
449 bytestream2_get_be16(&gb); // cdp_hdr_sequence_cntr
450 unsigned section_id = bytestream2_get_byte(&gb);
451
452 const unsigned TIME_CODE_SECTION_ID = 0x71;
453 if (section_id == TIME_CODE_SECTION_ID) {
454 bytestream2_skip(&gb, 4); // skip time code section
455 section_id = bytestream2_get_byte(&gb);
456 }
457 const unsigned CC_DATA_SECTION_ID = 0x72;
458 if (section_id == CC_DATA_SECTION_ID) {
459 if (bytestream2_get_bytes_left(&gb) < 1)
460 goto too_short;
461 // 0x1F for lower 5 bits, upper 3 bits are marker bits
462 unsigned cc_count = bytestream2_get_byte(&gb) & 0x1F;
463 unsigned data_length = cc_count * 3; // EIA-608/CTA-708 triples are 3 bytes long
464 if (bytestream2_get_bytes_left(&gb) < data_length)
465 goto too_short;
466 if (cc_data)
467 bytestream2_get_bufferu(&gb, cc_data, data_length);
468 return cc_count;
469 }
470 return AVERROR(EAGAIN);
471
472too_short:
473 av_log(log_ctx, AV_LOG_ERROR, "not enough bytes in cdp\n");
474 return AVERROR_INVALIDDATA;
475}
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition bytestream.h:277
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition bytestream.h:168
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
static AVPacket * pkt
error code definitions
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition packet.c:121
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition error.h:53
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
#define AV_WB32(p, v)
#define AV_RB8(x)
#define AV_RB32(p)
#define AV_WB8(p, d)
#define AV_WB16(p, v)
#define AV_RB16(p)
int av_smpte_436m_anc_iter_next(AVSmpte436mAncIterator *iter, AVSmpte436mCodedAnc *anc)
Get the next ANC packet from the iterator, advancing the iterator.
Definition smpte_436m.c:250
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)
Encode a AVSmpte291mAnc8bit into a AVSmpte436mCodedAnc.
Definition smpte_436m.c:375
int av_smpte_436m_anc_iter_init(AVSmpte436mAncIterator *iter, const uint8_t *buf, int buf_size)
Set up iteration over the ANC packets in a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
Definition smpte_436m.c:234
static int validate_smpte_436m_anc_payload_sample_coding(AVSmpte436mPayloadSampleCoding payload_sample_coding)
Definition smpte_436m.c:46
#define SMPTE_436M_ANC_ENTRY_HEADER_SIZE
Definition smpte_436m.c:89
static int smpte_436m_anc_encode_entry(uint8_t *out, int size, const AVSmpte436mCodedAnc *anc)
Encode an ANC packet.
Definition smpte_436m.c:146
int av_smpte_436m_anc_encode(uint8_t *out, int size, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
Encode ANC packets into a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
Definition smpte_436m.c:173
int av_smpte_291m_anc_8bit_get_sample_count(const AVSmpte291mAnc8bit *anc, AVSmpte436mPayloadSampleCoding sample_coding, void *log_ctx)
Compute the sample count needed to encode a AVSmpte291mAnc8bit into a AVSmpte436mCodedAnc payload.
Definition smpte_436m.c:346
static int smpte_436m_anc_decode_entry(const uint8_t *in, int size, AVSmpte436mCodedAnc *anc)
Decode an ANC packet.
Definition smpte_436m.c:105
int av_smpte_436m_coded_anc_validate(const AVSmpte436mCodedAnc *anc)
Validate a AVSmpte436mCodedAnc structure.
Definition smpte_436m.c:69
int av_smpte_291m_anc_8bit_decode(AVSmpte291mAnc8bit *out, AVSmpte436mPayloadSampleCoding sample_coding, uint16_t sample_count, const uint8_t *payload, void *log_ctx)
Decode a AVSmpte436mCodedAnc payload into AVSmpte291mAnc8bit.
Definition smpte_436m.c:295
int av_smpte_436m_coded_anc_payload_size(AVSmpte436mPayloadSampleCoding sample_coding, uint16_t sample_count)
Get the minimum number of bytes needed to store a AVSmpte436mCodedAnc payload.
Definition smpte_436m.c:265
static int validate_smpte_436m_anc_wrapping_type(AVSmpte436mWrappingType wrapping_type)
Definition smpte_436m.c:29
int av_smpte_291m_anc_8bit_extract_cta_708(const AVSmpte291mAnc8bit *anc, uint8_t *cc_data, void *log_ctx)
Try to decode an ANC packet into EIA-608/CTA-708 data (AV_CODEC_ID_EIA_608).
Definition smpte_436m.c:433
void av_smpte_291m_anc_8bit_fill_checksum(AVSmpte291mAnc8bit *anc)
Fill in the correct checksum for a AVSmpte291mAnc8bit.
Definition smpte_436m.c:337
int av_smpte_436m_anc_append(AVPacket *pkt, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets)
Append more ANC packets to a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
Definition smpte_436m.c:201
AVSmpte436mPayloadSampleCoding
Payload Sample Coding from Table 4 (page 10) and Table 7 (page 13) of: https://pub....
Definition smpte_436m.h:59
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF
used for VBI and ANC
Definition smpte_436m.h:77
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA
only used for VBI
Definition smpte_436m.h:61
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF
used for VBI and ANC
Definition smpte_436m.h:71
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF
used for VBI and ANC
Definition smpte_436m.h:69
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF
only used for VBI
Definition smpte_436m.h:65
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF
only used for VBI
Definition smpte_436m.h:63
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA
used for VBI and ANC
Definition smpte_436m.h:67
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR
only used for ANC
Definition smpte_436m.h:79
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR
only used for ANC
Definition smpte_436m.h:83
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR
only used for ANC
Definition smpte_436m.h:81
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA
used for VBI and ANC
Definition smpte_436m.h:73
@ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF
used for VBI and ANC
Definition smpte_436m.h:75
#define AV_SMPTE_291M_ANC_SDID_CTA_708
AVSmpte291mAnc8bit::sdid_or_dbn when carrying CTA-708 data (for AV_CODEC_ID_EIA_608)
Definition smpte_436m.h:240
#define AV_SMPTE_436M_CODED_ANC_SAMPLE_CAPACITY
max number of samples that can be stored in the payload of AVSmpte436mCodedAnc
Definition smpte_436m.h:107
AVSmpte436mWrappingType
Wrapping Type from Table 7 (page 13) of: https://pub.smpte.org/latest/st436/s436m-2006....
Definition smpte_436m.h:41
@ AV_SMPTE_436M_WRAPPING_TYPE_HANC_PROGRESSIVE_FRAME
Definition smpte_436m.h:49
@ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2
Definition smpte_436m.h:44
@ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_1
Definition smpte_436m.h:47
@ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FRAME
Definition smpte_436m.h:46
@ AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME
Definition smpte_436m.h:45
@ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME
Definition smpte_436m.h:42
@ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1
Definition smpte_436m.h:43
@ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_2
Definition smpte_436m.h:48
#define AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY
max number of bytes that can be stored in the payload of AVSmpte436mCodedAnc
Definition smpte_436m.h:110
#define AV_SMPTE_291M_ANC_DID_CTA_708
AVSmpte291mAnc8bit::did when carrying CTA-708 data (for AV_CODEC_ID_EIA_608)
Definition smpte_436m.h:237
This structure stores compressed data.
Definition packet.h:580
An ANC packet with an 8-bit payload.
Definition smpte_436m.h:98
uint8_t payload[AV_SMPTE_291M_ANC_PAYLOAD_CAPACITY]
Definition smpte_436m.h:102
Iterator over the ANC packets in a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
Definition smpte_436m.h:30
const uint8_t * data_left
Definition smpte_436m.h:33
An encoded ANC packet within a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
Definition smpte_436m.h:117
AVSmpte436mWrappingType wrapping_type
Definition smpte_436m.h:119
uint32_t payload_array_length
Definition smpte_436m.h:122
AVSmpte436mPayloadSampleCoding payload_sample_coding
Definition smpte_436m.h:120
uint16_t payload_sample_count
Definition smpte_436m.h:121
uint8_t payload[AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY]
the payload, has size payload_array_length.
Definition smpte_436m.h:126
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
int size