avcodec/x86/h264_idct: Fix ff_h264_luma_dc_dequant_idct_sse2 checkasm failures
[ffmpeg.git] / libavformat / mccenc.c
1 /*
2 * MCC subtitle muxer
3 * Copyright (c) 2025 Jacob Lifshay
4 * Copyright (c) 2017 Paul B Mahol
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "avformat.h"
24 #include "internal.h"
25 #include "mux.h"
26 #include "version.h"
27
28 #include "libavcodec/codec_id.h"
29 #include "libavcodec/smpte_436m.h"
30
31 #include "libavutil/avassert.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/error.h"
34 #include "libavutil/log.h"
35 #include "libavutil/macros.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/parseutils.h"
38 #include "libavutil/rational.h"
39 #include "libavutil/time_internal.h" // for localtime_r
40 #include "libavutil/timecode.h"
41
42 typedef struct MCCContext {
43 const AVClass *class;
44 AVTimecode timecode;
45 int64_t twenty_four_hr;
46 char *override_time_code_rate;
47 int use_u_alias;
48 unsigned mcc_version;
49 char *creation_program;
50 char *creation_time;
51 } MCCContext;
52
53 typedef enum MCCVersion
54 {
55 MCC_VERSION_1 = 1,
56 MCC_VERSION_2 = 2,
57 MCC_VERSION_MIN = MCC_VERSION_1,
58 MCC_VERSION_MAX = MCC_VERSION_2,
59 } MCCVersion;
60
61 #define MCC_HEADER \
62 "File Format=MacCaption_MCC V%c.0\n" \
63 "\n" \
64 "///////////////////////////////////////////////////////////////////////////////////\n" \
65 "// Computer Prompting and Captioning Company\n" \
66 "// Ancillary Data Packet Transfer File\n" \
67 "//\n" \
68 "// Permission to generate this format is granted provided that\n" \
69 "// 1. This ANC Transfer file format is used on an as-is basis and no warranty is given, and\n" \
70 "// 2. This entire descriptive information text is included in a generated .mcc file.\n" \
71 "//\n" \
72 "// General file format:\n" \
73 "// HH:MM:SS:FF(tab)[Hexadecimal ANC data in groups of 2 characters]\n" \
74 "// Hexadecimal data starts with the Ancillary Data Packet DID (Data ID defined in S291M)\n" \
75 "// and concludes with the Check Sum following the User Data Words.\n" \
76 "// Each time code line must contain at most one complete ancillary data packet.\n" \
77 "// To transfer additional ANC Data successive lines may contain identical time code.\n" \
78 "// Time Code Rate=[24, 25, 30, 30DF, 50, 60%s]\n" \
79 "//\n" \
80 "// ANC data bytes may be represented by one ASCII character according to the following schema:\n" \
81 "// G FAh 00h 00h\n" \
82 "// H 2 x (FAh 00h 00h)\n" \
83 "// I 3 x (FAh 00h 00h)\n" \
84 "// J 4 x (FAh 00h 00h)\n" \
85 "// K 5 x (FAh 00h 00h)\n" \
86 "// L 6 x (FAh 00h 00h)\n" \
87 "// M 7 x (FAh 00h 00h)\n" \
88 "// N 8 x (FAh 00h 00h)\n" \
89 "// O 9 x (FAh 00h 00h)\n" \
90 "// P FBh 80h 80h\n" \
91 "// Q FCh 80h 80h\n" \
92 "// R FDh 80h 80h\n" \
93 "// S 96h 69h\n" \
94 "// T 61h 01h\n" \
95 "// U E1h 00h 00h 00h\n" \
96 "// Z 00h\n" \
97 "//\n" \
98 "///////////////////////////////////////////////////////////////////////////////////\n"
99
100 #define MCC_HEADER_PRINTF_ARGS(mcc_version) (mcc_version) + '0', \
101 (mcc_version) == MCC_VERSION_1 ? "" : ", 60DF"
102
103 /**
104 * generated with the bash command:
105 * ```bash
106 * URL="https://code.ffmpeg.org/FFmpeg/FFmpeg/src/branch/master/libavformat/mccenc.c"
107 * python3 -c "from uuid import *; print(str(uuid5(NAMESPACE_URL, '$URL')).upper())"
108 * ```
109 */
110 static const char mcc_ffmpeg_uuid[] = "0087C4F6-A6B4-5469-8C8E-BBF44950401D";
111
112 static const AVRational valid_time_code_rates[] = {
113 { .num = 24, .den = 1 },
114 { .num = 25, .den = 1 },
115 { .num = 30000, .den = 1001 },
116 { .num = 30, .den = 1 },
117 { .num = 50, .den = 1 },
118 { .num = 60000, .den = 1001 },
119 { .num = 60, .den = 1 },
120 };
121
122 static int mcc_write_header(AVFormatContext *avf)
123 {
124 MCCContext *mcc = avf->priv_data;
125 const char *creation_program = mcc->creation_program;
126 if (!creation_program) {
127 if (avf->flags & AVFMT_FLAG_BITEXACT)
128 creation_program = "Lavf";
129 else
130 creation_program = LIBAVFORMAT_IDENT;
131 } else if (strchr(creation_program, '\n')) {
132 av_log(avf, AV_LOG_FATAL, "creation_program must not contain multiple lines of text\n");
133 return AVERROR(EINVAL);
134 }
135 if (avf->flags & AVFMT_FLAG_BITEXACT && !av_strcasecmp(mcc->creation_time, "now"))
136 av_log(avf, AV_LOG_ERROR, "creation_time must be overridden for bit-exact output\n");
137 int64_t timeval = 0;
138 int ret = av_parse_time(&timeval, mcc->creation_time, 0);
139 if (ret < 0) {
140 av_log(avf, AV_LOG_FATAL, "can't parse creation_time\n");
141 return ret;
142 }
143 struct tm tm;
144 if (!localtime_r((time_t[1]){ timeval / 1000000 }, &tm))
145 return AVERROR(EINVAL);
146 // we can't rely on having the C locale, so convert the date/time to a string ourselves:
147 static const char months[12][10] = {
148 "January",
149 "February",
150 "March",
151 "April",
152 "May",
153 "June",
154 "July",
155 "August",
156 "September",
157 "October",
158 "November",
159 "December",
160 };
161 // assert that values are sane so we don't index out of bounds
162 av_assert0(tm.tm_mon >= 0 && tm.tm_mon < FF_ARRAY_ELEMS(months));
163 const char *month = months[tm.tm_mon];
164
165 static const char weekdays[7][10] = {
166 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
167 };
168 // assert that values are sane so we don't index out of bounds
169 av_assert0(tm.tm_wday >= 0 && tm.tm_wday < FF_ARRAY_ELEMS(weekdays));
170 const char *weekday = weekdays[tm.tm_wday];
171
172 avio_printf(avf->pb,
173 MCC_HEADER "\n"
174 "UUID=%s\n"
175 "Creation Program=%s\n"
176 "Creation Date=%s, %s %d, %d\n"
177 "Creation Time=%02d:%02d:%02d\n"
178 "Time Code Rate=%u%s\n\n",
179 MCC_HEADER_PRINTF_ARGS(mcc->mcc_version),
180 mcc_ffmpeg_uuid,
181 creation_program,
182 weekday,
183 month,
184 tm.tm_mday,
185 tm.tm_year + 1900,
186 tm.tm_hour,
187 tm.tm_min,
188 tm.tm_sec,
189 mcc->timecode.fps,
190 mcc->timecode.flags & AV_TIMECODE_FLAG_DROPFRAME ? "DF" : "");
191
192 return 0;
193 }
194
195 /// convert the input bytes to hexadecimal with mcc's aliases
196 static void mcc_bytes_to_hex(char *dest, const uint8_t *bytes, size_t bytes_size, int use_u_alias)
197 {
198 while (bytes_size != 0) {
199 switch (bytes[0]) {
200 case 0xFA:
201 *dest = '\0';
202 for (unsigned char code = 'G'; code <= (unsigned char)'O'; code++) {
203 if (bytes_size < 3)
204 break;
205 if (bytes[0] != 0xFA || bytes[1] != 0 || bytes[2] != 0)
206 break;
207 *dest = code;
208 bytes += 3;
209 bytes_size -= 3;
210 }
211 if (*dest) {
212 dest++;
213 continue;
214 }
215 break;
216 case 0xFB:
217 case 0xFC:
218 case 0xFD:
219 if (bytes_size >= 3 && bytes[1] == 0x80 && bytes[2] == 0x80) {
220 *dest++ = bytes[0] - 0xFB + 'P';
221 bytes += 3;
222 bytes_size -= 3;
223 continue;
224 }
225 break;
226 case 0x96:
227 if (bytes_size >= 2 && bytes[1] == 0x69) {
228 *dest++ = 'S';
229 bytes += 2;
230 bytes_size -= 2;
231 continue;
232 }
233 break;
234 case 0x61:
235 if (bytes_size >= 2 && bytes[1] == 0x01) {
236 *dest++ = 'T';
237 bytes += 2;
238 bytes_size -= 2;
239 continue;
240 }
241 break;
242 case 0xE1:
243 if (use_u_alias && bytes_size >= 4 && bytes[1] == 0 && bytes[2] == 0 && bytes[3] == 0) {
244 *dest++ = 'U';
245 bytes += 4;
246 bytes_size -= 4;
247 continue;
248 }
249 break;
250 case 0:
251 *dest++ = 'Z';
252 bytes++;
253 bytes_size--;
254 continue;
255 default:
256 // any other bytes falls through to writing hex
257 break;
258 }
259 for (int shift = 4; shift >= 0; shift -= 4) {
260 int v = (bytes[0] >> shift) & 0xF;
261 if (v < 0xA)
262 *dest++ = v + '0';
263 else
264 *dest++ = v - 0xA + 'A';
265 }
266 bytes++;
267 bytes_size--;
268 }
269 *dest = '\0';
270 }
271
272 static int mcc_write_packet(AVFormatContext *avf, AVPacket *pkt)
273 {
274 MCCContext *mcc = avf->priv_data;
275 int64_t pts = pkt->pts;
276 int ret;
277
278 if (pts == AV_NOPTS_VALUE) {
279 av_log(avf, AV_LOG_WARNING, "Insufficient timestamps.\n");
280 return 0;
281 }
282
283 char timecode_str[AV_TIMECODE_STR_SIZE];
284
285 // wrap pts values at 24hr ourselves since they can be bigger than fits in an int
286 av_timecode_make_string(&mcc->timecode, timecode_str, pts % mcc->twenty_four_hr);
287
288 for (char *p = timecode_str; *p; p++) {
289 // .mcc doesn't use ; for drop-frame time codes
290 if (*p == ';')
291 *p = ':';
292 }
293
294 AVSmpte436mAncIterator iter;
295 ret = av_smpte_436m_anc_iter_init(&iter, pkt->data, pkt->size);
296 if (ret < 0)
297 return ret;
298 AVSmpte436mCodedAnc coded_anc;
299 while ((ret = av_smpte_436m_anc_iter_next(&iter, &coded_anc)) >= 0) {
300 AVSmpte291mAnc8bit anc;
301 ret = av_smpte_291m_anc_8bit_decode(
302 &anc, coded_anc.payload_sample_coding, coded_anc.payload_sample_count, coded_anc.payload, avf);
303 if (ret < 0)
304 return ret;
305 // 4 for did, sdid_or_dbn, data_count, and checksum fields.
306 uint8_t mcc_anc[4 + AV_SMPTE_291M_ANC_PAYLOAD_CAPACITY];
307 size_t mcc_anc_len = 0;
308
309 mcc_anc[mcc_anc_len++] = anc.did;
310 mcc_anc[mcc_anc_len++] = anc.sdid_or_dbn;
311 mcc_anc[mcc_anc_len++] = anc.data_count;
312 memcpy(mcc_anc + mcc_anc_len, anc.payload, anc.data_count);
313 mcc_anc_len += anc.data_count;
314 mcc_anc[mcc_anc_len++] = anc.checksum;
315
316 unsigned field_number;
317 switch (coded_anc.wrapping_type) {
318 case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FRAME:
319 case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_1:
320 case AV_SMPTE_436M_WRAPPING_TYPE_VANC_PROGRESSIVE_FRAME:
321 field_number = 0;
322 break;
323 case AV_SMPTE_436M_WRAPPING_TYPE_VANC_FIELD_2:
324 field_number = 1;
325 break;
326 default:
327 av_log(avf,
328 AV_LOG_WARNING,
329 "Unsupported SMPTE 436M ANC Wrapping Type %#x -- discarding ANC packet\n",
330 (unsigned)coded_anc.wrapping_type);
331 continue;
332 }
333
334 char field_and_line[32] = "";
335 if (coded_anc.line_number != 9) {
336 snprintf(field_and_line, sizeof(field_and_line), ".%u,%u", field_number, (unsigned)coded_anc.line_number);
337 } else if (field_number != 0) {
338 snprintf(field_and_line, sizeof(field_and_line), ".%u", field_number);
339 }
340
341 switch ((MCCVersion)mcc->mcc_version) {
342 case MCC_VERSION_1:
343 if (field_and_line[0] != '\0') {
344 av_log(avf,
345 AV_LOG_WARNING,
346 "MCC Version 1.0 doesn't support ANC packets where the field number (got %u) isn't 0 and "
347 "line number (got %u) isn't 9: discarding ANC packet\n",
348 field_number,
349 (unsigned)coded_anc.line_number);
350 continue;
351 }
352 break;
353 case MCC_VERSION_2:
354 break;
355 }
356
357 // 1 for terminating nul. 2 since there's 2 hex digits per byte.
358 char hex[1 + 2 * sizeof(mcc_anc)];
359 mcc_bytes_to_hex(hex, mcc_anc, mcc_anc_len, mcc->use_u_alias);
360 avio_printf(avf->pb, "%s%s\t%s\n", timecode_str, field_and_line, hex);
361 }
362 if (ret != AVERROR_EOF)
363 return ret;
364 return 0;
365 }
366
367 static int mcc_init(AVFormatContext *avf)
368 {
369 MCCContext *mcc = avf->priv_data;
370 int ret;
371
372 if (avf->nb_streams != 1) {
373 av_log(avf, AV_LOG_ERROR, "mcc muxer supports at most one stream\n");
374 return AVERROR(EINVAL);
375 }
376
377 AVStream *st = avf->streams[0];
378 AVRational time_code_rate = st->avg_frame_rate;
379 int timecode_flags = 0;
380 AVTimecode twenty_four_hr;
381
382 if (mcc->override_time_code_rate && (ret = av_parse_video_rate(&time_code_rate, mcc->override_time_code_rate)) < 0)
383 return ret;
384
385 ret = AVERROR(EINVAL);
386
387 for (size_t i = 0; i < FF_ARRAY_ELEMS(valid_time_code_rates); i++) {
388 if (time_code_rate.num == valid_time_code_rates[i].num && time_code_rate.den == valid_time_code_rates[i].den) {
389 ret = 0;
390 break;
391 }
392 }
393
394 if (ret != 0) {
395 if (!mcc->override_time_code_rate && (time_code_rate.num <= 0 || time_code_rate.den <= 0)) {
396 av_log(avf, AV_LOG_FATAL, "time code rate not set, you need to use -override_time_code_rate to set it\n");
397 } else {
398 av_log(avf,
399 AV_LOG_FATAL,
400 "time code rate not supported by mcc: %d/%d\n",
401 time_code_rate.num,
402 time_code_rate.den);
403 }
404 return AVERROR(EINVAL);
405 }
406
407 avpriv_set_pts_info(st, 64, time_code_rate.den, time_code_rate.num);
408
409 if (time_code_rate.den == 1001 && time_code_rate.num % 30000 == 0) {
410 timecode_flags |= AV_TIMECODE_FLAG_DROPFRAME;
411 }
412
413 ret = av_timecode_init(&mcc->timecode, time_code_rate, timecode_flags, 0, avf);
414 if (ret < 0)
415 return ret;
416
417 if (mcc->mcc_version == MCC_VERSION_1) {
418 if (mcc->timecode.fps == 60 && mcc->timecode.flags & AV_TIMECODE_FLAG_DROPFRAME) {
419 av_log(avf, AV_LOG_FATAL, "MCC Version 1.0 doesn't support 60DF (59.94 fps drop-frame)\n");
420 return AVERROR(EINVAL);
421 }
422 }
423
424 // get av_timecode to calculate how many frames are in 24hr
425 ret = av_timecode_init_from_components(&twenty_four_hr, time_code_rate, timecode_flags, 24, 0, 0, 0, avf);
426 if (ret < 0)
427 return ret;
428
429 mcc->twenty_four_hr = twenty_four_hr.start;
430
431 if (st->codecpar->codec_id == AV_CODEC_ID_EIA_608) {
432 char args[64];
433 snprintf(args, sizeof(args), "cdp_frame_rate=%d/%d", time_code_rate.num, time_code_rate.den);
434 ret = ff_stream_add_bitstream_filter(st, "eia608_to_smpte436m", args);
435 if (ret < 0)
436 return ret;
437 } else if (st->codecpar->codec_id != AV_CODEC_ID_SMPTE_436M_ANC) {
438 av_log(avf,
439 AV_LOG_ERROR,
440 "mcc muxer supports only codec smpte_436m_anc or codec eia_608\n");
441 return AVERROR(EINVAL);
442 }
443
444 return 0;
445 }
446
447 static int mcc_query_codec(enum AVCodecID codec_id, int std_compliance)
448 {
449 (void)std_compliance;
450 if (codec_id == AV_CODEC_ID_EIA_608 || codec_id == AV_CODEC_ID_SMPTE_436M_ANC)
451 return 1;
452 return 0;
453 }
454
455 #define OFFSET(x) offsetof(MCCContext, x)
456 #define ENC AV_OPT_FLAG_ENCODING_PARAM
457 // clang-format off
458 static const AVOption options[] = {
459 { "override_time_code_rate", "override the `Time Code Rate` value in the output", OFFSET(override_time_code_rate), AV_OPT_TYPE_STRING, { .str = NULL }, 0, INT_MAX, ENC },
460 { "use_u_alias", "use the U alias for E1h 00h 00h 00h, disabled by default because some .mcc files disagree on whether it has 2 or 3 zero bytes", OFFSET(use_u_alias), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, ENC },
461 { "mcc_version", "the mcc file format version", OFFSET(mcc_version), AV_OPT_TYPE_UINT, { .i64 = MCC_VERSION_2 }, MCC_VERSION_MIN, MCC_VERSION_MAX, ENC },
462 { "creation_program", "the creation program", OFFSET(creation_program), AV_OPT_TYPE_STRING, { .str = NULL }, 0, INT_MAX, ENC },
463 { "creation_time", "the creation time", OFFSET(creation_time), AV_OPT_TYPE_STRING, { .str = "now" }, 0, INT_MAX, ENC },
464 { NULL },
465 };
466 // clang-format on
467
468 static const AVClass mcc_muxer_class = {
469 .class_name = "mcc muxer",
470 .item_name = av_default_item_name,
471 .option = options,
472 .version = LIBAVUTIL_VERSION_INT,
473 };
474
475 const FFOutputFormat ff_mcc_muxer = {
476 .p.name = "mcc",
477 .p.long_name = NULL_IF_CONFIG_SMALL("MacCaption"),
478 .p.extensions = "mcc",
479 .p.flags = AVFMT_GLOBALHEADER,
480 .p.video_codec = AV_CODEC_ID_NONE,
481 .p.audio_codec = AV_CODEC_ID_NONE,
482 .p.subtitle_codec = AV_CODEC_ID_EIA_608,
483 .p.priv_class = &mcc_muxer_class,
484 .priv_data_size = sizeof(MCCContext),
485 .init = mcc_init,
486 .query_codec = mcc_query_codec,
487 .write_header = mcc_write_header,
488 .write_packet = mcc_write_packet,
489 };