History

lavc: add API for manipulating SMPTE-436M VBI/ANC data

Jacob Lifshay committed 1 year ago

Commit 1c85a381 parent a566fcb7 files · +835 −0Browse files

Unified · Split

7 files
  1. .forgejo/pre-commit/ignored-words.txt +1 −0
  2. configure +1 −0
  3. doc/APIchanges +4 −0
  4. libavcodec/Makefile +2 −0
  5. libavcodec/smpte_436m.c +475 −0
  6. libavcodec/smpte_436m.h +254 −0
  7. libavcodec/smpte_436m_internal.h +98 −0
.forgejo/pre-commit/ignored-words.txt+1−0
@@ -8,6 +8,7 @@ ALOG · 7 unmodified lines
88 ALS
99 als
1010 ANC
11+anc
1112 ANS
1213 ans
1314 anull
configure+1−0
@@ -2651,6 +2651,7 @@ CONFIG_EXTRA=" · 2650 unmodified lines
26512651 rv34dsp
26522652 scene_sad
26532653 sinewin
2654+ smpte_436m
26542655 snappy
26552656 srtp
26562657 startcode
doc/APIchanges+4−0
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2025-03-28 · 1 unmodified line
22
33 API changes, most recent first:
44
5+2025-07-29 - xxxxxxxxxx - lavc 62.10.100 - smpte_436m.h
6+ Add a new public header smpte_436m.h with API for
7+ manipulating AV_CODEC_ID_SMPTE_436M_ANC data.
8+
59 2025-07-10 - xxxxxxxxxx - lavf 62.2.100
610 mxf [de]muxer now uses AV_CODEC_ID_SMPTE_436M_ANC for
711 the vbi_vanc_smpte_436M streams instead of AV_CODEC_ID_NONE.
libavcodec/Makefile+2−0
@@ -19,6 +19,7 @@ HEADERS = ac3_parser.h \ · 18 unmodified lines
1919 mediacodec.h \
2020 packet.h \
2121 qsv.h \
22+ smpte_436m.h \
2223 vdpau.h \
2324 version.h \
2425 version_major.h \
@@ -167,6 +168,7 @@ OBJS-$(CONFIG_QSVENC) += qsvenc.o · 142 unmodified lines
167168 OBJS-$(CONFIG_RANGECODER) += rangecoder.o
168169 OBJS-$(CONFIG_RV34DSP) += rv34dsp.o
169170 OBJS-$(CONFIG_SINEWIN) += sinewin.o
171+OBJS-$(CONFIG_SMPTE_436M) += smpte_436m.o
170172 OBJS-$(CONFIG_SNAPPY) += snappy.o
171173 OBJS-$(CONFIG_STARTCODE) += startcode.o
172174 OBJS-$(CONFIG_TEXTUREDSP) += texturedsp.o
libavcodec/smpte_436m.c+475−0
@@ -0,0 +1,475 @@
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+
22+#include "libavcodec/smpte_436m.h"
23+#include "bytestream.h"
24+#include "libavcodec/packet.h"
25+#include "libavutil/avassert.h"
26+#include "libavutil/error.h"
27+#include "libavutil/intreadwrite.h"
28+
29+static int validate_smpte_436m_anc_wrapping_type(AVSmpte436mWrappingType wrapping_type)
30+{
31+ switch (wrapping_type) {
32+ case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME:
33+ case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1:
34+ case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2:
35+ case AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME:
36+ case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FRAME:
37+ case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_1:
38+ case AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_2:
39+ case AV_SMPTE_436M_WRAPPING_TYPE_HANC_PROGRESSIVE_FRAME:
40+ return 0;
41+ default:
42+ return AVERROR_INVALIDDATA;
43+ }
44+}
45+
46+static int validate_smpte_436m_anc_payload_sample_coding(AVSmpte436mPayloadSampleCoding payload_sample_coding)
47+{
48+ switch (payload_sample_coding) {
49+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
50+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
51+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
52+ // not allowed for ANC packets
53+ return AVERROR_INVALIDDATA;
54+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
55+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
56+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
57+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
58+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
59+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
60+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
61+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
62+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
63+ return 0;
64+ default:
65+ return AVERROR_INVALIDDATA;
66+ }
67+}
68+
69+int av_smpte_436m_coded_anc_validate(const AVSmpte436mCodedAnc *anc)
70+{
71+ int ret = validate_smpte_436m_anc_wrapping_type(anc->wrapping_type);
72+ if (ret < 0)
73+ return ret;
74+ ret = validate_smpte_436m_anc_payload_sample_coding(anc->payload_sample_coding);
75+ if (ret < 0)
76+ return ret;
77+ if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
78+ return AVERROR_INVALIDDATA;
79+ ret = av_smpte_436m_coded_anc_payload_size(anc->payload_sample_coding, anc->payload_sample_count);
80+ if (ret < 0)
81+ return ret;
82+ if (anc->payload_array_length < ret)
83+ return AVERROR_INVALIDDATA;
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+ */
105+static 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
109+ if (SMPTE_436M_ANC_ENTRY_HEADER_SIZE > size)
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;
129+ if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
130+ return AVERROR_INVALIDDATA;
131+ memcpy(anc->payload, in, anc->payload_array_length);
132+ int ret = av_smpte_436m_coded_anc_validate(anc);
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+ */
146+static 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
150+ if (anc->payload_array_length > AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY)
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)
156+ return AVERROR_BUFFER_TOO_SMALL;
157+ AV_WB16(out, anc->line_number);
158+ out += 2;
159+ AV_WB8(out, anc->wrapping_type);
160+ out++;
161+ AV_WB8(out, anc->payload_sample_coding);
162+ out++;
163+ AV_WB16(out, anc->payload_sample_count);
164+ out += 2;
165+ AV_WB32(out, anc->payload_array_length);
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+
173+int 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)
183+ return AVERROR_BUFFER_TOO_SMALL;
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+
201+int 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+
234+int 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+
250+int av_smpte_436m_anc_iter_next(AVSmpte436mAncIterator *iter, AVSmpte436mCodedAnc *anc)
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+
265+int av_smpte_436m_coded_anc_payload_size(AVSmpte436mPayloadSampleCoding sample_coding, uint16_t sample_count)
266+{
267+ if (sample_count > AV_SMPTE_436M_CODED_ANC_SAMPLE_CAPACITY)
268+ return AVERROR_INVALIDDATA;
269+ switch (sample_coding) {
270+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
271+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
272+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
273+ return AVERROR_INVALIDDATA;
274+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
275+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
276+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
277+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
278+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
279+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
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;
283+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
284+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
285+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
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+
295+int av_smpte_291m_anc_8bit_decode(AVSmpte291mAnc8bit *out,
296+ AVSmpte436mPayloadSampleCoding sample_coding,
297+ uint16_t sample_count,
298+ const uint8_t *payload,
299+ void *log_ctx)
300+{
301+ switch (sample_coding) {
302+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
303+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
304+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
305+ return AVERROR_INVALIDDATA;
306+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
307+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
308+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
309+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
310+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
311+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
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.
322+ av_smpte_291m_anc_8bit_fill_checksum(out);
323+ return 0;
324+ }
325+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
326+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
327+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
328+ av_log(log_ctx,
329+ AV_LOG_ERROR,
330+ "decoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
331+ return AVERROR_PATCHWELCOME;
332+ default:
333+ return AVERROR_INVALIDDATA;
334+ }
335+}
336+
337+void av_smpte_291m_anc_8bit_fill_checksum(AVSmpte291mAnc8bit *anc)
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+
346+int av_smpte_291m_anc_8bit_get_sample_count(const AVSmpte291mAnc8bit *anc,
347+ AVSmpte436mPayloadSampleCoding sample_coding,
348+ void *log_ctx)
349+{
350+ switch (sample_coding) {
351+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
352+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
353+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
354+ return AVERROR_INVALIDDATA;
355+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
356+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
357+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
358+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
359+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
360+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
361+ // 3 for did, sdid_or_dbn, and data_count; checksum isn't stored in 8-bit modes
362+ return 3 + anc->data_count;
363+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
364+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
365+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
366+ av_log(log_ctx,
367+ AV_LOG_ERROR,
368+ "encoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
369+ return AVERROR_PATCHWELCOME;
370+ default:
371+ return AVERROR_INVALIDDATA;
372+ }
373+}
374+
375+int av_smpte_291m_anc_8bit_encode(AVSmpte436mCodedAnc *out,
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) {
399+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA:
400+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF:
401+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF:
402+ return AVERROR_INVALIDDATA;
403+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA:
404+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF:
405+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF:
406+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR:
407+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR:
408+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR:
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+ }
421+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA:
422+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF:
423+ case AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF:
424+ av_log(log_ctx,
425+ AV_LOG_ERROR,
426+ "encoding an ANC packet using the 10-bit SMPTE 436M sample coding isn't implemented.\n");
427+ return AVERROR_PATCHWELCOME;
428+ default:
429+ return AVERROR_INVALIDDATA;
430+ }
431+}
432+
433+int av_smpte_291m_anc_8bit_extract_cta_708(const AVSmpte291mAnc8bit *anc, uint8_t *cc_data, void *log_ctx)
434+{
435+ if (anc->did != AV_SMPTE_291M_ANC_DID_CTA_708 || anc->sdid_or_dbn != AV_SMPTE_291M_ANC_SDID_CTA_708)
436+ return AVERROR(EAGAIN);
437+ GetByteContext gb;
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+
472+too_short:
473+ av_log(log_ctx, AV_LOG_ERROR, "not enough bytes in cdp\n");
474+ return AVERROR_INVALIDDATA;
475+}
libavcodec/smpte_436m.h+254−0
@@ -0,0 +1,254 @@
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+
22+#ifndef AVCODEC_SMPTE_436M_H
23+#define AVCODEC_SMPTE_436M_H
24+
25+#include <stdint.h>
26+
27+/**
28+ * Iterator over the ANC packets in a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data
29+ */
30+typedef struct AVSmpte436mAncIterator {
31+ uint16_t anc_packets_left;
32+ int size_left;
33+ const uint8_t *data_left;
34+} AVSmpte436mAncIterator;
35+
36+/**
37+ * Wrapping Type from Table 7 (page 13) of:
38+ * https://pub.smpte.org/latest/st436/s436m-2006.pdf
39+ */
40+typedef enum AVSmpte436mWrappingType
41+{
42+ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME = 1,
43+ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1 = 2,
44+ AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2 = 3,
45+ AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME = 4,
46+ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FRAME = 0x11,
47+ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_1 = 0x12,
48+ AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_2 = 0x13,
49+ AV_SMPTE_436M_WRAPPING_TYPE_HANC_PROGRESSIVE_FRAME = 0x14,
50+ /** not a real wrapping type, just here to guarantee the enum is big enough */
51+ AV_SMPTE_436M_WRAPPING_TYPE_MAX = 0xFF,
52+} AVSmpte436mWrappingType;
53+
54+/**
55+ * Payload Sample Coding from Table 4 (page 10) and Table 7 (page 13) of:
56+ * https://pub.smpte.org/latest/st436/s436m-2006.pdf
57+ */
58+typedef enum AVSmpte436mPayloadSampleCoding
59+{
60+ /** only used for VBI */
61+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA = 1,
62+ /** only used for VBI */
63+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF = 2,
64+ /** only used for VBI */
65+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF = 3,
66+ /** used for VBI and ANC */
67+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA = 4,
68+ /** used for VBI and ANC */
69+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF = 5,
70+ /** used for VBI and ANC */
71+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF = 6,
72+ /** used for VBI and ANC */
73+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA = 7,
74+ /** used for VBI and ANC */
75+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF = 8,
76+ /** used for VBI and ANC */
77+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF = 9,
78+ /** only used for ANC */
79+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR = 10,
80+ /** only used for ANC */
81+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR = 11,
82+ /** only used for ANC */
83+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR = 12,
84+ /** not a real sample coding, just here to guarantee the enum is big enough */
85+ AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_MAX = 0xFF,
86+} AVSmpte436mPayloadSampleCoding;
87+
88+/** the payload capacity of AVSmpte291mAnc8bit (and of AVSmpte291mAnc10bit when that gets added) */
89+#define AV_SMPTE_291M_ANC_PAYLOAD_CAPACITY 0xFF
90+
91+/**
92+ * An ANC packet with an 8-bit payload.
93+ * This can be decoded from AVSmpte436mCodedAnc::payload.
94+ *
95+ * Note: Some ANC packets need a 10-bit payload, if stored in this struct,
96+ * the most-significant 2 bits of each sample are discarded.
97+ */
98+typedef struct AVSmpte291mAnc8bit {
99+ uint8_t did;
100+ uint8_t sdid_or_dbn;
101+ uint8_t data_count;
102+ uint8_t payload[AV_SMPTE_291M_ANC_PAYLOAD_CAPACITY];
103+ uint8_t checksum;
104+} AVSmpte291mAnc8bit;
105+
106+/** max number of samples that can be stored in the payload of AVSmpte436mCodedAnc */
107+#define AV_SMPTE_436M_CODED_ANC_SAMPLE_CAPACITY \
108+ (AV_SMPTE_291M_ANC_PAYLOAD_CAPACITY + 4) /* 4 for did, sdid_or_dbn, data_count, and checksum */
109+/** max number of bytes that can be stored in the payload of AVSmpte436mCodedAnc */
110+#define AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY (((AV_SMPTE_436M_CODED_ANC_SAMPLE_CAPACITY + 2) / 3) * 4)
111+
112+/**
113+ * An encoded ANC packet within a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
114+ * The repeated section of Table 7 (page 13) of:
115+ * https://pub.smpte.org/latest/st436/s436m-2006.pdf
116+ */
117+typedef struct AVSmpte436mCodedAnc {
118+ uint16_t line_number;
119+ AVSmpte436mWrappingType wrapping_type;
120+ AVSmpte436mPayloadSampleCoding payload_sample_coding;
121+ uint16_t payload_sample_count;
122+ uint32_t payload_array_length;
123+ /** the payload, has size payload_array_length.
124+ * can be decoded into AVSmpte291mAnc8bit
125+ */
126+ uint8_t payload[AV_SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY];
127+} AVSmpte436mCodedAnc;
128+
129+/**
130+ * Validate a AVSmpte436mCodedAnc structure. Doesn't check if the payload is valid.
131+ * @param[in] anc ANC packet to validate
132+ * @return 0 on success, AVERROR codes otherwise.
133+ */
134+int av_smpte_436m_coded_anc_validate(const AVSmpte436mCodedAnc *anc);
135+
136+/**
137+ * Encode ANC packets into a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
138+ * @param[in] anc_packet_count number of ANC packets to encode
139+ * @param[in] anc_packets the ANC packets to encode
140+ * @param[in] size the size of out. ignored if out is NULL.
141+ * @param[out] out Output bytes. Doesn't write anything if out is NULL.
142+ * @return the number of bytes written on success, AVERROR codes otherwise.
143+ * If out is NULL, returns the number of bytes it would have written.
144+ */
145+int av_smpte_436m_anc_encode(uint8_t *out, int size, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets);
146+
147+struct AVPacket;
148+
149+/**
150+ * Append more ANC packets to a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
151+ * @param[in] anc_packet_count number of ANC packets to encode
152+ * @param[in] anc_packets the ANC packets to encode
153+ * @param pkt the AVPacket to append to.
154+ * it must either be size 0 or contain valid SMPTE_436M_ANC data.
155+ * @return 0 on success, AVERROR codes otherwise.
156+ */
157+int av_smpte_436m_anc_append(struct AVPacket *pkt, int anc_packet_count, const AVSmpte436mCodedAnc *anc_packets);
158+
159+/**
160+ * Set up iteration over the ANC packets in a single AV_CODEC_ID_SMPTE_436M_ANC AVPacket's data.
161+ * @param[in] buf Pointer to the data from a AV_CODEC_ID_SMPTE_436M_ANC AVPacket.
162+ * @param[in] buf_size Size of the data from a AV_CODEC_ID_SMPTE_436M_ANC AVPacket.
163+ * @param[out] iter Pointer to the iterator.
164+ * @return 0 on success, AVERROR codes otherwise.
165+ */
166+int av_smpte_436m_anc_iter_init(AVSmpte436mAncIterator *iter, const uint8_t *buf, int buf_size);
167+
168+/**
169+ * Get the next ANC packet from the iterator, advancing the iterator.
170+ * @param[in,out] iter Pointer to the iterator.
171+ * @param[out] anc The returned ANC packet.
172+ * @return 0 on success, AVERROR_EOF when the iterator has reached the end, AVERROR codes otherwise.
173+ */
174+int av_smpte_436m_anc_iter_next(AVSmpte436mAncIterator *iter, AVSmpte436mCodedAnc *anc);
175+
176+/**
177+ * Get the minimum number of bytes needed to store a AVSmpte436mCodedAnc payload.
178+ * @param sample_coding the payload sample coding
179+ * @param sample_count the number of samples stored in the payload
180+ * @return returns the minimum number of bytes needed, on error returns < 0.
181+ * always <= SMPTE_436M_CODED_ANC_PAYLOAD_CAPACITY
182+ */
183+int av_smpte_436m_coded_anc_payload_size(AVSmpte436mPayloadSampleCoding sample_coding, uint16_t sample_count);
184+
185+/**
186+ * Decode a AVSmpte436mCodedAnc payload into AVSmpte291mAnc8bit
187+ * @param[in] sample_coding the payload sample coding
188+ * @param[in] sample_count the number of samples stored in the payload
189+ * @param[in] payload the bytes storing the payload,
190+ * the needed size can be obtained from
191+ avpriv_smpte_436m_coded_anc_payload_size
192+ * @param[in] log_ctx context pointer for av_log
193+ * @param[out] out The decoded ANC packet.
194+ * @return returns 0 on success, otherwise < 0.
195+ */
196+int av_smpte_291m_anc_8bit_decode(AVSmpte291mAnc8bit *out,
197+ AVSmpte436mPayloadSampleCoding sample_coding,
198+ uint16_t sample_count,
199+ const uint8_t *payload,
200+ void *log_ctx);
201+
202+/**
203+ * Fill in the correct checksum for a AVSmpte291mAnc8bit
204+ * @param[in,out] anc The ANC packet.
205+ */
206+void av_smpte_291m_anc_8bit_fill_checksum(AVSmpte291mAnc8bit *anc);
207+
208+/**
209+ * Compute the sample count needed to encode a AVSmpte291mAnc8bit into a AVSmpte436mCodedAnc payload
210+ * @param[in] anc The ANC packet.
211+ * @param[in] sample_coding The sample coding.
212+ * @param[in] log_ctx context pointer for av_log
213+ * @return returns the sample count on success, otherwise < 0.
214+ */
215+int av_smpte_291m_anc_8bit_get_sample_count(const AVSmpte291mAnc8bit *anc,
216+ AVSmpte436mPayloadSampleCoding sample_coding,
217+ void *log_ctx);
218+
219+/**
220+ * Encode a AVSmpte291mAnc8bit into a AVSmpte436mCodedAnc
221+ * @param[in] line_number the line number the ANC packet is on
222+ * @param[in] wrapping_type the wrapping type
223+ * @param[in] sample_coding the payload sample coding
224+ * @param[in] payload the ANC packet to encode.
225+ * @param[in] log_ctx context pointer for av_log
226+ * @param[out] out The encoded ANC packet.
227+ * @return returns 0 on success, otherwise < 0.
228+ */
229+int av_smpte_291m_anc_8bit_encode(AVSmpte436mCodedAnc *out,
230+ uint16_t line_number,
231+ AVSmpte436mWrappingType wrapping_type,
232+ AVSmpte436mPayloadSampleCoding sample_coding,
233+ const AVSmpte291mAnc8bit *payload,
234+ void *log_ctx);
235+
236+/** AVSmpte291mAnc8bit::did when carrying CTA-708 data (for AV_CODEC_ID_EIA_608) */
237+#define AV_SMPTE_291M_ANC_DID_CTA_708 0x61
238+
239+/** AVSmpte291mAnc8bit::sdid_or_dbn when carrying CTA-708 data (for AV_CODEC_ID_EIA_608) */
240+#define AV_SMPTE_291M_ANC_SDID_CTA_708 0x1
241+
242+/**
243+ * Try to decode an ANC packet into EIA-608/CTA-708 data (AV_CODEC_ID_EIA_608). This
244+ * @param[in] anc The ANC packet.
245+ * @param[in] log_ctx Context pointer for av_log
246+ * @param[out] cc_data the buffer to store the extracted EIA-608/CTA-708 data,
247+ * you can pass NULL to not store the data.
248+ * the required size is 3 * cc_count bytes.
249+ * SMPTE_291M_ANC_PAYLOAD_CAPACITY is always enough size.
250+ * @return returns cc_count (>= 0) on success, AVERROR(EAGAIN) if it wasn't a CTA-708 ANC packet, < 0 on error.
251+ */
252+int av_smpte_291m_anc_8bit_extract_cta_708(const AVSmpte291mAnc8bit *anc, uint8_t *cc_data, void *log_ctx);
253+
254+#endif /* AVCODEC_SMPTE_436M_H */
libavcodec/smpte_436m_internal.h+98−0
@@ -0,0 +1,98 @@
1+/*
2+ * MXF SMPTE-436M VBI/ANC internals
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+
22+#ifndef AVCODEC_SMPTE_436M_INTERNAL_H
23+#define AVCODEC_SMPTE_436M_INTERNAL_H
24+
25+#include "smpte_436m.h"
26+
27+// clang-format off
28+#define FF_SMPTE_436M_WRAPPING_TYPE_VANC_AVOPTIONS(flags, unit_name) \
29+ { "vanc_frame", "VANC frame (interlaced or segmented progressive frame)", 0, AV_OPT_TYPE_CONST, \
30+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME}, 0, 0xFF, flags, .unit = unit_name }, \
31+ { "vanc_field_1", "VANC field 1", 0, AV_OPT_TYPE_CONST, \
32+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1}, 0, 0xFF, flags, .unit = unit_name }, \
33+ { "vanc_field_2", "VANC field 2", 0, AV_OPT_TYPE_CONST, \
34+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2}, 0, 0xFF, flags, .unit = unit_name }, \
35+ { "vanc_progressive_frame", "VANC progressive frame", 0, AV_OPT_TYPE_CONST, \
36+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME}, 0, 0xFF, flags, .unit = unit_name }
37+
38+#define FF_SMPTE_436M_WRAPPING_TYPE_HANC_AVOPTIONS(flags, unit_name) \
39+ { "hanc_frame", "HANC frame (interlaced or segmented progressive frame)", 0, AV_OPT_TYPE_CONST, \
40+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_HANC_FRAME}, 0, 0xFF, flags, .unit = unit_name }, \
41+ { "hanc_field_1", "HANC field 1", 0, AV_OPT_TYPE_CONST, \
42+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_1}, 0, 0xFF, flags, .unit = unit_name }, \
43+ { "hanc_field_2", "HANC field 2", 0, AV_OPT_TYPE_CONST, \
44+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_HANC_FIELD_2}, 0, 0xFF, flags, .unit = unit_name }, \
45+ { "hanc_progressive_frame", "HANC progressive frame", 0, AV_OPT_TYPE_CONST, \
46+ {.i64 = AV_SMPTE_436M_WRAPPING_TYPE_HANC_PROGRESSIVE_FRAME}, 0, 0xFF, flags, .unit = unit_name }
47+
48+#define FF_SMPTE_436M_WRAPPING_TYPE_AVOPTIONS(flags, unit_name) \
49+ FF_SMPTE_436M_WRAPPING_TYPE_VANC_AVOPTIONS(flags, unit_name), \
50+ FF_SMPTE_436M_WRAPPING_TYPE_HANC_AVOPTIONS(flags, unit_name)
51+// clang-format on
52+
53+// clang-format off
54+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_VBI_AVOPTIONS(flags, unit_name) \
55+ { "1bit_luma", "1-bit component luma samples", 0, AV_OPT_TYPE_CONST, \
56+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA}, 0, 0xFF, flags, .unit = unit_name }, \
57+ { "1bit_color_diff", "1-bit component color difference samples", 0, AV_OPT_TYPE_CONST, \
58+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }, \
59+ { "1bit_luma_and_color_diff", "1-bit component luma and color difference samples", 0, AV_OPT_TYPE_CONST, \
60+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_1BIT_LUMA_AND_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }
61+
62+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_SHARED_AVOPTIONS(flags, unit_name) \
63+ { "8bit_luma", "8-bit component luma samples", 0, AV_OPT_TYPE_CONST, \
64+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA}, 0, 0xFF, flags, .unit = unit_name }, \
65+ { "8bit_color_diff", "8-bit component color difference samples", 0, AV_OPT_TYPE_CONST, \
66+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }, \
67+ { "8bit_luma_and_color_diff", "8-bit component luma and color difference samples", 0, AV_OPT_TYPE_CONST, \
68+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }, \
69+ { "10bit_luma", "10-bit component luma samples", 0, AV_OPT_TYPE_CONST, \
70+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA}, 0, 0xFF, flags, .unit = unit_name }, \
71+ { "10bit_color_diff", "10-bit component color difference samples", 0, AV_OPT_TYPE_CONST, \
72+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }, \
73+ { "10bit_luma_and_color_diff", "10-bit component luma and color difference samples", 0, AV_OPT_TYPE_CONST, \
74+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_10BIT_LUMA_AND_COLOR_DIFF}, 0, 0xFF, flags, .unit = unit_name }
75+
76+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_ANC_AVOPTIONS(flags, unit_name) \
77+ { "8bit_luma_parity_error", "8-bit component luma samples with parity error", 0, AV_OPT_TYPE_CONST, \
78+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_WITH_PARITY_ERROR}, 0, 0xFF, flags, .unit = unit_name }, \
79+ { "8bit_color_diff_parity_error", "8-bit component color difference samples with parity error", 0, AV_OPT_TYPE_CONST, \
80+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_COLOR_DIFF_WITH_PARITY_ERROR}, 0, 0xFF, flags, .unit = unit_name }, \
81+ { "8bit_luma_and_color_diff_parity_error", "8-bit component luma and color difference samples with parity error", 0, AV_OPT_TYPE_CONST, \
82+ {.i64 = AV_SMPTE_436M_PAYLOAD_SAMPLE_CODING_8BIT_LUMA_AND_COLOR_DIFF_WITH_PARITY_ERROR}, 0, 0xFF, flags, .unit = unit_name }
83+
84+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_VBI_AVOPTIONS(flags, unit_name) \
85+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_VBI_AVOPTIONS(flags, unit_name), \
86+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_SHARED_AVOPTIONS(flags, unit_name)
87+
88+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ANC_AVOPTIONS(flags, unit_name) \
89+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_SHARED_AVOPTIONS(flags, unit_name), \
90+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_ANC_AVOPTIONS(flags, unit_name)
91+
92+#define FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_AVOPTIONS(flags, unit_name) \
93+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_VBI_AVOPTIONS(flags, unit_name), \
94+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_SHARED_AVOPTIONS(flags, unit_name), \
95+ FF_SMPTE_436M_PAYLOAD_SAMPLE_CODING_ONLY_IN_ANC_AVOPTIONS(flags, unit_name)
96+// clang-format on
97+
98+#endif /* AVCODEC_SMPTE_436M_INTERNAL_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t