cta: parse short audio descriptors

Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
Simon Ser 2022-09-06 19:21:50 +02:00
parent 6f7dc0bcf7
commit 896b83627e
7 changed files with 546 additions and 21 deletions

257
cta.c
View file

@ -18,6 +18,10 @@
* Exclusive upper bound for the detailed timing definitions in the CTA block. * Exclusive upper bound for the detailed timing definitions in the CTA block.
*/ */
#define CTA_DTD_END 127 #define CTA_DTD_END 127
/**
* Number of bytes in a CTA short audio descriptor.
*/
#define CTA_SAD_SIZE 3
static void static void
add_failure(struct di_edid_cta *cta, const char fmt[], ...) add_failure(struct di_edid_cta *cta, const char fmt[], ...)
@ -85,6 +89,242 @@ parse_video_block(struct di_edid_cta *cta, struct di_cta_video_block *video,
return true; return true;
} }
static bool
parse_sad_format(struct di_edid_cta *cta, const uint8_t data[static CTA_SAD_SIZE],
enum di_cta_audio_format *format)
{
uint8_t code, code_ext;
code = get_bit_range(data[0], 6, 3);
switch (code) {
case 0x0:
add_failure_until(cta, 3,
"Audio Data Block: Audio Format Code 0x00 is reserved.");
return false;
case 0x1:
*format = DI_CTA_AUDIO_FORMAT_LPCM;
break;
case 0x2:
*format = DI_CTA_AUDIO_FORMAT_AC3;
break;
case 0x3:
*format = DI_CTA_AUDIO_FORMAT_MPEG1;
break;
case 0x4:
*format = DI_CTA_AUDIO_FORMAT_MP3;
break;
case 0x5:
*format = DI_CTA_AUDIO_FORMAT_MPEG2;
break;
case 0x6:
*format = DI_CTA_AUDIO_FORMAT_AAC_LC;
break;
case 0x7:
*format = DI_CTA_AUDIO_FORMAT_DTS;
break;
case 0x8:
*format = DI_CTA_AUDIO_FORMAT_ATRAC;
break;
case 0x9:
*format = DI_CTA_AUDIO_FORMAT_ONE_BIT_AUDIO;
break;
case 0xA:
*format = DI_CTA_AUDIO_FORMAT_ENHANCED_AC3;
break;
case 0xB:
*format = DI_CTA_AUDIO_FORMAT_DTS_HD;
break;
case 0xC:
*format = DI_CTA_AUDIO_FORMAT_MAT;
break;
case 0xD:
*format = DI_CTA_AUDIO_FORMAT_DST;
break;
case 0xE:
*format = DI_CTA_AUDIO_FORMAT_WMA_PRO;
break;
case 0xF:
code_ext = get_bit_range(data[2], 7, 3);
switch (code_ext) {
case 0x04:
*format = DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC;
break;
case 0x05:
*format = DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_V2;
break;
case 0x06:
*format = DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC;
break;
case 0x07:
*format = DI_CTA_AUDIO_FORMAT_DRA;
break;
case 0x08:
*format = DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_MPEG_SURROUND;
break;
case 0x0A:
*format = DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC_MPEG_SURROUND;
break;
case 0x0B:
*format = DI_CTA_AUDIO_FORMAT_MPEGH_3D;
break;
case 0x0C:
*format = DI_CTA_AUDIO_FORMAT_AC4;
break;
case 0x0D:
*format = DI_CTA_AUDIO_FORMAT_LPCM_3D;
break;
default:
add_failure_until(cta, 3,
"Audio Data Block: Unknown Audio Ext Format 0x%02x.",
code_ext);
return false;
}
break;
default:
add_failure_until(cta, 3,
"Audio Data Block: Unknown Audio Format 0x%02x.",
code);
return false;
}
return true;
}
static bool
parse_sad(struct di_edid_cta *cta, struct di_cta_audio_block *audio,
const uint8_t data[static CTA_SAD_SIZE])
{
enum di_cta_audio_format format;
struct di_cta_sad *sad;
struct di_cta_sad_priv *priv;
uint8_t max_channels_lo, mpegh_3d_level;
if (!parse_sad_format(cta, data, &format))
return true;
priv = calloc(1, sizeof(*priv));
if (!priv)
return false;
sad = &priv->base;
sad->format = format;
/* Parse byte 1 */
switch (format) {
case DI_CTA_AUDIO_FORMAT_LPCM_3D:
max_channels_lo = (uint8_t) (get_bit_range(data[0], 2, 0) |
(get_bit_range(data[0], 7, 7) << 3));
break;
case DI_CTA_AUDIO_FORMAT_MPEGH_3D:
sad->mpegh_3d = &priv->mpegh_3d;
mpegh_3d_level = get_bit_range(data[0], 2, 0);
switch (mpegh_3d_level) {
case DI_CTA_SAD_MPEGH_3D_LEVEL_UNSPECIFIED:
case DI_CTA_SAD_MPEGH_3D_LEVEL_1:
case DI_CTA_SAD_MPEGH_3D_LEVEL_2:
case DI_CTA_SAD_MPEGH_3D_LEVEL_3:
case DI_CTA_SAD_MPEGH_3D_LEVEL_4:
case DI_CTA_SAD_MPEGH_3D_LEVEL_5:
priv->mpegh_3d.level = mpegh_3d_level;
break;
default:
add_failure_until(cta, 3,
"Unknown MPEG-H 3D Audio Level 0x%02x.",
mpegh_3d_level);
break;
}
break;
case DI_CTA_AUDIO_FORMAT_AC4:
if (get_bit_range(data[0], 2, 0) != 0)
add_failure_until(cta, 3, "Bits F10-F12 must be 0.");
break;
default:
sad->max_channels = get_bit_range(data[0], 2, 0) + 1;
break;
}
if (format != DI_CTA_AUDIO_FORMAT_LPCM_3D && has_bit(data[0], 7))
add_failure_until(cta, 3, "Audio Data Block: Bit F17 must be 0.");
/* Parse byte 2 */
priv->supported_sample_rates.has_192_khz = has_bit(data[1], 6);
priv->supported_sample_rates.has_176_4_khz = has_bit(data[1], 5);
priv->supported_sample_rates.has_96_khz = has_bit(data[1], 4);
priv->supported_sample_rates.has_88_2_khz = has_bit(data[1], 3);
priv->supported_sample_rates.has_48_khz = has_bit(data[1], 2);
priv->supported_sample_rates.has_44_1_khz = has_bit(data[1], 1);
priv->supported_sample_rates.has_32_khz = has_bit(data[1], 0);
sad->supported_sample_rates = &priv->supported_sample_rates;
if (format == DI_CTA_AUDIO_FORMAT_LPCM_3D)
sad->max_channels = max_channels_lo
| (get_bit_range(data[1], 7, 7) << 4);
else if (has_bit(data[1], 7))
add_failure_until(cta, 3, "Audio Data Block: Bit F27 must be 0.");
/* TODO: some sample rates are forbidden with some formats */
/* Parse byte 3 */
switch (format) {
case DI_CTA_AUDIO_FORMAT_LPCM:
case DI_CTA_AUDIO_FORMAT_LPCM_3D:
priv->supported_sample_sizes.has_24_bits = has_bit(data[2], 2);
priv->supported_sample_sizes.has_20_bits = has_bit(data[2], 1);
priv->supported_sample_sizes.has_16_bits = has_bit(data[2], 0);
sad->supported_sample_sizes = &priv->supported_sample_sizes;
break;
case DI_CTA_AUDIO_FORMAT_AC3:
case DI_CTA_AUDIO_FORMAT_MPEG1:
case DI_CTA_AUDIO_FORMAT_MP3:
case DI_CTA_AUDIO_FORMAT_MPEG2:
case DI_CTA_AUDIO_FORMAT_AAC_LC:
case DI_CTA_AUDIO_FORMAT_DTS:
case DI_CTA_AUDIO_FORMAT_ATRAC:
sad->max_bitrate_kbs = data[2] * 8;
break;
case DI_CTA_AUDIO_FORMAT_MPEGH_3D:
priv->mpegh_3d.low_complexity_profile = has_bit(data[2], 0);
priv->mpegh_3d.baseline_profile = has_bit(data[2], 1);
break;
case DI_CTA_AUDIO_FORMAT_ONE_BIT_AUDIO:
case DI_CTA_AUDIO_FORMAT_ENHANCED_AC3:
case DI_CTA_AUDIO_FORMAT_DTS_HD:
case DI_CTA_AUDIO_FORMAT_MAT:
case DI_CTA_AUDIO_FORMAT_DST:
case DI_CTA_AUDIO_FORMAT_WMA_PRO:
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC:
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_V2:
case DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC:
case DI_CTA_AUDIO_FORMAT_DRA:
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_MPEG_SURROUND:
case DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC_MPEG_SURROUND:
case DI_CTA_AUDIO_FORMAT_AC4:
break; /* TODO */
}
if ((format == DI_CTA_AUDIO_FORMAT_LPCM || format == DI_CTA_AUDIO_FORMAT_WMA_PRO) &&
get_bit_range(data[2], 7, 3) != 0)
add_failure_until(cta, 3, "Audio Data Block: Bits F33-F37 must be 0.");
assert(audio->sads_len < EDID_CTA_MAX_AUDIO_BLOCK_ENTRIES);
audio->sads[audio->sads_len++] = priv;
return true;
}
static bool
parse_audio_block(struct di_edid_cta *cta, struct di_cta_audio_block *audio,
const uint8_t *data, size_t size)
{
size_t i;
if (size % 3 != 0)
add_failure(cta, "Broken CTA-861 audio block length %d.", size);
for (i = 0; i + 3 <= size; i += 3) {
if (!parse_sad(cta, audio, &data[i]))
return false;
}
return true;
}
static bool static bool
parse_video_cap_block(struct di_edid_cta *cta, parse_video_cap_block(struct di_edid_cta *cta,
struct di_cta_video_cap_block *video_cap, struct di_cta_video_cap_block *video_cap,
@ -219,6 +459,7 @@ destroy_data_block(struct di_cta_data_block *data_block)
{ {
size_t i; size_t i;
struct di_cta_video_block *video; struct di_cta_video_block *video;
struct di_cta_audio_block *audio;
switch (data_block->tag) { switch (data_block->tag) {
case DI_CTA_DATA_BLOCK_VIDEO: case DI_CTA_DATA_BLOCK_VIDEO:
@ -226,6 +467,11 @@ destroy_data_block(struct di_cta_data_block *data_block)
for (i = 0; i < video->svds_len; i++) for (i = 0; i < video->svds_len; i++)
free(video->svds[i]); free(video->svds[i]);
break; break;
case DI_CTA_DATA_BLOCK_AUDIO:
audio = &data_block->audio;
for (i = 0; i < audio->sads_len; i++)
free(audio->sads[i]);
break;
default: default:
break; /* Nothing to do */ break; /* Nothing to do */
} }
@ -248,6 +494,8 @@ parse_data_block(struct di_edid_cta *cta, uint8_t raw_tag, const uint8_t *data,
switch (raw_tag) { switch (raw_tag) {
case 1: case 1:
tag = DI_CTA_DATA_BLOCK_AUDIO; tag = DI_CTA_DATA_BLOCK_AUDIO;
if (!parse_audio_block(cta, &data_block->audio, data, size))
goto error;
break; break;
case 2: case 2:
tag = DI_CTA_DATA_BLOCK_VIDEO; tag = DI_CTA_DATA_BLOCK_VIDEO;
@ -504,6 +752,15 @@ di_cta_data_block_get_svds(const struct di_cta_data_block *block)
return (const struct di_cta_svd *const *) block->video.svds; return (const struct di_cta_svd *const *) block->video.svds;
} }
const struct di_cta_sad *const *
di_cta_data_block_get_sads(const struct di_cta_data_block *block)
{
if (block->tag != DI_CTA_DATA_BLOCK_AUDIO) {
return NULL;
}
return (const struct di_cta_sad *const *) block->audio.sads;
}
const struct di_cta_colorimetry_block * const struct di_cta_colorimetry_block *
di_cta_data_block_get_colorimetry(const struct di_cta_data_block *block) di_cta_data_block_get_colorimetry(const struct di_cta_data_block *block)
{ {

View file

@ -574,6 +574,134 @@ printf_cta_svds(const struct di_cta_svd *const *svds)
} }
} }
static const char *
cta_audio_format_name(enum di_cta_audio_format format)
{
switch (format) {
case DI_CTA_AUDIO_FORMAT_LPCM:
return "Linear PCM";
case DI_CTA_AUDIO_FORMAT_AC3:
return "AC-3";
case DI_CTA_AUDIO_FORMAT_MPEG1:
return "MPEG 1 (Layers 1 & 2)";
case DI_CTA_AUDIO_FORMAT_MP3:
return "MPEG 1 Layer 3 (MP3)";
case DI_CTA_AUDIO_FORMAT_MPEG2:
return "MPEG2 (multichannel)";
case DI_CTA_AUDIO_FORMAT_AAC_LC:
return "AAC LC";
case DI_CTA_AUDIO_FORMAT_DTS:
return "DTS";
case DI_CTA_AUDIO_FORMAT_ATRAC:
return "ATRAC";
case DI_CTA_AUDIO_FORMAT_ONE_BIT_AUDIO:
return "One Bit Audio";
case DI_CTA_AUDIO_FORMAT_ENHANCED_AC3:
return "Enhanced AC-3 (DD+)";
case DI_CTA_AUDIO_FORMAT_DTS_HD:
return "DTS-HD";
case DI_CTA_AUDIO_FORMAT_MAT:
return "MAT (MLP)";
case DI_CTA_AUDIO_FORMAT_DST:
return "DST";
case DI_CTA_AUDIO_FORMAT_WMA_PRO:
return "WMA Pro";
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC:
return "MPEG-4 HE AAC";
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_V2:
return "MPEG-4 HE AAC v2";
case DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC:
return "MPEG-4 AAC LC";
case DI_CTA_AUDIO_FORMAT_DRA:
return "DRA";
case DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_MPEG_SURROUND:
return "MPEG-4 HE AAC + MPEG Surround";
case DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC_MPEG_SURROUND:
return "MPEG-4 AAC LC + MPEG Surround";
case DI_CTA_AUDIO_FORMAT_MPEGH_3D:
return "MPEG-H 3D Audio";
case DI_CTA_AUDIO_FORMAT_AC4:
return "AC-4";
case DI_CTA_AUDIO_FORMAT_LPCM_3D:
return "L-PCM 3D Audio";
}
abort();
}
static const char *
cta_sad_mpegh_3d_level_name(enum di_cta_sad_mpegh_3d_level level)
{
switch (level) {
case DI_CTA_SAD_MPEGH_3D_LEVEL_UNSPECIFIED:
return "Unspecified";
case DI_CTA_SAD_MPEGH_3D_LEVEL_1:
return "Level 1";
case DI_CTA_SAD_MPEGH_3D_LEVEL_2:
return "Level 2";
case DI_CTA_SAD_MPEGH_3D_LEVEL_3:
return "Level 3";
case DI_CTA_SAD_MPEGH_3D_LEVEL_4:
return "Level 4";
case DI_CTA_SAD_MPEGH_3D_LEVEL_5:
return "Level 5";
}
abort();
}
static void
print_cta_sads(const struct di_cta_sad *const *sads)
{
size_t i;
const struct di_cta_sad *sad;
for (i = 0; sads[i] != NULL; i++) {
sad = sads[i];
printf(" %s:\n", cta_audio_format_name(sad->format));
if (sad->max_channels != 0)
printf(" Max channels: %d\n", sad->max_channels);
if (sad->mpegh_3d)
printf(" MPEG-H 3D Audio Level: %s\n",
cta_sad_mpegh_3d_level_name(sad->mpegh_3d->level));
printf(" Supported sample rates (kHz):");
if (sad->supported_sample_rates->has_192_khz)
printf(" 192");
if (sad->supported_sample_rates->has_176_4_khz)
printf(" 176.4");
if (sad->supported_sample_rates->has_96_khz)
printf(" 96");
if (sad->supported_sample_rates->has_88_2_khz)
printf(" 88.2");
if (sad->supported_sample_rates->has_48_khz)
printf(" 48");
if (sad->supported_sample_rates->has_44_1_khz)
printf(" 44.1");
if (sad->supported_sample_rates->has_32_khz)
printf(" 32");
printf("\n");
if (sad->supported_sample_sizes) {
printf(" Supported sample sizes (bits):");
if (sad->supported_sample_sizes->has_24_bits)
printf(" 24");
if (sad->supported_sample_sizes->has_20_bits)
printf(" 20");
if (sad->supported_sample_sizes->has_16_bits)
printf(" 16");
printf("\n");
}
if (sad->max_bitrate_kbs != 0)
printf(" Maximum bit rate: %d kb/s\n", sad->max_bitrate_kbs);
if (sad->mpegh_3d && sad->mpegh_3d->low_complexity_profile)
printf(" Supports MPEG-H 3D Audio Low Complexity Profile\n");
if (sad->mpegh_3d && sad->mpegh_3d->baseline_profile)
printf(" Supports MPEG-H 3D Audio Baseline Profile\n");
}
}
static uint8_t static uint8_t
encode_max_luminance(float max) encode_max_luminance(float max)
{ {
@ -698,6 +826,7 @@ print_cta(const struct di_edid_cta *cta)
const struct di_cta_data_block *data_block; const struct di_cta_data_block *data_block;
enum di_cta_data_block_tag data_block_tag; enum di_cta_data_block_tag data_block_tag;
const struct di_cta_svd *const *svds; const struct di_cta_svd *const *svds;
const struct di_cta_sad *const *sads;
const struct di_cta_video_cap_block *video_cap; const struct di_cta_video_cap_block *video_cap;
const struct di_cta_colorimetry_block *colorimetry; const struct di_cta_colorimetry_block *colorimetry;
const struct di_cta_hdr_static_metadata_block *hdr_static_metadata; const struct di_cta_hdr_static_metadata_block *hdr_static_metadata;
@ -733,6 +862,10 @@ print_cta(const struct di_edid_cta *cta)
svds = di_cta_data_block_get_svds(data_block); svds = di_cta_data_block_get_svds(data_block);
printf_cta_svds(svds); printf_cta_svds(svds);
break; break;
case DI_CTA_DATA_BLOCK_AUDIO:
sads = di_cta_data_block_get_sads(data_block);
print_cta_sads(sads);
break;
case DI_CTA_DATA_BLOCK_VIDEO_CAP: case DI_CTA_DATA_BLOCK_VIDEO_CAP:
video_cap = di_cta_data_block_get_video_cap(data_block); video_cap = di_cta_data_block_get_video_cap(data_block);
printf(" YCbCr quantization: %s\n", printf(" YCbCr quantization: %s\n",

View file

@ -33,6 +33,13 @@
* is 63 bytes, and each SVD uses 1 byte. * is 63 bytes, and each SVD uses 1 byte.
*/ */
#define EDID_CTA_MAX_VIDEO_BLOCK_ENTRIES 63 #define EDID_CTA_MAX_VIDEO_BLOCK_ENTRIES 63
/**
* The maximum number of SAD entries in an audio data block.
*
* Each data block has its size described in a 5-bit field, so its maximum size
* is 63 bytes, and each SAD uses 3 bytes.
*/
#define EDID_CTA_MAX_AUDIO_BLOCK_ENTRIES 21
struct di_edid_cta { struct di_edid_cta {
int revision; int revision;
@ -61,11 +68,26 @@ struct di_cta_video_block {
size_t svds_len; size_t svds_len;
}; };
struct di_cta_sad_priv {
struct di_cta_sad base;
struct di_cta_sad_sample_rates supported_sample_rates;
struct di_cta_sad_sample_sizes supported_sample_sizes;
struct di_cta_sad_mpegh_3d mpegh_3d;
};
struct di_cta_audio_block {
/* NULL-terminated */
struct di_cta_sad_priv *sads[EDID_CTA_MAX_AUDIO_BLOCK_ENTRIES + 1];
size_t sads_len;
};
struct di_cta_data_block { struct di_cta_data_block {
enum di_cta_data_block_tag tag; enum di_cta_data_block_tag tag;
/* Used for DI_CTA_DATA_BLOCK_VIDEO */ /* Used for DI_CTA_DATA_BLOCK_VIDEO */
struct di_cta_video_block video; struct di_cta_video_block video;
/* used for DI_CTA_DATA_BLOCK_AUDIO */
struct di_cta_audio_block audio;
/* Used for DI_CTA_DATA_BLOCK_VIDEO_CAP */ /* Used for DI_CTA_DATA_BLOCK_VIDEO_CAP */
struct di_cta_video_cap_block video_cap; struct di_cta_video_cap_block video_cap;
/* Used for DI_CTA_DATA_BLOCK_COLORIMETRY */ /* Used for DI_CTA_DATA_BLOCK_COLORIMETRY */

View file

@ -117,6 +117,124 @@ enum di_cta_data_block_tag {
enum di_cta_data_block_tag enum di_cta_data_block_tag
di_cta_data_block_get_tag(const struct di_cta_data_block *block); di_cta_data_block_get_tag(const struct di_cta_data_block *block);
/**
* Audio formats, defined in tables 37 and 39.
*
* Note, the enum values don't match the specification.
*/
enum di_cta_audio_format {
/* L-PCM */
DI_CTA_AUDIO_FORMAT_LPCM = 1,
/* AC-3 */
DI_CTA_AUDIO_FORMAT_AC3,
/* MPEG-1 (layers 1 & 2) */
DI_CTA_AUDIO_FORMAT_MPEG1,
/* MP3 */
DI_CTA_AUDIO_FORMAT_MP3,
/* MPEG-2 */
DI_CTA_AUDIO_FORMAT_MPEG2,
/* AAC LC */
DI_CTA_AUDIO_FORMAT_AAC_LC,
/* DTS */
DI_CTA_AUDIO_FORMAT_DTS,
/* ATRAC */
DI_CTA_AUDIO_FORMAT_ATRAC,
/* One Bit Audio */
DI_CTA_AUDIO_FORMAT_ONE_BIT_AUDIO,
/* Enhanced AC-3 */
DI_CTA_AUDIO_FORMAT_ENHANCED_AC3,
/* DTS-HD and DTS-UHD */
DI_CTA_AUDIO_FORMAT_DTS_HD,
/* MAT */
DI_CTA_AUDIO_FORMAT_MAT,
/* DST */
DI_CTA_AUDIO_FORMAT_DST,
/* WMA Pro */
DI_CTA_AUDIO_FORMAT_WMA_PRO,
/* MPEG-4 HE AAC */
DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC,
/* MPEG-4 HE AAC v2 */
DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_V2,
/* MPEG-4 AAC LC */
DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC,
/* DRA */
DI_CTA_AUDIO_FORMAT_DRA,
/* MPEG-4 HE AAC + MPEG Surround */
DI_CTA_AUDIO_FORMAT_MPEG4_HE_AAC_MPEG_SURROUND,
/* MPEG-4 AAC LC + MPEG Surround */
DI_CTA_AUDIO_FORMAT_MPEG4_AAC_LC_MPEG_SURROUND,
/* MPEG-H 3D Audio */
DI_CTA_AUDIO_FORMAT_MPEGH_3D,
/* AC-4 */
DI_CTA_AUDIO_FORMAT_AC4,
/* L-PCM 3D Audio */
DI_CTA_AUDIO_FORMAT_LPCM_3D,
};
struct di_cta_sad_sample_rates {
bool has_192_khz; /* 192 kHz */
bool has_176_4_khz; /* 176.4 kHz */
bool has_96_khz; /* 96 kHz */
bool has_88_2_khz; /* 88.2 kHz */
bool has_48_khz; /* 48 kHz */
bool has_44_1_khz; /* 44.1 kHz */
bool has_32_khz; /* 32 kHz */
};
struct di_cta_sad_sample_sizes {
bool has_24_bits; /* 24 bits */
bool has_20_bits; /* 20 bits */
bool has_16_bits; /* 16 bits */
};
enum di_cta_sad_mpegh_3d_level {
DI_CTA_SAD_MPEGH_3D_LEVEL_UNSPECIFIED = 0,
DI_CTA_SAD_MPEGH_3D_LEVEL_1 = 1,
DI_CTA_SAD_MPEGH_3D_LEVEL_2 = 2,
DI_CTA_SAD_MPEGH_3D_LEVEL_3 = 3,
DI_CTA_SAD_MPEGH_3D_LEVEL_4 = 4,
DI_CTA_SAD_MPEGH_3D_LEVEL_5 = 5,
};
struct di_cta_sad_mpegh_3d {
/* Maximum supported MPEG-H 3D level, zero if unspecified */
enum di_cta_sad_mpegh_3d_level level;
/* True if MPEG-H 3D Audio Low Complexity Profile is supported */
bool low_complexity_profile;
/* True if MPEG-H 3D Audio Baseline Profile is supported */
bool baseline_profile;
};
/**
* A CTA short audio descriptor (SAD), defined in section 7.5.2.
*/
struct di_cta_sad {
/* Format */
enum di_cta_audio_format format;
/* Maximum number of channels, zero if unset */
int32_t max_channels;
/* Supported sample rates */
const struct di_cta_sad_sample_rates *supported_sample_rates;
/* Supported sample sizes, NULL if unset */
const struct di_cta_sad_sample_sizes *supported_sample_sizes;
/* Maximum bitrate (kb/s), zero if unset */
int32_t max_bitrate_kbs;
/* Additional metadata for MPEG-H 3D Audio, NULL unless format is
* DI_CTA_AUDIO_FORMAT_MPEGH_3D */
const struct di_cta_sad_mpegh_3d *mpegh_3d;
};
/**
* Get an array of short audio descriptors from a CTA data block.
*
* Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_AUDIO.
*
* The returned array is NULL-terminated.
*/
const struct di_cta_sad *const *
di_cta_data_block_get_sads(const struct di_cta_data_block *data_block);
/** /**
* Over- and underscan capability. * Over- and underscan capability.
*/ */

View file

@ -23,7 +23,7 @@
Detailed Timing Descriptors: Detailed Timing Descriptors:
DTD 1: 3840x2160 59.996625 Hz 16:9 133.312 kHz 533.250000 MHz (700 mm x 390 mm) DTD 1: 3840x2160 59.996625 Hz 16:9 133.312 kHz 533.250000 MHz (700 mm x 390 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P Hfront 48 Hsync 32 Hback 80 Hpol P
@@ -73,57 +73,32 @@ @@ -73,57 +73,36 @@
Supports YCbCr 4:2:2 Supports YCbCr 4:2:2
Native detailed modes: 1 Native detailed modes: 1
Video Data Block: Video Data Block:
@ -62,10 +62,10 @@
+ VIC 97 + VIC 97
+ VIC 96 + VIC 96
Audio Data Block: Audio Data Block:
- Linear PCM: Linear PCM:
- Max channels: 2 Max channels: 2
- Supported sample rates (kHz): 96 48 44.1 32 Supported sample rates (kHz): 96 48 44.1 32
- Supported sample sizes (bits): 24 20 16 Supported sample sizes (bits): 24 20 16
Speaker Allocation Data Block: Speaker Allocation Data Block:
- FL/FR - Front Left/Right - FL/FR - Front Left/Right
- Vendor-Specific Data Block (HDMI), OUI 00-0C-03: - Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
@ -98,7 +98,7 @@
HDR Static Metadata Data Block: HDR Static Metadata Data Block:
Electro optical transfer functions: Electro optical transfer functions:
Traditional gamma - SDR luminance range Traditional gamma - SDR luminance range
@@ -133,7 +108,6 @@ @@ -133,7 +112,6 @@
Static metadata type 1 Static metadata type 1
Desired content max luminance: 92 (366.802 cd/m^2) Desired content max luminance: 92 (366.802 cd/m^2)
Desired content max frame-average luminance: 92 (366.802 cd/m^2) Desired content max frame-average luminance: 92 (366.802 cd/m^2)
@ -106,7 +106,7 @@
Detailed Timing Descriptors: Detailed Timing Descriptors:
DTD 2: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (700 mm x 390 mm) DTD 2: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (700 mm x 390 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P Hfront 48 Hsync 32 Hback 80 Hpol P
@@ -144,29 +118,12 @@ @@ -144,29 +122,12 @@
DTD 4: 1280x768 59.870228 Hz 5:3 47.776 kHz 79.500000 MHz (700 mm x 390 mm) DTD 4: 1280x768 59.870228 Hz 5:3 47.776 kHz 79.500000 MHz (700 mm x 390 mm)
Hfront 64 Hsync 128 Hback 192 Hpol N Hfront 64 Hsync 128 Hback 192 Hpol N
Vfront 3 Vsync 7 Vback 20 Vpol P Vfront 3 Vsync 7 Vback 20 Vpol P

View file

@ -9,14 +9,9 @@
Display Product Name: 'S27A950D' Display Product Name: 'S27A950D'
Extension blocks: 1 Extension blocks: 1
Checksum: 0x1b Checksum: 0x1b
@@ -41,29 +39,13 @@ @@ -46,24 +44,12 @@
Basic audio support Supported sample rates (kHz): 48 44.1 32
Native detailed modes: 0 Supported sample sizes (bits): 24 20 16
Audio Data Block:
- Linear PCM:
- Max channels: 2
- Supported sample rates (kHz): 48 44.1 32
- Supported sample sizes (bits): 24 20 16
Speaker Allocation Data Block: Speaker Allocation Data Block:
- FL/FR - Front Left/Right - FL/FR - Front Left/Right
-Checksum: 0x71 Unused space in Extension Block: 115 bytes -Checksum: 0x71 Unused space in Extension Block: 115 bytes

View file

@ -23,7 +23,7 @@
Detailed Timing Descriptors: Detailed Timing Descriptors:
DTD 1: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (597 mm x 336 mm) DTD 1: 2560x1440 59.950550 Hz 16:9 88.787 kHz 241.500000 MHz (597 mm x 336 mm)
Hfront 48 Hsync 32 Hback 80 Hpol P Hfront 48 Hsync 32 Hback 80 Hpol P
@@ -79,35 +79,29 @@ @@ -79,35 +79,33 @@
Supports YCbCr 4:2:2 Supports YCbCr 4:2:2
Native detailed modes: 1 Native detailed modes: 1
Video Data Block: Video Data Block:
@ -56,10 +56,10 @@
+ VIC 34 + VIC 34
+ VIC 1 + VIC 1
Audio Data Block: Audio Data Block:
- Linear PCM: Linear PCM:
- Max channels: 2 Max channels: 2
- Supported sample rates (kHz): 192 176.4 96 88.2 48 44.1 32 Supported sample rates (kHz): 192 176.4 96 88.2 48 44.1 32
- Supported sample sizes (bits): 24 20 16 Supported sample sizes (bits): 24 20 16
Speaker Allocation Data Block: Speaker Allocation Data Block:
- FL/FR - Front Left/Right - FL/FR - Front Left/Right
Detailed Timing Descriptors: Detailed Timing Descriptors:
@ -75,7 +75,7 @@
DTD 4: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz (597 mm x 336 mm) DTD 4: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz (597 mm x 336 mm)
Hfront 110 Hsync 40 Hback 220 Hpol P Hfront 110 Hsync 40 Hback 220 Hpol P
Vfront 5 Vsync 5 Vback 20 Vpol P Vfront 5 Vsync 5 Vback 20 Vpol P
@@ -117,28 +111,14 @@ @@ -117,28 +115,14 @@
DTD 6: 1920x1080 50.000000 Hz 16:9 56.250 kHz 148.500000 MHz (597 mm x 336 mm) DTD 6: 1920x1080 50.000000 Hz 16:9 56.250 kHz 148.500000 MHz (597 mm x 336 mm)
Hfront 528 Hsync 44 Hback 148 Hpol P Hfront 528 Hsync 44 Hback 148 Hpol P
Vfront 4 Vsync 5 Vback 36 Vpol P Vfront 4 Vsync 5 Vback 36 Vpol P