1use crate::diagnostics::codes::ValidationCode;
4use crate::diagnostics::{Category, Severity};
5
6macro_rules! impl_into_string {
7 ($t:ty) => {
8 impl From<$t> for String {
9 fn from(c: $t) -> String {
10 <$t as ValidationCode>::code(&c).to_string()
11 }
12 }
13 };
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::EnumIter)]
22pub enum St2067_21_2020 {
23 AppIdMismatch,
25}
26
27impl ValidationCode for St2067_21_2020 {
28 fn code(&self) -> &'static str {
29 match self {
30 Self::AppIdMismatch => "ST2067-21:2020:7.1/AppIdMismatch",
31 }
32 }
33 fn description(&self) -> &'static str {
34 match self {
35 Self::AppIdMismatch =>
36 "Application identifier in CPL ExtensionProperties does not match the expected App2E URI.",
37 }
38 }
39 fn default_severity(&self) -> Severity {
40 Severity::Warning
41 }
42 fn category(&self) -> Category {
43 Category::Metadata
44 }
45 fn example(&self) -> Option<&'static str> {
46 Some(match self {
47 Self::AppIdMismatch =>
48 "CPL ExtensionProperties contains `<ApplicationIdentification>http://www.smpte-ra.org/schemas/2067-20/2013</ApplicationIdentification>` (App #2) instead of the App #2E URI.",
49 })
50 }
51}
52
53impl St2067_21_2020 {
54 pub const ALL: &'static [Self] = &[Self::AppIdMismatch];
55}
56
57impl_into_string!(St2067_21_2020);
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::EnumIter)]
73pub enum St2067_21_2023 {
74 FrameRate,
77 Resolution,
79
80 EmptyLanguageTag,
83 MalformedLanguageTag,
85 RegionCode,
87
88 ColorSystem,
91
92 RequiredStoredWidth,
95 RequiredStoredHeight,
97 RequiredSampleRate,
99 RequiredFrameLayout,
101 RequiredColorPrimaries,
103 RequiredTransferCharacteristic,
105 RequiredPictureCompression,
107 RequiredComponentDepth,
109
110 RequiredChannelCount,
113 RequiredQuantizationBits,
115
116 AlphaTransparency,
119 CodingEquationsMissing,
121 ColorPrimariesMissing,
123 FieldDominance,
125 FrameLayout,
127 FrameLayoutInterlaced,
129 ImageAlignmentOffset,
131 ImageEndOffset,
133 ImageStartOffset,
135 SampledHeight,
137 SampledWidth,
139 SampledXOffset,
141 SampledYOffset,
143 StoredF2Offset,
145 TransferCharacteristicMissing,
147
148 TransferCharacteristicUnknown,
151
152 CodingEquationsUnknown,
155
156 ColorPrimariesUnknown,
159
160 J2KRequired,
163
164 AlphaMaxRef,
167 AlphaMinRef,
169 ComponentMaxRef,
171 ComponentMinRef,
173 Palette,
175 PaletteLayout,
177 ScanningDirection,
179
180 ComponentRefValues,
183
184 AlphaSampleDepth,
187 ColorSiting,
189 ComponentDepth,
191 HorizontalSubsampling,
193 PaddingBits,
195 ReversedByteOrder,
197 VerticalSubsampling,
199
200 BlackRefLevel,
203 ColorRange,
205 WhiteRefLevel,
207
208 AudioSampleRate,
211 QuantizationBits,
213
214 CodingStyle,
217 J2CLayout,
219 J2KExtendedCapabilities,
221 Jpeg2000SubDescriptor,
223
224 J2KHtNotAllowed,
227 J2K4KResolution,
229 J2K2KResolution,
231 J2KBcpResolution,
233
234 ApplicationIdentification,
237 ContentMaturityRatingAgency,
239 ContentMaturityRatingAgencyUri,
241
242 HomogeneousImageEssence,
245
246 AppIdMismatch,
249
250 SegmentDurationMultiple,
253
254 MaxCLLMaxFALL,
257}
258
259impl ValidationCode for St2067_21_2023 {
260 fn code(&self) -> &'static str {
261 match self {
262 Self::FrameRate => "ST2067-21:2023:5.2/FrameRate",
263 Self::Resolution => "ST2067-21:2023:5.2/Resolution",
264 Self::EmptyLanguageTag => "ST2067-21:2023:5.3/EmptyLanguageTag",
265 Self::MalformedLanguageTag => "ST2067-21:2023:5.3/MalformedLanguageTag",
266 Self::RegionCode => "ST2067-21:2023:5.3/RegionCode",
267 Self::ColorSystem => "ST2067-21:2023:6.2/ColorSystem",
268 Self::RequiredStoredWidth => "ST2067-21:2023:6.2/Required-StoredWidth",
269 Self::RequiredStoredHeight => "ST2067-21:2023:6.2/Required-StoredHeight",
270 Self::RequiredSampleRate => "ST2067-21:2023:6.2/Required-SampleRate",
271 Self::RequiredFrameLayout => "ST2067-21:2023:6.2/Required-FrameLayout",
272 Self::RequiredColorPrimaries => "ST2067-21:2023:6.2/Required-ColorPrimaries",
273 Self::RequiredTransferCharacteristic => {
274 "ST2067-21:2023:6.2/Required-TransferCharacteristic"
275 }
276 Self::RequiredPictureCompression => "ST2067-21:2023:6.2/Required-PictureCompression",
277 Self::RequiredComponentDepth => "ST2067-21:2023:6.2/Required-ComponentDepth",
278 Self::RequiredChannelCount => "ST2067-21:2023:6.5/Required-ChannelCount",
279 Self::RequiredQuantizationBits => "ST2067-21:2023:6.5/Required-QuantizationBits",
280 Self::AlphaTransparency => "ST2067-21:2023:6.2.1/AlphaTransparency",
281 Self::CodingEquationsMissing => "ST2067-21:2023:6.2.1/CodingEquationsMissing",
282 Self::ColorPrimariesMissing => "ST2067-21:2023:6.2.1/ColorPrimariesMissing",
283 Self::FieldDominance => "ST2067-21:2023:6.2.1/FieldDominance",
284 Self::FrameLayout => "ST2067-21:2023:6.2.1/FrameLayout",
285 Self::FrameLayoutInterlaced => "ST2067-21:2023:6.2.1/FrameLayoutInterlaced",
286 Self::ImageAlignmentOffset => "ST2067-21:2023:6.2.1/ImageAlignmentOffset",
287 Self::ImageEndOffset => "ST2067-21:2023:6.2.1/ImageEndOffset",
288 Self::ImageStartOffset => "ST2067-21:2023:6.2.1/ImageStartOffset",
289 Self::SampledHeight => "ST2067-21:2023:6.2.1/SampledHeight",
290 Self::SampledWidth => "ST2067-21:2023:6.2.1/SampledWidth",
291 Self::SampledXOffset => "ST2067-21:2023:6.2.1/SampledXOffset",
292 Self::SampledYOffset => "ST2067-21:2023:6.2.1/SampledYOffset",
293 Self::StoredF2Offset => "ST2067-21:2023:6.2.1/StoredF2Offset",
294 Self::TransferCharacteristicMissing => {
295 "ST2067-21:2023:6.2.1/TransferCharacteristicMissing"
296 }
297 Self::TransferCharacteristicUnknown => {
298 "ST2067-21:2023:6.2.2/TransferCharacteristicUnknown"
299 }
300 Self::CodingEquationsUnknown => "ST2067-21:2023:6.2.3/CodingEquationsUnknown",
301 Self::ColorPrimariesUnknown => "ST2067-21:2023:6.2.4/ColorPrimariesUnknown",
302 Self::J2KRequired => "ST2067-21:2023:6.2.5/J2KRequired",
303 Self::AlphaMaxRef => "ST2067-21:2023:6.3/AlphaMaxRef",
304 Self::AlphaMinRef => "ST2067-21:2023:6.3/AlphaMinRef",
305 Self::ComponentMaxRef => "ST2067-21:2023:6.3/ComponentMaxRef",
306 Self::ComponentMinRef => "ST2067-21:2023:6.3/ComponentMinRef",
307 Self::Palette => "ST2067-21:2023:6.3/Palette",
308 Self::PaletteLayout => "ST2067-21:2023:6.3/PaletteLayout",
309 Self::ScanningDirection => "ST2067-21:2023:6.3/ScanningDirection",
310 Self::ComponentRefValues => "ST2067-21:2023:6.3.2/ComponentRefValues",
311 Self::AlphaSampleDepth => "ST2067-21:2023:6.4/AlphaSampleDepth",
312 Self::ColorSiting => "ST2067-21:2023:6.4/ColorSiting",
313 Self::ComponentDepth => "ST2067-21:2023:6.4/ComponentDepth",
314 Self::HorizontalSubsampling => "ST2067-21:2023:6.4/HorizontalSubsampling",
315 Self::PaddingBits => "ST2067-21:2023:6.4/PaddingBits",
316 Self::ReversedByteOrder => "ST2067-21:2023:6.4/ReversedByteOrder",
317 Self::VerticalSubsampling => "ST2067-21:2023:6.4/VerticalSubsampling",
318 Self::BlackRefLevel => "ST2067-21:2023:6.4.3/BlackRefLevel",
319 Self::ColorRange => "ST2067-21:2023:6.4.3/ColorRange",
320 Self::WhiteRefLevel => "ST2067-21:2023:6.4.3/WhiteRefLevel",
321 Self::AudioSampleRate => "ST2067-21:2023:6.5/AudioSampleRate",
322 Self::QuantizationBits => "ST2067-21:2023:6.5/QuantizationBits",
323 Self::CodingStyle => "ST2067-21:2023:6.5.2/CodingStyle",
324 Self::J2CLayout => "ST2067-21:2023:6.5.2/J2CLayout",
325 Self::J2KExtendedCapabilities => "ST2067-21:2023:6.5.2/J2KExtendedCapabilities",
326 Self::Jpeg2000SubDescriptor => "ST2067-21:2023:6.5.2/JPEG2000SubDescriptor",
327 Self::J2KHtNotAllowed => "ST2067-21:2023:6.2.5/J2K-HT-Not-Allowed",
328 Self::J2K4KResolution => "ST2067-21:2023:6.2.5/J2K-4K-Resolution",
329 Self::J2K2KResolution => "ST2067-21:2023:6.2.5/J2K-2K-Resolution",
330 Self::J2KBcpResolution => "ST2067-21:2023:6.2.5/J2K-BCP-Resolution",
331 Self::ApplicationIdentification => "ST2067-21:2023:7.1/ApplicationIdentification",
332 Self::ContentMaturityRatingAgency => "ST2067-21:2023:7.1/ContentMaturityRating-Agency",
333 Self::ContentMaturityRatingAgencyUri => {
334 "ST2067-21:2023:7.1/ContentMaturityRating-Agency-URI"
335 }
336 Self::HomogeneousImageEssence => "ST2067-21:2023:7.2/HomogeneousImageEssence",
337 Self::AppIdMismatch => "ST2067-21:2023:7.1/AppIdMismatch",
338 Self::SegmentDurationMultiple => "ST2067-21:2023:7.4/SegmentDurationMultiple",
339 Self::MaxCLLMaxFALL => "ST2067-21:2023:7.5/MaxCLLMaxFALL",
340 }
341 }
342
343 fn description(&self) -> &'static str {
344 match self {
345 Self::FrameRate => "Frame rate is not in the permitted set for App2E.",
346 Self::Resolution => "Image resolution is not in the permitted set for App2E.",
347 Self::EmptyLanguageTag => "Locale language tag is empty.",
348 Self::MalformedLanguageTag => "Locale language tag is not a valid BCP-47 subtag.",
349 Self::RegionCode => "Region subtag in a language tag is not valid.",
350 Self::ColorSystem => "Color system designator is not in the permitted set.",
351 Self::RequiredStoredWidth => "RGBA/CDCI descriptor is missing the required StoredWidth field.",
352 Self::RequiredStoredHeight => "RGBA/CDCI descriptor is missing the required StoredHeight field.",
353 Self::RequiredSampleRate => "RGBA/CDCI descriptor is missing the required SampleRate field.",
354 Self::RequiredFrameLayout => "RGBA/CDCI descriptor is missing the required FrameLayout field.",
355 Self::RequiredColorPrimaries => "RGBA/CDCI descriptor is missing the required ColorPrimaries field.",
356 Self::RequiredTransferCharacteristic => "RGBA/CDCI descriptor is missing the required TransferCharacteristic field.",
357 Self::RequiredPictureCompression => "RGBA/CDCI descriptor is missing the required PictureCompression field.",
358 Self::RequiredComponentDepth => "CDCI descriptor is missing the required ComponentDepth field.",
359 Self::RequiredChannelCount => "WavePCM descriptor is missing the required ChannelCount field.",
360 Self::RequiredQuantizationBits => "WavePCM descriptor is missing the required QuantizationBits field.",
361 Self::AlphaTransparency => "Alpha transparency mode is not permitted in App2E.",
362 Self::CodingEquationsMissing => "CodingEquations field is absent from the picture descriptor (Table 8).",
363 Self::ColorPrimariesMissing => "ColorPrimaries field is absent from the picture descriptor (Table 8).",
364 Self::FieldDominance => "FieldDominance value is not permitted for the declared FrameLayout.",
365 Self::FrameLayout => "FrameLayout value is not in the permitted set for App2E.",
366 Self::FrameLayoutInterlaced => "FrameLayout declares interlaced content, which is not permitted in App2E.",
367 Self::ImageAlignmentOffset => "ImageAlignmentOffset must be zero.",
368 Self::ImageEndOffset => "ImageEndOffset must be zero.",
369 Self::ImageStartOffset => "ImageStartOffset must be zero.",
370 Self::SampledHeight => "SampledHeight must equal StoredHeight.",
371 Self::SampledWidth => "SampledWidth must equal StoredWidth.",
372 Self::SampledXOffset => "SampledXOffset must be zero.",
373 Self::SampledYOffset => "SampledYOffset must be zero.",
374 Self::StoredF2Offset => "StoredF2Offset must be zero.",
375 Self::TransferCharacteristicMissing => "TransferCharacteristic field is absent from the picture descriptor (Table 8).",
376 Self::TransferCharacteristicUnknown => "TransferCharacteristic UL is present but not a recognized value.",
377 Self::CodingEquationsUnknown => "CodingEquations UL is present but not a recognized value.",
378 Self::ColorPrimariesUnknown => "ColorPrimaries UL is present but not a recognized value.",
379 Self::J2KRequired => "Video essence is not JPEG 2000 encoded as required by App2E.",
380 Self::AlphaMaxRef => "AlphaMaxRef value is not permitted.",
381 Self::AlphaMinRef => "AlphaMinRef value is not permitted.",
382 Self::ComponentMaxRef => "ComponentMaxRef value is not in the permitted range.",
383 Self::ComponentMinRef => "ComponentMinRef value is not in the permitted range.",
384 Self::Palette => "Palette is present; palette images are not permitted in App2E.",
385 Self::PaletteLayout => "PaletteLayout is present; palette layout is not permitted in App2E.",
386 Self::ScanningDirection => "ScanningDirection value is not in the permitted set.",
387 Self::ComponentRefValues => "Component max/min reference values are inconsistent with bit depth.",
388 Self::AlphaSampleDepth => "AlphaSampleDepth value is not permitted.",
389 Self::ColorSiting => "ColorSiting value is not in the permitted set.",
390 Self::ComponentDepth => "ComponentDepth value is not in the permitted set (8 / 10 / 12 / 16).",
391 Self::HorizontalSubsampling => "HorizontalSubsampling value is not in the permitted set.",
392 Self::PaddingBits => "PaddingBits must be zero.",
393 Self::ReversedByteOrder => "ReversedByteOrder flag is set; byte reversal is not permitted.",
394 Self::VerticalSubsampling => "VerticalSubsampling value is not in the permitted set.",
395 Self::BlackRefLevel => "BlackRefLevel value is inconsistent with ComponentDepth.",
396 Self::ColorRange => "ColorRange value is not in the permitted set.",
397 Self::WhiteRefLevel => "WhiteRefLevel value is inconsistent with ComponentDepth.",
398 Self::AudioSampleRate => "Audio sample rate must be 48 000 Hz.",
399 Self::QuantizationBits => "QuantizationBits must be 16 or 24.",
400 Self::CodingStyle => "JPEG 2000 codestream coding style is not compliant.",
401 Self::J2CLayout => "JPEG 2000 codestream layout does not meet App2E requirements.",
402 Self::J2KExtendedCapabilities => "JPEG 2000 extended capabilities are declared but not permitted.",
403 Self::Jpeg2000SubDescriptor => "JPEG2000SubDescriptor is absent or incomplete.",
404 Self::J2KHtNotAllowed => "JPEG 2000 HT (ISO 15444-15) is not permitted by App2E 2020.",
405 Self::J2K4KResolution => "JPEG 2000 IMF 4K Profile: stored resolution is outside the permitted range.",
406 Self::J2K2KResolution => "JPEG 2000 IMF 2K Profile: stored resolution is outside the permitted range.",
407 Self::J2KBcpResolution => "JPEG 2000 Broadcast Contribution Profile: stored resolution is outside the permitted range.",
408 Self::ApplicationIdentification => "ApplicationIdentification is required for App2E compositions.",
409 Self::ContentMaturityRatingAgency => "ContentMaturityRating Agency is empty.",
410 Self::ContentMaturityRatingAgencyUri => "ContentMaturityRating Agency is not a valid xs:anyURI.",
411 Self::HomogeneousImageEssence => "All image essence in a composition shall use the same color system.",
412 Self::AppIdMismatch => "Application identifier in CPL ExtensionProperties does not match the expected App2E URI.",
413 Self::SegmentDurationMultiple => "Segment duration must be an integer multiple of 5 edit units.",
414 Self::MaxCLLMaxFALL => "MaxCLL / MaxFALL HDR metadata is absent; recommended for HDR content.",
415 }
416 }
417
418 fn default_severity(&self) -> Severity {
419 match self {
420 Self::MaxCLLMaxFALL => Severity::Info,
421 Self::AppIdMismatch | Self::Jpeg2000SubDescriptor => Severity::Warning,
422 Self::ContentMaturityRatingAgency | Self::ContentMaturityRatingAgencyUri => {
423 Severity::Error
424 }
425 _ => Severity::Error,
426 }
427 }
428
429 fn category(&self) -> Category {
430 match self {
431 Self::EmptyLanguageTag
432 | Self::MalformedLanguageTag
433 | Self::RegionCode
434 | Self::AppIdMismatch
435 | Self::ApplicationIdentification
436 | Self::ContentMaturityRatingAgency
437 | Self::ContentMaturityRatingAgencyUri => Category::Metadata,
438
439 Self::RequiredChannelCount
440 | Self::RequiredQuantizationBits
441 | Self::AudioSampleRate
442 | Self::QuantizationBits => Category::Audio,
443
444 Self::J2KRequired
445 | Self::CodingStyle
446 | Self::J2CLayout
447 | Self::J2KExtendedCapabilities
448 | Self::Jpeg2000SubDescriptor
449 | Self::J2KHtNotAllowed
450 | Self::J2K4KResolution
451 | Self::J2K2KResolution
452 | Self::J2KBcpResolution
453 | Self::RequiredStoredWidth
454 | Self::RequiredStoredHeight
455 | Self::RequiredSampleRate
456 | Self::RequiredFrameLayout
457 | Self::RequiredColorPrimaries
458 | Self::RequiredTransferCharacteristic
459 | Self::RequiredPictureCompression
460 | Self::RequiredComponentDepth => Category::Encoding,
461
462 Self::SegmentDurationMultiple => Category::Timing,
463
464 _ => Category::Video,
465 }
466 }
467 fn example(&self) -> Option<&'static str> {
468 Some(match self {
469 Self::FrameRate =>
470 "<EditRate>30 1</EditRate> <!-- not in {24,25,30,50,60,120}/{1,1001} -->",
471 Self::Resolution =>
472 "<StoredWidth>1280</StoredWidth><StoredHeight>720</StoredHeight> <!-- not 1920×1080 / 3840×2160 / 4096×2160 -->",
473 Self::EmptyLanguageTag =>
474 "<Locale><LanguageList><Language></Language></LanguageList></Locale>",
475 Self::MalformedLanguageTag =>
476 "<Language>123-en</Language> <!-- BCP-47 primary subtag must start with a letter -->",
477 Self::RegionCode =>
478 "<Language>en-XYZ</Language> <!-- region subtag XYZ not in ISO 3166-1 -->",
479 Self::ColorSystem =>
480 "ColorPrimaries + TransferCharacteristic + CodingEquations triple doesn't map to a permitted App2E ColorN system",
481 Self::RequiredStoredWidth =>
482 "<RGBADescriptor>…</RGBADescriptor> <!-- no <StoredWidth> child -->",
483 Self::RequiredStoredHeight =>
484 "<RGBADescriptor>…</RGBADescriptor> <!-- no <StoredHeight> child -->",
485 Self::RequiredSampleRate =>
486 "<RGBADescriptor>…</RGBADescriptor> <!-- no <SampleRate> child -->",
487 Self::RequiredFrameLayout =>
488 "<RGBADescriptor>…</RGBADescriptor> <!-- no <FrameLayout> child -->",
489 Self::RequiredColorPrimaries =>
490 "<RGBADescriptor>…</RGBADescriptor> <!-- no <ColorPrimaries> UL child -->",
491 Self::RequiredTransferCharacteristic =>
492 "<RGBADescriptor>…</RGBADescriptor> <!-- no <TransferCharacteristic> UL child -->",
493 Self::RequiredPictureCompression =>
494 "<RGBADescriptor>…</RGBADescriptor> <!-- no <PictureCompression> UL child -->",
495 Self::RequiredComponentDepth =>
496 "<CDCIDescriptor>…</CDCIDescriptor> <!-- no <ComponentDepth> child -->",
497 Self::RequiredChannelCount =>
498 "<WAVEPCMDescriptor>…</WAVEPCMDescriptor> <!-- no <ChannelCount> child -->",
499 Self::RequiredQuantizationBits =>
500 "<WAVEPCMDescriptor>…</WAVEPCMDescriptor> <!-- no <QuantizationBits> child -->",
501 Self::AlphaTransparency =>
502 "<AlphaTransparency>true</AlphaTransparency> <!-- App2E disallows alpha -->",
503 Self::CodingEquationsMissing =>
504 "<CDCIDescriptor>…</CDCIDescriptor> <!-- no <CodingEquations> UL child -->",
505 Self::ColorPrimariesMissing =>
506 "<CDCIDescriptor>…</CDCIDescriptor> <!-- no <ColorPrimaries> UL child -->",
507 Self::FieldDominance =>
508 "<FieldDominance>2</FieldDominance> on <FrameLayout>FullFrame</FrameLayout>",
509 Self::FrameLayout =>
510 "<FrameLayout>MixedFields</FrameLayout> <!-- not in {FullFrame,SeparateFields,SingleField} -->",
511 Self::FrameLayoutInterlaced =>
512 "<FrameLayout>SeparateFields</FrameLayout> <!-- App2E forbids interlaced -->",
513 Self::ImageAlignmentOffset =>
514 "<ImageAlignmentOffset>16</ImageAlignmentOffset> <!-- must be 0 -->",
515 Self::ImageEndOffset =>
516 "<ImageEndOffset>32</ImageEndOffset> <!-- must be 0 -->",
517 Self::ImageStartOffset =>
518 "<ImageStartOffset>16</ImageStartOffset> <!-- must be 0 -->",
519 Self::SampledHeight =>
520 "<StoredHeight>1080</StoredHeight><SampledHeight>1056</SampledHeight>",
521 Self::SampledWidth =>
522 "<StoredWidth>1920</StoredWidth><SampledWidth>1872</SampledWidth>",
523 Self::SampledXOffset =>
524 "<SampledXOffset>4</SampledXOffset> <!-- must be 0 -->",
525 Self::SampledYOffset =>
526 "<SampledYOffset>4</SampledYOffset> <!-- must be 0 -->",
527 Self::StoredF2Offset =>
528 "<StoredF2Offset>1</StoredF2Offset> <!-- must be 0 -->",
529 Self::TransferCharacteristicMissing =>
530 "<CDCIDescriptor>…</CDCIDescriptor> <!-- no <TransferCharacteristic> UL child -->",
531 Self::TransferCharacteristicUnknown =>
532 "<TransferCharacteristic>urn:smpte:ul:060e2b34.04010101.04010101.01010500</TransferCharacteristic> <!-- UL not in §6.2.2 table -->",
533 Self::CodingEquationsUnknown =>
534 "<CodingEquations>urn:smpte:ul:060e2b34.04010101.04010101.02020500</CodingEquations> <!-- UL not in §6.2.3 table -->",
535 Self::ColorPrimariesUnknown =>
536 "<ColorPrimaries>urn:smpte:ul:060e2b34.04010101.04010101.03030500</ColorPrimaries> <!-- UL not in §6.2.4 table -->",
537 Self::J2KRequired =>
538 "<PictureCompression>urn:smpte:ul:060e2b34.04010101.04010202.01020500</PictureCompression> <!-- not a JPEG-2000 UL -->",
539 Self::AlphaMaxRef =>
540 "<AlphaMaxRef>1024</AlphaMaxRef> <!-- outside permitted depth-derived range -->",
541 Self::AlphaMinRef =>
542 "<AlphaMinRef>-1</AlphaMinRef> <!-- outside permitted depth-derived range -->",
543 Self::ComponentMaxRef =>
544 "<ComponentMaxRef>9999</ComponentMaxRef> <!-- beyond (2^ComponentDepth)-1 -->",
545 Self::ComponentMinRef =>
546 "<ComponentMinRef>-5</ComponentMinRef> <!-- must be ≥ 0 -->",
547 Self::Palette =>
548 "<Palette>…</Palette> <!-- palette images forbidden in App2E -->",
549 Self::PaletteLayout =>
550 "<PaletteLayout>…</PaletteLayout> <!-- forbidden in App2E -->",
551 Self::ScanningDirection =>
552 "<ScanningDirection>5</ScanningDirection> <!-- not in permitted set -->",
553 Self::ComponentRefValues =>
554 "<ComponentDepth>10</ComponentDepth><ComponentMaxRef>4096</ComponentMaxRef> <!-- 4096 > (2^10)-1 -->",
555 Self::AlphaSampleDepth =>
556 "<AlphaSampleDepth>7</AlphaSampleDepth> <!-- not in {8,10,12,16} -->",
557 Self::ColorSiting =>
558 "<ColorSiting>9</ColorSiting> <!-- not in permitted set -->",
559 Self::ComponentDepth =>
560 "<ComponentDepth>9</ComponentDepth> <!-- not in {8,10,12,16} -->",
561 Self::HorizontalSubsampling =>
562 "<HorizontalSubsampling>3</HorizontalSubsampling> <!-- not in {1,2,4} -->",
563 Self::PaddingBits =>
564 "<PaddingBits>4</PaddingBits> <!-- must be 0 -->",
565 Self::ReversedByteOrder =>
566 "<ReversedByteOrder>true</ReversedByteOrder> <!-- byte reversal forbidden -->",
567 Self::VerticalSubsampling =>
568 "<VerticalSubsampling>3</VerticalSubsampling> <!-- not in {1,2} -->",
569 Self::BlackRefLevel =>
570 "<ComponentDepth>10</ComponentDepth><BlackRefLevel>16</BlackRefLevel> <!-- expected 64 for 10-bit -->",
571 Self::ColorRange =>
572 "<ComponentDepth>10</ComponentDepth><ColorRange>1019</ColorRange> <!-- not in permitted set -->",
573 Self::WhiteRefLevel =>
574 "<ComponentDepth>10</ComponentDepth><WhiteRefLevel>235</WhiteRefLevel> <!-- expected 940 for 10-bit -->",
575 Self::AudioSampleRate =>
576 "<AudioSampleRate>44100/1</AudioSampleRate> <!-- must be 48000/1 -->",
577 Self::QuantizationBits =>
578 "<QuantizationBits>32</QuantizationBits> <!-- not in {16,24} -->",
579 Self::CodingStyle =>
580 "JPEG2000SubDescriptor CodingStyleDefault Scod byte declares non-compliant entropy coding",
581 Self::J2CLayout =>
582 "JPEG2000SubDescriptor declares >1 layer or unsupported precinct sizes",
583 Self::J2KExtendedCapabilities =>
584 "JPEG2000SubDescriptor <Capabilities><Bit set=\"15\"/></Capabilities> <!-- HT not permitted -->",
585 Self::Jpeg2000SubDescriptor =>
586 "<PictureDescriptor>…</PictureDescriptor> <!-- no JPEG2000SubDescriptor child -->",
587 Self::J2KHtNotAllowed =>
588 "JPEG2000SubDescriptor Profile field declares HTJ2K (ISO 15444-15)",
589 Self::J2K4KResolution =>
590 "<StoredWidth>5000</StoredWidth> <!-- IMF 4K profile caps width at 4096 -->",
591 Self::J2K2KResolution =>
592 "<StoredWidth>2400</StoredWidth> <!-- IMF 2K profile caps width at 2048 -->",
593 Self::J2KBcpResolution =>
594 "<StoredWidth>3840</StoredWidth> <!-- Broadcast Contribution Profile caps width at 1920 -->",
595 Self::ApplicationIdentification =>
596 "<CompositionPlaylist>…</CompositionPlaylist> <!-- ExtensionProperties has no <ApplicationIdentification> -->",
597 Self::ContentMaturityRatingAgency =>
598 "<ContentMaturityRating><Agency></Agency>…</ContentMaturityRating>",
599 Self::ContentMaturityRatingAgencyUri =>
600 "<ContentMaturityRating><Agency>imdb</Agency>…</ContentMaturityRating> <!-- not a URI -->",
601 Self::HomogeneousImageEssence =>
602 "Composition mixes Color1 (BT.709) and Color3 (BT.2020) resources across segments",
603 Self::AppIdMismatch =>
604 "<ApplicationIdentification>http://example.org/not-app2e</ApplicationIdentification>",
605 Self::SegmentDurationMultiple =>
606 "<Resource><SourceDuration>7</SourceDuration></Resource> <!-- not a multiple of 5 -->",
607 Self::MaxCLLMaxFALL =>
608 "HDR content (PQ TransferCharacteristic) with no <MaxCLL> / <MaxFALL> in ExtensionProperties",
609 })
610 }
611}
612
613impl St2067_21_2023 {
614 pub const ALL: &'static [Self] = &[
615 Self::FrameRate,
616 Self::Resolution,
617 Self::EmptyLanguageTag,
618 Self::MalformedLanguageTag,
619 Self::RegionCode,
620 Self::ColorSystem,
621 Self::RequiredStoredWidth,
622 Self::RequiredStoredHeight,
623 Self::RequiredSampleRate,
624 Self::RequiredFrameLayout,
625 Self::RequiredColorPrimaries,
626 Self::RequiredTransferCharacteristic,
627 Self::RequiredPictureCompression,
628 Self::RequiredComponentDepth,
629 Self::RequiredChannelCount,
630 Self::RequiredQuantizationBits,
631 Self::AlphaTransparency,
632 Self::CodingEquationsMissing,
633 Self::ColorPrimariesMissing,
634 Self::FieldDominance,
635 Self::FrameLayout,
636 Self::FrameLayoutInterlaced,
637 Self::ImageAlignmentOffset,
638 Self::ImageEndOffset,
639 Self::ImageStartOffset,
640 Self::SampledHeight,
641 Self::SampledWidth,
642 Self::SampledXOffset,
643 Self::SampledYOffset,
644 Self::StoredF2Offset,
645 Self::TransferCharacteristicMissing,
646 Self::TransferCharacteristicUnknown,
647 Self::CodingEquationsUnknown,
648 Self::ColorPrimariesUnknown,
649 Self::J2KRequired,
650 Self::AlphaMaxRef,
651 Self::AlphaMinRef,
652 Self::ComponentMaxRef,
653 Self::ComponentMinRef,
654 Self::Palette,
655 Self::PaletteLayout,
656 Self::ScanningDirection,
657 Self::ComponentRefValues,
658 Self::AlphaSampleDepth,
659 Self::ColorSiting,
660 Self::ComponentDepth,
661 Self::HorizontalSubsampling,
662 Self::PaddingBits,
663 Self::ReversedByteOrder,
664 Self::VerticalSubsampling,
665 Self::BlackRefLevel,
666 Self::ColorRange,
667 Self::WhiteRefLevel,
668 Self::AudioSampleRate,
669 Self::QuantizationBits,
670 Self::CodingStyle,
671 Self::J2CLayout,
672 Self::J2KExtendedCapabilities,
673 Self::Jpeg2000SubDescriptor,
674 Self::J2KHtNotAllowed,
675 Self::J2K4KResolution,
676 Self::J2K2KResolution,
677 Self::J2KBcpResolution,
678 Self::ApplicationIdentification,
679 Self::ContentMaturityRatingAgency,
680 Self::ContentMaturityRatingAgencyUri,
681 Self::HomogeneousImageEssence,
682 Self::AppIdMismatch,
683 Self::SegmentDurationMultiple,
684 Self::MaxCLLMaxFALL,
685 ];
686}
687
688impl_into_string!(St2067_21_2023);
689
690#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::EnumIter)]
696pub enum St2067_21_2025 {
697 FNTimedText,
699 HICTimedText,
701}
702
703impl ValidationCode for St2067_21_2025 {
704 fn code(&self) -> &'static str {
705 match self {
706 Self::FNTimedText => "ST2067-21:2025:5.6/FNTimedText",
707 Self::HICTimedText => "ST2067-21:2025:5.6/HICTimedText",
708 }
709 }
710 fn description(&self) -> &'static str {
711 match self {
712 Self::FNTimedText => {
713 "Timed text track designated as Forced Narrative (FN) does not comply with §5.6."
714 }
715 Self::HICTimedText => {
716 "Timed text track designated as HI-Caption (HIC) does not comply with §5.6."
717 }
718 }
719 }
720 fn default_severity(&self) -> Severity {
721 Severity::Error
722 }
723 fn category(&self) -> Category {
724 Category::Subtitle
725 }
726 fn example(&self) -> Option<&'static str> {
727 Some(match self {
728 Self::FNTimedText =>
729 "<ForcedNarrativeSequence>…</ForcedNarrativeSequence> <!-- but the referenced essence is not a TimedText track -->",
730 Self::HICTimedText =>
731 "<HearingImpairedCaptionsSequence>…</HearingImpairedCaptionsSequence> <!-- but the referenced essence is not a TimedText track -->",
732 })
733 }
734}
735
736impl St2067_21_2025 {
737 pub const ALL: &'static [Self] = &[Self::FNTimedText, Self::HICTimedText];
738}
739
740impl_into_string!(St2067_21_2025);