mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-20 13:06:23 +00:00
pbutils: AV1 mime codec
Add basic AV1 mime codec param generation based on the spec at https://aomediacodec.github.io/av1-isobmff/#codecsparam Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6696>
This commit is contained in:
parent
efba52fcba
commit
6fd1900d54
4 changed files with 507 additions and 5 deletions
|
@ -3147,6 +3147,34 @@ rate.</doc>
|
|||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="codec_utils_av1_get_level" c:identifier="gst_codec_utils_av1_get_level" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">Transform a seq_level_idx into the level string</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.h"/>
|
||||
<return-value transfer-ownership="none" nullable="1">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">the level string or %NULL if the seq_level_idx is unknown</doc>
|
||||
<type name="utf8" c:type="const gchar*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="seq_level_idx" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">A seq_level_idx</doc>
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="codec_utils_av1_get_seq_level_idx" c:identifier="gst_codec_utils_av1_get_seq_level_idx" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">Transform a level string from the caps into the seq_level_idx</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">the seq_level_idx or 31 (max-level) if the level is unknown</doc>
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="level" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">A level string from caps</doc>
|
||||
<type name="utf8" c:type="const gchar*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="codec_utils_caps_from_mime_codec" c:identifier="gst_codec_utils_caps_from_mime_codec" version="1.22">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-base/gst-libs/gst/pbutils/codec-utils.c">Converts a RFC 6381 compatible codec string to #GstCaps. More than one codec
|
||||
string can be present (separated by `,`).
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <gst/base/gstbitreader.h>
|
||||
#include <gst/tag/tag.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
|
@ -1543,6 +1544,142 @@ gst_codec_utils_h265_caps_set_level_tier_and_profile (GstCaps * caps,
|
|||
return (level != NULL && tier != NULL && profile != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_av1_get_seq_level_idx:
|
||||
* @level: A level string from caps
|
||||
*
|
||||
* Transform a level string from the caps into the seq_level_idx
|
||||
*
|
||||
* Returns: the seq_level_idx or 31 (max-level) if the level is unknown
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
guint8
|
||||
gst_codec_utils_av1_get_seq_level_idx (const gchar * level)
|
||||
{
|
||||
g_return_val_if_fail (level != NULL, 0);
|
||||
|
||||
if (!strcmp (level, "2.0"))
|
||||
return 0;
|
||||
else if (!strcmp (level, "2.1"))
|
||||
return 1;
|
||||
else if (!strcmp (level, "2.2"))
|
||||
return 2;
|
||||
else if (!strcmp (level, "2.3"))
|
||||
return 3;
|
||||
else if (!strcmp (level, "3.0"))
|
||||
return 4;
|
||||
else if (!strcmp (level, "3.1"))
|
||||
return 5;
|
||||
else if (!strcmp (level, "3.2"))
|
||||
return 6;
|
||||
else if (!strcmp (level, "3.3"))
|
||||
return 7;
|
||||
else if (!strcmp (level, "4.0"))
|
||||
return 8;
|
||||
else if (!strcmp (level, "4.1"))
|
||||
return 9;
|
||||
else if (!strcmp (level, "4.2"))
|
||||
return 10;
|
||||
else if (!strcmp (level, "4.3"))
|
||||
return 11;
|
||||
else if (!strcmp (level, "5.0"))
|
||||
return 12;
|
||||
else if (!strcmp (level, "5.1"))
|
||||
return 13;
|
||||
else if (!strcmp (level, "5.2"))
|
||||
return 14;
|
||||
else if (!strcmp (level, "5.3"))
|
||||
return 15;
|
||||
else if (!strcmp (level, "6.0"))
|
||||
return 16;
|
||||
else if (!strcmp (level, "6.1"))
|
||||
return 17;
|
||||
else if (!strcmp (level, "6.2"))
|
||||
return 18;
|
||||
else if (!strcmp (level, "6.3"))
|
||||
return 19;
|
||||
else if (!strcmp (level, "7.0"))
|
||||
return 20;
|
||||
else if (!strcmp (level, "7.1"))
|
||||
return 21;
|
||||
else if (!strcmp (level, "7.2"))
|
||||
return 22;
|
||||
else if (!strcmp (level, "7.3"))
|
||||
return 23;
|
||||
|
||||
GST_WARNING ("Invalid level %s", level);
|
||||
return 31;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_codec_utils_av1_get_level:
|
||||
* @seq_level_idx: A seq_level_idx
|
||||
*
|
||||
* Transform a seq_level_idx into the level string
|
||||
*
|
||||
* Returns: (nullable): the level string or %NULL if the seq_level_idx is unknown
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
const gchar *
|
||||
gst_codec_utils_av1_get_level (guint8 seq_level_idx)
|
||||
{
|
||||
switch (seq_level_idx) {
|
||||
case 0:
|
||||
return "2.0";
|
||||
case 1:
|
||||
return "2.1";
|
||||
case 2:
|
||||
return "2.2";
|
||||
case 3:
|
||||
return "2.3";
|
||||
case 4:
|
||||
return "3.0";
|
||||
case 5:
|
||||
return "3.1";
|
||||
case 6:
|
||||
return "3.2";
|
||||
case 7:
|
||||
return "3.3";
|
||||
case 8:
|
||||
return "4.0";
|
||||
case 9:
|
||||
return "4.1";
|
||||
case 10:
|
||||
return "4.2";
|
||||
case 11:
|
||||
return "4.3";
|
||||
case 12:
|
||||
return "5.0";
|
||||
case 13:
|
||||
return "5.1";
|
||||
case 14:
|
||||
return "5.2";
|
||||
case 15:
|
||||
return "5.3";
|
||||
case 16:
|
||||
return "6.0";
|
||||
case 17:
|
||||
return "6.1";
|
||||
case 18:
|
||||
return "6.2";
|
||||
case 19:
|
||||
return "6.3";
|
||||
case 20:
|
||||
return "7.0";
|
||||
case 21:
|
||||
return "7.1";
|
||||
case 22:
|
||||
return "7.2";
|
||||
case 23:
|
||||
return "7.3";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_codec_utils_mpeg4video_get_profile:
|
||||
* @vis_obj_seq: (array length=len): Pointer to the visual object
|
||||
|
@ -2555,6 +2692,256 @@ done:
|
|||
return g_string_free (codec_string, FALSE);
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
av1_caps_from_mime_codec (gchar ** subcodec)
|
||||
{
|
||||
GstCaps *caps = NULL;
|
||||
gchar tier;
|
||||
guint seq_level_idx_0;
|
||||
guint bit_depth, seq_profile, chroma_sample_position,
|
||||
monochrome, chroma_subsampling_x, chroma_subsampling_y, primaries,
|
||||
transfer, matrix, full_range, chroma_sampling;
|
||||
const gchar *level_str;
|
||||
const gchar *tier_str;
|
||||
const gchar *profile_str;
|
||||
const gchar *chroma_format_str;
|
||||
gchar *colorimetry_str;
|
||||
GstVideoColorimetry cinfo = { 0, };
|
||||
|
||||
caps = gst_caps_new_empty_simple ("video/x-av1");
|
||||
|
||||
if (!subcodec[1])
|
||||
goto done;
|
||||
|
||||
seq_profile = g_ascii_strtoull (subcodec[1], NULL, 10);
|
||||
if (seq_profile == 0) {
|
||||
profile_str = "main";
|
||||
} else if (seq_profile == 1) {
|
||||
profile_str = "high";
|
||||
} else if (seq_profile == 2) {
|
||||
profile_str = "professional";
|
||||
} else {
|
||||
GST_WARNING ("Unknown AV1 profile %d", seq_profile);
|
||||
goto done;
|
||||
}
|
||||
gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str, NULL);
|
||||
|
||||
if (subcodec[2]) {
|
||||
if (sscanf (subcodec[2], "%02u%c", &seq_level_idx_0, &tier) != 2) {
|
||||
GST_WARNING ("Failed to parse level and tier from %s", subcodec[2]);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
seq_level_idx_0 = 1;
|
||||
tier = 'M';
|
||||
}
|
||||
|
||||
if (tier == 'H') {
|
||||
tier_str = "high";
|
||||
} else if (tier == 'M') {
|
||||
tier_str = "main";
|
||||
} else {
|
||||
GST_WARNING ("Unknown AV1 tier %c", tier);
|
||||
goto done;
|
||||
}
|
||||
gst_caps_set_simple (caps, "tier", G_TYPE_STRING, tier_str, NULL);
|
||||
|
||||
level_str = gst_codec_utils_av1_get_level (seq_level_idx_0);
|
||||
if (level_str) {
|
||||
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_str, NULL);
|
||||
} else {
|
||||
GST_WARNING ("Unknown AV1 level %d", seq_level_idx_0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (subcodec[3]) {
|
||||
bit_depth = g_ascii_strtoull (subcodec[3], NULL, 10);
|
||||
gst_caps_set_simple (caps, "bit-depth-luma", G_TYPE_UINT, bit_depth,
|
||||
"bit-depth-chroma", G_TYPE_UINT, bit_depth, NULL);
|
||||
} else {
|
||||
GST_WARNING ("Failed to parse bit-depth from %s", subcodec[3]);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Verify if all values necessary to continue are present in the subcodec */
|
||||
if (subcodec[4] && subcodec[5] && subcodec[6]
|
||||
&& subcodec[7] && subcodec[8] && subcodec[9]) {
|
||||
|
||||
monochrome = g_ascii_strtoull (subcodec[4], NULL, 10);
|
||||
chroma_sampling = g_ascii_strtoull (subcodec[5], NULL, 10);
|
||||
chroma_subsampling_x = chroma_sampling / 100;
|
||||
chroma_subsampling_y = (chroma_sampling % 100) / 10;
|
||||
chroma_sample_position = chroma_sampling % 10;
|
||||
if (monochrome) {
|
||||
chroma_format_str = "4:0:0";
|
||||
} else if (chroma_subsampling_x == 1 && chroma_subsampling_y == 1) {
|
||||
chroma_format_str = "4:2:0";
|
||||
} else if (chroma_subsampling_x == 1 && chroma_subsampling_y == 0) {
|
||||
chroma_format_str = "4:2:2";
|
||||
} else if (chroma_subsampling_x == 0 && chroma_subsampling_y == 0) {
|
||||
chroma_format_str = "4:4:4";
|
||||
} else {
|
||||
GST_WARNING ("Unknown chroma subsampling %d:%d:%d", chroma_subsampling_x,
|
||||
chroma_subsampling_y, monochrome);
|
||||
goto done;
|
||||
}
|
||||
|
||||
primaries = g_ascii_strtoull (subcodec[6], NULL, 10);
|
||||
transfer = g_ascii_strtoull (subcodec[7], NULL, 10);
|
||||
matrix = g_ascii_strtoull (subcodec[8], NULL, 10);
|
||||
full_range = g_ascii_strtoull (subcodec[9], NULL, 10);
|
||||
} else {
|
||||
GST_DEBUG
|
||||
("Using default values for chroma_format, chroma_sample_position, "
|
||||
"primaries, transfer, matrix, and full_range");
|
||||
|
||||
chroma_format_str = "4:2:0";
|
||||
chroma_sample_position = 0;
|
||||
primaries = 1;
|
||||
transfer = 1;
|
||||
matrix = 1;
|
||||
full_range = 0;
|
||||
}
|
||||
|
||||
gst_caps_set_simple (caps, "chroma-format", G_TYPE_STRING, chroma_format_str,
|
||||
NULL);
|
||||
if (chroma_sample_position == 1) {
|
||||
gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING, "v-cosited", NULL);
|
||||
} else if (chroma_sample_position == 2) {
|
||||
gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
|
||||
"v-cosited+h-cosited", NULL);
|
||||
}
|
||||
|
||||
cinfo.range =
|
||||
full_range ? GST_VIDEO_COLOR_RANGE_0_255 : GST_VIDEO_COLOR_RANGE_16_235;
|
||||
cinfo.primaries = gst_video_color_primaries_from_iso (primaries);
|
||||
cinfo.transfer = gst_video_transfer_function_from_iso (transfer);
|
||||
cinfo.matrix = gst_video_color_matrix_from_iso (matrix);
|
||||
colorimetry_str = gst_video_colorimetry_to_string (&cinfo);
|
||||
if (colorimetry_str) {
|
||||
gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, colorimetry_str,
|
||||
NULL);
|
||||
} else {
|
||||
GST_WARNING ("Failed to parse colorimetry from %u %u %u %u", full_range,
|
||||
matrix, transfer, primaries);
|
||||
}
|
||||
g_free (colorimetry_str);
|
||||
|
||||
done:
|
||||
return caps;
|
||||
}
|
||||
|
||||
/* https://aomediacodec.github.io/av1-isobmff/#codecsparam */
|
||||
static char *
|
||||
av1_caps_get_mime_codec (GstCaps * caps)
|
||||
{
|
||||
gchar tier_mime;
|
||||
guint8 seq_level_idx_0;
|
||||
guint bit_depth, seq_profile, chroma_sample_position,
|
||||
monochrome, chroma_subsampling_x, chroma_subsampling_y, primaries,
|
||||
transfer, matrix, full_range;
|
||||
GstStructure *caps_st;
|
||||
GString *codec_string;
|
||||
const gchar *level_str;
|
||||
const gchar *tier_str;
|
||||
const gchar *profile_str;
|
||||
const gchar *chroma_format_str;
|
||||
const gchar *chroma_site_str;
|
||||
const gchar *colorimetry_str;
|
||||
GstVideoColorimetry cinfo = { 0, };
|
||||
|
||||
caps_st = gst_caps_get_structure (caps, 0);
|
||||
codec_string = g_string_new ("av01");
|
||||
|
||||
tier_str = gst_structure_get_string (caps_st, "tier");
|
||||
if (g_strcmp0 (tier_str, "main") == 0) {
|
||||
tier_mime = 'M';
|
||||
} else if (g_strcmp0 (tier_str, "high") == 0) {
|
||||
tier_mime = 'H';
|
||||
} else {
|
||||
GST_WARNING ("Unknown AV1 tier %s, using default 'M'", tier_str);
|
||||
tier_mime = 'M';
|
||||
}
|
||||
|
||||
level_str = gst_structure_get_string (caps_st, "level");
|
||||
if (level_str) {
|
||||
seq_level_idx_0 = gst_codec_utils_av1_get_seq_level_idx (level_str);
|
||||
} else {
|
||||
seq_level_idx_0 = 1;
|
||||
}
|
||||
|
||||
profile_str = gst_structure_get_string (caps_st, "profile");
|
||||
if (g_strcmp0 (profile_str, "main") == 0) {
|
||||
seq_profile = 0;
|
||||
} else if (g_strcmp0 (profile_str, "high") == 0) {
|
||||
seq_profile = 1;
|
||||
} else if (g_strcmp0 (profile_str, "professional") == 0) {
|
||||
seq_profile = 2;
|
||||
} else {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!gst_structure_get_uint (caps_st, "bit-depth-luma", &bit_depth))
|
||||
goto done;
|
||||
|
||||
/* We have all information to compute a minimal mime */
|
||||
g_string_append_printf (codec_string, ".%d.%02u%c.%02u",
|
||||
seq_profile, seq_level_idx_0, tier_mime, bit_depth);
|
||||
|
||||
chroma_format_str = gst_structure_get_string (caps_st, "chroma-format");
|
||||
if (g_strcmp0 (chroma_format_str, "4:0:0") == 0) {
|
||||
monochrome = 1;
|
||||
chroma_subsampling_x = 1;
|
||||
chroma_subsampling_y = 1;
|
||||
} else if (g_strcmp0 (chroma_format_str, "4:2:0") == 0) {
|
||||
monochrome = 0;
|
||||
chroma_subsampling_x = 1;
|
||||
chroma_subsampling_y = 1;
|
||||
} else if (g_strcmp0 (chroma_format_str, "4:2:2") == 0) {
|
||||
monochrome = 0;
|
||||
chroma_subsampling_x = 1;
|
||||
chroma_subsampling_y = 0;
|
||||
} else if (g_strcmp0 (chroma_format_str, "4:4:4") == 0) {
|
||||
monochrome = 0;
|
||||
chroma_subsampling_x = 0;
|
||||
chroma_subsampling_y = 0;
|
||||
} else {
|
||||
goto done;
|
||||
}
|
||||
|
||||
chroma_sample_position = 0;
|
||||
chroma_site_str = gst_structure_get_string (caps_st, "chroma-site");
|
||||
if (g_strcmp0 (chroma_site_str, "v-cosited") == 0) {
|
||||
chroma_sample_position = 1;
|
||||
} else if (g_strcmp0 (chroma_site_str, "v-cosited+h-cosited") == 0) {
|
||||
chroma_sample_position = 2;
|
||||
}
|
||||
|
||||
colorimetry_str = gst_structure_get_string (caps_st, "colorimetry");
|
||||
if (!colorimetry_str)
|
||||
goto done;
|
||||
if (!gst_video_colorimetry_from_string (&cinfo, colorimetry_str))
|
||||
goto done;
|
||||
full_range = cinfo.range == GST_VIDEO_COLOR_RANGE_0_255;
|
||||
|
||||
primaries = gst_video_color_primaries_to_iso (cinfo.primaries);
|
||||
transfer = gst_video_transfer_function_to_iso (cinfo.transfer);
|
||||
matrix = gst_video_color_matrix_to_iso (cinfo.matrix);
|
||||
|
||||
if (chroma_subsampling_x != 1 || chroma_subsampling_y != 1
|
||||
|| chroma_sample_position != 0 || primaries != 1 || transfer != 1
|
||||
|| matrix != 1 || full_range != 0) {
|
||||
g_string_append_printf (codec_string,
|
||||
".%u.%u%u%u.%02u.%02u.%02u.%u", monochrome, chroma_subsampling_x,
|
||||
chroma_subsampling_y, chroma_sample_position, primaries, transfer,
|
||||
matrix, full_range);
|
||||
}
|
||||
|
||||
done:
|
||||
return g_string_free (codec_string, FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_codec_utils_caps_get_mime_codec:
|
||||
* @caps: A #GstCaps to convert to mime codec
|
||||
|
@ -2612,10 +2999,7 @@ gst_codec_utils_caps_get_mime_codec (GstCaps * caps)
|
|||
mime_codec = g_strdup ("hev1");
|
||||
}
|
||||
} else if (g_strcmp0 (media_type, "video/x-av1") == 0) {
|
||||
/* TODO: Some browsers won't play the video unless more codec information is
|
||||
* available in the mime codec for av1. This is documented in
|
||||
* https://aomediacodec.github.io/av1-isobmff/#codecsparam */
|
||||
mime_codec = g_strdup ("av01");
|
||||
mime_codec = av1_caps_get_mime_codec (caps);
|
||||
} else if (g_strcmp0 (media_type, "video/x-vp8") == 0) {
|
||||
/* TODO: most browsers won't play the video unless more codec information is
|
||||
* available in the mime codec for vp8. */
|
||||
|
@ -2812,9 +3196,11 @@ gst_codec_utils_caps_from_mime_codec_single (const gchar * codec)
|
|||
caps = gst_caps_new_empty_simple ("video/x-vp9");
|
||||
break;
|
||||
case GST_MAKE_FOURCC ('a', 'v', '0', '1'):
|
||||
{
|
||||
/* AV1 */
|
||||
caps = gst_caps_new_empty_simple ("video/x-av1");
|
||||
caps = av1_caps_from_mime_codec (subcodec);
|
||||
break;
|
||||
}
|
||||
case GST_MAKE_FOURCC ('o', 'p', 'u', 's'):
|
||||
/* Opus */
|
||||
caps = gst_caps_new_empty_simple ("audio/x-opus");
|
||||
|
|
|
@ -96,6 +96,15 @@ GST_PBUTILS_API
|
|||
gboolean gst_codec_utils_h265_caps_set_level_tier_and_profile (GstCaps * caps,
|
||||
const guint8 * profile_tier_level,
|
||||
guint len);
|
||||
|
||||
/* AV1 */
|
||||
|
||||
GST_PBUTILS_API
|
||||
guint8 gst_codec_utils_av1_get_seq_level_idx (const gchar * level);
|
||||
|
||||
GST_PBUTILS_API
|
||||
const gchar * gst_codec_utils_av1_get_level (guint8 seq_level_idx);
|
||||
|
||||
/* MPEG-4 part 2 */
|
||||
|
||||
GST_PBUTILS_API
|
||||
|
|
|
@ -1475,6 +1475,50 @@ GST_START_TEST (test_pb_utils_caps_mime_codec)
|
|||
g_free (mime_codec);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* av1 with default chroma subsampling, color primaries, color transfer,
|
||||
* color matrix and luma/chroma encoded*/
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("video/x-av1, stream-format=(string)obu-stream, alignment=(string)tu, profile=(string)main, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)bt709");
|
||||
mime_codec = gst_codec_utils_caps_get_mime_codec (caps);
|
||||
fail_unless_equals_string (mime_codec, "av01.0.01M.08");
|
||||
g_free (mime_codec);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* av1 with non-default chroma subsampling */
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("video/x-av1, stream-format=(string)obu-stream, alignment=(string)tu, profile=(string)main, width=(int)640, height=(int)480, "
|
||||
"pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, chroma-format=(string)4:2:2, bit-depth-luma=(uint)8, "
|
||||
"colorimetry=(string)bt709");
|
||||
mime_codec = gst_codec_utils_caps_get_mime_codec (caps);
|
||||
fail_unless_equals_string (mime_codec, "av01.0.01M.08.0.100.01.01.01.0");
|
||||
g_free (mime_codec);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* av1 with non-default level and tier */
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("video/x-av1, stream-format=(string)obu-stream, alignment=(string)tu, profile=(string)main, width=(int)640, height=(int)480, "
|
||||
"pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, chroma-format=(string)4:2:2, bit-depth-luma=(uint)8, "
|
||||
"colorimetry=(string)bt709, tier=(string)high, level=(string)3.0");
|
||||
mime_codec = gst_codec_utils_caps_get_mime_codec (caps);
|
||||
fail_unless_equals_string (mime_codec, "av01.0.04H.08.0.100.01.01.01.0");
|
||||
g_free (mime_codec);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* av1 with missing colorimetry */
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("video/x-av1, stream-format=(string)obu-stream, alignment=(string)tu, profile=(string)main, width=(int)640, height=(int)480, "
|
||||
"pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1, "
|
||||
"chroma-format=(string)4:2:2, bit-depth-luma=(uint)8, "
|
||||
"bit-depth-chroma=(uint)8, tier=(string)main, level=(string)5.0");
|
||||
mime_codec = gst_codec_utils_caps_get_mime_codec (caps);
|
||||
fail_unless_equals_string (mime_codec, "av01.0.12M.08");
|
||||
g_free (mime_codec);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* vp8 */
|
||||
caps = gst_caps_new_empty_simple ("video/x-vp8");
|
||||
mime_codec = gst_codec_utils_caps_get_mime_codec (caps);
|
||||
|
@ -1581,6 +1625,40 @@ GST_START_TEST (test_pb_utils_caps_mime_codec)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_pb_utils_caps_from_mime_codec)
|
||||
{
|
||||
GstCaps *caps = NULL;
|
||||
gchar *caps_str = NULL;
|
||||
|
||||
/* AV1 minimal caps */
|
||||
caps = gst_codec_utils_caps_from_mime_codec ("av01");
|
||||
caps_str = gst_caps_to_string (caps);
|
||||
fail_unless_equals_string (caps_str, "video/x-av1");
|
||||
gst_caps_unref (caps);
|
||||
g_free (caps_str);
|
||||
|
||||
/* AV1 with default chroma subsampling, color primaries, color transfer,
|
||||
* color matrix and luma/chroma encoded */
|
||||
caps = gst_codec_utils_caps_from_mime_codec ("av01.0.01M.08");
|
||||
caps_str = gst_caps_to_string (caps);
|
||||
fail_unless_equals_string (caps_str,
|
||||
"video/x-av1, profile=(string)main, tier=(string)main, level=(string)2.1, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, chroma-format=(string)4:2:0, colorimetry=(string)bt709");
|
||||
gst_caps_unref (caps);
|
||||
g_free (caps_str);
|
||||
|
||||
/* av1 with non-default chroma subsampling */
|
||||
caps =
|
||||
gst_codec_utils_caps_from_mime_codec ("av01.0.01M.08.0.100.01.01.01.0");
|
||||
caps_str = gst_caps_to_string (caps);
|
||||
fail_unless_equals_string (caps_str,
|
||||
("video/x-av1, profile=(string)main, tier=(string)main, level=(string)2.1, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, chroma-format=(string)4:2:2, colorimetry=(string)bt709"));
|
||||
gst_caps_unref (caps);
|
||||
g_free (caps_str);
|
||||
|
||||
};
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
libgstpbutils_suite (void)
|
||||
{
|
||||
|
@ -1603,6 +1681,7 @@ libgstpbutils_suite (void)
|
|||
tcase_add_test (tc_chain, test_pb_utils_h264_get_profile_flags_level);
|
||||
tcase_add_test (tc_chain, test_pb_utils_h265_profiles);
|
||||
tcase_add_test (tc_chain, test_pb_utils_caps_mime_codec);
|
||||
tcase_add_test (tc_chain, test_pb_utils_caps_from_mime_codec);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue