mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-21 17:21:13 +00:00
mpegts: Add support for JPEG-XS
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7172>
This commit is contained in:
parent
838ad5c7e4
commit
2e8afcf51a
13 changed files with 822 additions and 7 deletions
|
@ -1311,6 +1311,20 @@ two bytes are the @tag and @length.</doc>
|
|||
<type name="gpointer" c:type="gpointer"/>
|
||||
</array>
|
||||
</field>
|
||||
<method name="copy" c:identifier="gst_mpegts_descriptor_copy" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Copy the given descriptor.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="full">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A copy of @desc.</doc>
|
||||
<type name="Descriptor" c:type="GstMpegtsDescriptor*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="desc" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A #GstMpegtsDescriptor:</doc>
|
||||
<type name="Descriptor" c:type="GstMpegtsDescriptor*"/>
|
||||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="free" c:identifier="gst_mpegts_descriptor_free">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Frees @desc</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
|
@ -2047,6 +2061,24 @@ ISO 639-1 language code from the returned ISO 639-2 one.</doc>
|
|||
</instance-parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="parse_jpeg_xs" c:identifier="gst_mpegts_descriptor_parse_jpeg_xs" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Parses the JPEG-XS descriptor information from @descriptor:</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">TRUE if the information could be parsed, else FALSE.</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<instance-parameter name="descriptor" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A #GstMpegtsDescriptor</doc>
|
||||
<type name="Descriptor" c:type="const GstMpegtsDescriptor*"/>
|
||||
</instance-parameter>
|
||||
<parameter name="res" direction="out" caller-allocates="1" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A parsed #GstMpegtsJpegXsDescriptor</doc>
|
||||
<type name="JpegXsDescriptor" c:type="GstMpegtsJpegXsDescriptor*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="parse_logical_channel" c:identifier="gst_mpegts_descriptor_parse_logical_channel">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Extracts the logical channels from @descriptor.</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
|
@ -2310,6 +2342,20 @@ a single language</doc>
|
|||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="from_jpeg_xs" c:identifier="gst_mpegts_descriptor_from_jpeg_xs" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Create a new #GstMpegtsDescriptor based on the information in @jpegxs</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="full">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">The #GstMpegtsDescriptor</doc>
|
||||
<type name="Descriptor" c:type="GstMpegtsDescriptor*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="jpegxs" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A #GstMpegtsJpegXsDescriptor</doc>
|
||||
<type name="JpegXsDescriptor" c:type="const GstMpegtsJpegXsDescriptor*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="from_metadata" c:identifier="gst_mpegts_descriptor_from_metadata" version="1.26">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="full">
|
||||
|
@ -2799,6 +2845,94 @@ Consult the relevant specifications for more details.</doc>
|
|||
<member name="visual_impaired_commentary" value="3" c:identifier="GST_MPEGTS_AUDIO_TYPE_VISUAL_IMPAIRED_COMMENTARY">
|
||||
</member>
|
||||
</enumeration>
|
||||
<record name="JpegXsDescriptor" c:type="GstMpegtsJpegXsDescriptor" version="1.26" glib:type-name="GstMpegtsJpegXsDescriptor" glib:get-type="gst_mpegts_jpeg_xs_descriptor_get_type" c:symbol-prefix="jpeg_xs_descriptor">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h">JPEG-XS descriptor</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<field name="descriptor_version" writable="1">
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</field>
|
||||
<field name="horizontal_size" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="vertical_size" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="brat" writable="1">
|
||||
<type name="guint32" c:type="guint32"/>
|
||||
</field>
|
||||
<field name="frat" writable="1">
|
||||
<type name="guint32" c:type="guint32"/>
|
||||
</field>
|
||||
<field name="schar" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Ppih" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Plev" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="max_buffer_size" writable="1">
|
||||
<type name="guint32" c:type="guint32"/>
|
||||
</field>
|
||||
<field name="buffer_model_type" writable="1">
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</field>
|
||||
<field name="colour_primaries" writable="1">
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</field>
|
||||
<field name="transfer_characteristics" writable="1">
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</field>
|
||||
<field name="matrix_coefficients" writable="1">
|
||||
<type name="guint8" c:type="guint8"/>
|
||||
</field>
|
||||
<field name="video_full_range_flag" writable="1">
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</field>
|
||||
<field name="still_mode" writable="1">
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</field>
|
||||
<field name="mdm_flag" writable="1">
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</field>
|
||||
<field name="X_c0" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Y_c0" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="X_c1" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Y_c1" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="X_c2" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Y_c2" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="X_wp" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="Y_wp" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="L_max" writable="1">
|
||||
<type name="guint32" c:type="guint32"/>
|
||||
</field>
|
||||
<field name="L_min" writable="1">
|
||||
<type name="guint32" c:type="guint32"/>
|
||||
</field>
|
||||
<field name="MaxCLL" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
<field name="MaxFALL" writable="1">
|
||||
<type name="guint16" c:type="guint16"/>
|
||||
</field>
|
||||
</record>
|
||||
<record name="LogicalChannel" c:type="GstMpegtsLogicalChannel" glib:type-name="GstMpegtsLogicalChannel" glib:get-type="gst_mpegts_logical_channel_get_type" c:symbol-prefix="logical_channel">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<field name="service_id" writable="1">
|
||||
|
@ -4746,6 +4880,9 @@ profiles defined in Annex A for service-compatible stereoscopic 3D services</doc
|
|||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtssection.h">Rec. ITU-T H.265 | ISO/IEC 23008-2 video
|
||||
stream or an HEVC temporal video sub-bitstream</doc>
|
||||
</member>
|
||||
<member name="video_jpeg_xs" value="50" c:identifier="GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtssection.h">JPEG-XS stream type</doc>
|
||||
</member>
|
||||
<member name="ipmp_stream" value="127" c:identifier="GST_MPEGTS_STREAM_TYPE_IPMP_STREAM">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtssection.h">IPMP stream</doc>
|
||||
</member>
|
||||
|
@ -5091,6 +5228,20 @@ a single language</doc>
|
|||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="descriptor_from_jpeg_xs" c:identifier="gst_mpegts_descriptor_from_jpeg_xs" moved-to="Descriptor.from_jpeg_xs" version="1.26">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">Create a new #GstMpegtsDescriptor based on the information in @jpegxs</doc>
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="full">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">The #GstMpegtsDescriptor</doc>
|
||||
<type name="Descriptor" c:type="GstMpegtsDescriptor*"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
<parameter name="jpegxs" transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.c">A #GstMpegtsJpegXsDescriptor</doc>
|
||||
<type name="JpegXsDescriptor" c:type="const GstMpegtsJpegXsDescriptor*"/>
|
||||
</parameter>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="descriptor_from_metadata" c:identifier="gst_mpegts_descriptor_from_metadata" moved-to="Descriptor.from_metadata" version="1.26">
|
||||
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/mpegts/gstmpegtsdescriptor.h"/>
|
||||
<return-value transfer-ownership="full">
|
||||
|
|
|
@ -220605,7 +220605,7 @@
|
|||
"presence": "sometimes"
|
||||
},
|
||||
"video_%%01x_%%05x": {
|
||||
"caps": "video/mpeg:\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-h264:\n stream-format: byte-stream\nvideo/x-h265:\n stream-format: byte-stream\nvideo/x-dirac:\nvideo/x-cavs:\nvideo/x-wmv:\n wmvversion: 3\n format: WVC1\nimage/x-jpc:\n",
|
||||
"caps": "video/mpeg:\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-h264:\n stream-format: byte-stream\nvideo/x-h265:\n stream-format: byte-stream\nvideo/x-dirac:\nvideo/x-cavs:\nvideo/x-wmv:\n wmvversion: 3\n format: WVC1\nimage/x-jpc:\nimage/x-jxsc:\n",
|
||||
"direction": "src",
|
||||
"presence": "sometimes"
|
||||
}
|
||||
|
@ -220863,7 +220863,7 @@
|
|||
"long-name": "MPEG Transport Stream Muxer",
|
||||
"pad-templates": {
|
||||
"sink_%%d": {
|
||||
"caps": "video/mpeg:\n parsed: true\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-dirac:\nimage/x-jpc:\n alignment: frame\nvideo/x-h264:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\nvideo/x-h265:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\naudio/mpeg:\n parsed: true\n mpegversion: 1\naudio/mpeg:\n framed: true\n mpegversion: { (int)2, (int)4 }\n stream-format: { (string)adts, (string)raw }\naudio/x-lpcm:\n width: { (int)16, (int)20, (int)24 }\n rate: { (int)48000, (int)96000 }\n channels: [ 1, 8 ]\n dynamic_range: [ 0, 255 ]\n emphasis: { (boolean)false, (boolean)true }\n mute: { (boolean)false, (boolean)true }\naudio/x-ac3:\n framed: true\naudio/x-dts:\n framed: true\naudio/x-opus:\n channels: [ 1, 255 ]\nsubpicture/x-dvb:\napplication/x-teletext:\nmeta/x-klv:\n parsed: true\nmeta/x-id3:\n parsed: true\nimage/x-jpc:\n alignment: frame\n profile: [ 0, 49151 ]\n",
|
||||
"caps": "video/mpeg:\n parsed: true\n mpegversion: { (int)1, (int)2, (int)4 }\n systemstream: false\nvideo/x-dirac:\nimage/x-jpc:\n alignment: frame\nvideo/x-h264:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\nvideo/x-h265:\n stream-format: byte-stream\n alignment: { (string)au, (string)nal }\naudio/mpeg:\n parsed: true\n mpegversion: 1\naudio/mpeg:\n framed: true\n mpegversion: { (int)2, (int)4 }\n stream-format: { (string)adts, (string)raw }\naudio/x-lpcm:\n width: { (int)16, (int)20, (int)24 }\n rate: { (int)48000, (int)96000 }\n channels: [ 1, 8 ]\n dynamic_range: [ 0, 255 ]\n emphasis: { (boolean)false, (boolean)true }\n mute: { (boolean)false, (boolean)true }\naudio/x-ac3:\n framed: true\naudio/x-dts:\n framed: true\naudio/x-opus:\n channels: [ 1, 255 ]\nsubpicture/x-dvb:\napplication/x-teletext:\nmeta/x-klv:\n parsed: true\nmeta/x-id3:\n parsed: true\nimage/x-jpc:\n alignment: frame\n profile: [ 0, 49151 ]\nimage/x-jxsc:\n alignment: frame\n sampling: { (string)YCbCr-4:2:2, (string)YCbCr-4:4:4 }\n",
|
||||
"direction": "sink",
|
||||
"presence": "request",
|
||||
"type": "GstBaseTsMuxPad"
|
||||
|
|
|
@ -696,8 +696,18 @@ _new_descriptor_with_extension (guint8 tag, guint8 tag_extension, guint8 length)
|
|||
return descriptor;
|
||||
}
|
||||
|
||||
static GstMpegtsDescriptor *
|
||||
_copy_descriptor (GstMpegtsDescriptor * desc)
|
||||
/**
|
||||
* gst_mpegts_descriptor_copy:
|
||||
* @desc: (transfer none): A #GstMpegtsDescriptor:
|
||||
*
|
||||
* Copy the given descriptor.
|
||||
*
|
||||
* Returns: (transfer full): A copy of @desc.
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
GstMpegtsDescriptor *
|
||||
gst_mpegts_descriptor_copy (GstMpegtsDescriptor * desc)
|
||||
{
|
||||
GstMpegtsDescriptor *copy;
|
||||
|
||||
|
@ -721,7 +731,7 @@ gst_mpegts_descriptor_free (GstMpegtsDescriptor * desc)
|
|||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegtsDescriptor, gst_mpegts_descriptor,
|
||||
(GBoxedCopyFunc) _copy_descriptor,
|
||||
(GBoxedCopyFunc) gst_mpegts_descriptor_copy,
|
||||
(GBoxedFreeFunc) gst_mpegts_descriptor_free);
|
||||
|
||||
/**
|
||||
|
@ -1544,3 +1554,167 @@ gst_mpegts_descriptor_from_metadata_pointer (const
|
|||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
DEFINE_STATIC_COPY_FUNCTION (GstMpegtsJpegXsDescriptor,
|
||||
gst_mpegts_jpeg_xs_descriptor);
|
||||
DEFINE_STATIC_FREE_FUNCTION (GstMpegtsJpegXsDescriptor,
|
||||
gst_mpegts_jpeg_xs_descriptor);
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegtsJpegXsDescriptor, gst_mpegts_jpeg_xs_descriptor,
|
||||
(GBoxedCopyFunc) _gst_mpegts_jpeg_xs_descriptor_copy,
|
||||
(GFreeFunc) _gst_mpegts_jpeg_xs_descriptor_free);
|
||||
|
||||
/**
|
||||
* gst_mpegts_descriptor_parse_jpeg_xs:
|
||||
* @descriptor: A #GstMpegtsDescriptor
|
||||
* @res: (out): A parsed #GstMpegtsJpegXsDescriptor
|
||||
*
|
||||
* Parses the JPEG-XS descriptor information from @descriptor:
|
||||
*
|
||||
* Returns: TRUE if the information could be parsed, else FALSE.
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
|
||||
gboolean
|
||||
gst_mpegts_descriptor_parse_jpeg_xs (const GstMpegtsDescriptor * descriptor,
|
||||
GstMpegtsJpegXsDescriptor * res)
|
||||
{
|
||||
GstByteReader br;
|
||||
guint8 flags;
|
||||
g_return_val_if_fail (descriptor != NULL && res != NULL, FALSE);
|
||||
|
||||
/* The smallest jpegxs descriptor doesn't contain the MDM, but is an H.222.0 extension (so additional one byte) */
|
||||
__common_desc_ext_checks (descriptor, GST_MTS_DESC_EXT_JXS_VIDEO, 32, FALSE);
|
||||
|
||||
/* Skip tag/length/extension/tag/length */
|
||||
gst_byte_reader_init (&br, descriptor->data + 5, descriptor->length - 3);
|
||||
memset (res, 0, sizeof (*res));
|
||||
|
||||
/* First part can be scanned out with unchecked reader */
|
||||
res->descriptor_version = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
if (res->descriptor_version != 0) {
|
||||
GST_WARNING ("Unsupported JPEG-XS descriptor version (%d != 0)",
|
||||
res->descriptor_version);
|
||||
return FALSE;
|
||||
}
|
||||
res->horizontal_size = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->vertical_size = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->brat = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
res->frat = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
res->schar = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Ppih = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Plev = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->max_buffer_size = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
res->buffer_model_type = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
res->colour_primaries = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
res->transfer_characteristics = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
res->matrix_coefficients = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
|
||||
res->video_full_range_flag =
|
||||
(gst_byte_reader_get_uint8_unchecked (&br) & 0x80) == 0x80;
|
||||
flags = gst_byte_reader_get_uint8_unchecked (&br);
|
||||
res->still_mode = flags >> 7;
|
||||
if ((flags & 0x40) == 0x40) {
|
||||
if (gst_byte_reader_get_remaining (&br) < 28) {
|
||||
GST_ERROR ("MDM present on JPEG-XS descriptor but not enough bytes");
|
||||
return FALSE;
|
||||
}
|
||||
res->X_c0 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Y_c0 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->X_c1 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Y_c1 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->X_c2 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Y_c2 = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->X_wp = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->Y_wp = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->L_max = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
res->L_min = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
res->MaxCLL = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
res->MaxFALL = gst_byte_reader_get_uint16_be_unchecked (&br);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_mpegts_descriptor_from_jpeg_xs:
|
||||
* @jpegxs: A #GstMpegtsJpegXsDescriptor
|
||||
*
|
||||
* Create a new #GstMpegtsDescriptor based on the information in @jpegxs
|
||||
*
|
||||
* Returns: (transfer full): The #GstMpegtsDescriptor
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
GstMpegtsDescriptor *
|
||||
gst_mpegts_descriptor_from_jpeg_xs (const GstMpegtsJpegXsDescriptor * jpegxs)
|
||||
{
|
||||
gsize desc_size = 30;
|
||||
GstByteWriter writer;
|
||||
guint8 *desc_data;
|
||||
GstMpegtsDescriptor *descriptor;
|
||||
|
||||
/* Extension descriptor
|
||||
* tag/length are take care of by gst_mpegts_descriptor_from_custom
|
||||
* The size of the "internal" descriptor (in the extension) is 1 (for the extension_descriptor_tag) and 29 for JXS_video_descriptor
|
||||
*/
|
||||
|
||||
gst_byte_writer_init_with_size (&writer, desc_size, FALSE);
|
||||
|
||||
/* extension tag */
|
||||
gst_byte_writer_put_uint8 (&writer, GST_MTS_DESC_EXT_JXS_VIDEO);
|
||||
/* tag/length again */
|
||||
gst_byte_writer_put_uint8 (&writer, GST_MTS_DESC_EXT_JXS_VIDEO);
|
||||
/* Size is 27 (29 minus 2 initial bytes for tag/length */
|
||||
gst_byte_writer_put_uint8 (&writer, 27);
|
||||
/* descriptor version: 0 */
|
||||
gst_byte_writer_put_uint8 (&writer, 0);
|
||||
/* horizontal/vertical size */
|
||||
gst_byte_writer_put_uint16_be (&writer, jpegxs->horizontal_size);
|
||||
gst_byte_writer_put_uint16_be (&writer, jpegxs->vertical_size);
|
||||
/* brat/frat */
|
||||
gst_byte_writer_put_uint32_be (&writer, jpegxs->brat);
|
||||
gst_byte_writer_put_uint32_be (&writer, jpegxs->frat);
|
||||
|
||||
/* schar, Ppih, Plev */
|
||||
gst_byte_writer_put_uint16_be (&writer, jpegxs->schar);
|
||||
gst_byte_writer_put_uint16_be (&writer, jpegxs->Ppih);
|
||||
gst_byte_writer_put_uint16_be (&writer, jpegxs->Plev);
|
||||
|
||||
gst_byte_writer_put_uint32_be (&writer, jpegxs->max_buffer_size);
|
||||
|
||||
/* Buffer model type */
|
||||
gst_byte_writer_put_uint8 (&writer, jpegxs->buffer_model_type);
|
||||
|
||||
/* color_primaries */
|
||||
gst_byte_writer_put_uint8 (&writer, jpegxs->colour_primaries);
|
||||
|
||||
/* transfer_characteristics */
|
||||
gst_byte_writer_put_uint8 (&writer, jpegxs->transfer_characteristics);
|
||||
|
||||
/* matrix_coefficients */
|
||||
gst_byte_writer_put_uint8 (&writer, jpegxs->matrix_coefficients);
|
||||
|
||||
/* video_full_range_flag */
|
||||
gst_byte_writer_put_uint8 (&writer,
|
||||
jpegxs->video_full_range_flag ? 1 << 7 : 0);
|
||||
|
||||
/* still_mode_flag : off
|
||||
* mdm_flag : off */
|
||||
gst_byte_writer_put_uint8 (&writer, jpegxs->still_mode ? 1 : 0);
|
||||
|
||||
if (jpegxs->mdm_flag) {
|
||||
GST_ERROR ("Mastering Display Metadata not supported yet !");
|
||||
}
|
||||
|
||||
desc_size = gst_byte_writer_get_size (&writer);
|
||||
desc_data = gst_byte_writer_reset_and_get_data (&writer);
|
||||
|
||||
descriptor =
|
||||
gst_mpegts_descriptor_from_custom (GST_MTS_DESC_EXTENSION, desc_data,
|
||||
desc_size);
|
||||
g_free (desc_data);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
|
|
@ -226,6 +226,9 @@ struct _GstMpegtsDescriptor
|
|||
GST_MPEGTS_API
|
||||
void gst_mpegts_descriptor_free (GstMpegtsDescriptor *desc);
|
||||
|
||||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor * gst_mpegts_descriptor_copy (GstMpegtsDescriptor *desc);
|
||||
|
||||
GST_MPEGTS_API
|
||||
GPtrArray *gst_mpegts_parse_descriptors (guint8 * buffer, gsize buf_len);
|
||||
|
||||
|
@ -663,6 +666,55 @@ GType gst_mpegts_metadata_pointer_descriptor_get_type(void);
|
|||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor *gst_mpegts_descriptor_from_metadata_pointer(const GstMpegtsMetadataPointerDescriptor *metadata_pointer_descriptor);
|
||||
|
||||
/* JPEG-XS descriptor */
|
||||
|
||||
/**
|
||||
* GstMpegtsJpegXsDescriptor:
|
||||
*
|
||||
* JPEG-XS descriptor
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
|
||||
typedef struct _GstMpegtsJpegXsDescriptor {
|
||||
guint8 descriptor_version;
|
||||
guint16 horizontal_size, vertical_size;
|
||||
guint32 brat, frat;
|
||||
guint16 schar, Ppih, Plev;
|
||||
guint32 max_buffer_size;
|
||||
guint8 buffer_model_type;
|
||||
guint8 colour_primaries;
|
||||
guint8 transfer_characteristics;
|
||||
guint8 matrix_coefficients;
|
||||
gboolean video_full_range_flag;
|
||||
gboolean still_mode;
|
||||
gboolean mdm_flag;
|
||||
guint16 X_c0, Y_c0, X_c1, Y_c1, X_c2, Y_c2;
|
||||
guint16 X_wp, Y_wp;
|
||||
guint32 L_max, L_min;
|
||||
guint16 MaxCLL, MaxFALL;
|
||||
} GstMpegtsJpegXsDescriptor;
|
||||
|
||||
/**
|
||||
* GST_TYPE_MPEGTS_JPEG_XS_DESCRIPTOR:
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
#define GST_TYPE_MPEGTS_JPEG_XS_DESCRIPTOR \
|
||||
(gst_mpegts_jpeg_xs_descriptor_get_type())
|
||||
|
||||
GST_MPEGTS_API
|
||||
GType gst_mpegts_jpeg_xs_descriptor_get_type(void);
|
||||
|
||||
GST_MPEGTS_API
|
||||
gboolean
|
||||
gst_mpegts_descriptor_parse_jpeg_xs(const GstMpegtsDescriptor *descriptor,
|
||||
GstMpegtsJpegXsDescriptor *res);
|
||||
|
||||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor *
|
||||
gst_mpegts_descriptor_from_jpeg_xs(const GstMpegtsJpegXsDescriptor *jpegxs);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_MPEGTS_DESCRIPTOR_H */
|
||||
|
|
|
@ -399,6 +399,14 @@ typedef enum {
|
|||
GST_MPEGTS_STREAM_TYPE_VIDEO_H264_STEREO_ADDITIONAL_VIEW = 0x23,
|
||||
GST_MPEGTS_STREAM_TYPE_VIDEO_HEVC = 0x24,
|
||||
/* 0x24 - 0x7e : Rec. ITU-T H.222.0 | ISO/IEC 13818-1 Reserved */
|
||||
/**
|
||||
* GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS:
|
||||
*
|
||||
* JPEG-XS stream type
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS = 0x32,
|
||||
GST_MPEGTS_STREAM_TYPE_IPMP_STREAM = 0x7f,
|
||||
/* 0x80 - 0xff : User Private (or defined in other specs) */
|
||||
|
||||
|
|
|
@ -243,6 +243,7 @@ struct _TSDemuxStream
|
|||
"wmvversion = (int) 3, " \
|
||||
"format = (string) WVC1;" \
|
||||
"image/x-jpc;" \
|
||||
"image/x-jxsc;" \
|
||||
)
|
||||
|
||||
#define AUDIO_CAPS \
|
||||
|
@ -1848,6 +1849,53 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
|
|||
"colorspace", G_TYPE_STRING, colorspace, NULL);
|
||||
}
|
||||
break;
|
||||
case GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS:
|
||||
{
|
||||
GstMpegtsJpegXsDescriptor jpegxs;
|
||||
desc =
|
||||
mpegts_get_descriptor_from_stream_with_extension (bstream,
|
||||
GST_MTS_DESC_EXTENSION, GST_MTS_DESC_EXT_JXS_VIDEO);
|
||||
if (!desc) {
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"image/x-jxsc stream does not have mandatory descriptor");
|
||||
break;
|
||||
}
|
||||
if (!gst_mpegts_descriptor_parse_jpeg_xs (desc, &jpegxs)) {
|
||||
GST_WARNING_OBJECT (demux, "Invalid JPEG XS descriptor");
|
||||
break;
|
||||
}
|
||||
if (jpegxs.frat >> 30) {
|
||||
GST_WARNING_OBJECT (demux, "Interlaced JPEG-XS not supported yet");
|
||||
break;
|
||||
}
|
||||
if ((jpegxs.schar >> 15) == 0) {
|
||||
GST_WARNING_OBJECT (demux, "JPEG-XS sampling properties are required");
|
||||
break;
|
||||
}
|
||||
is_video = TRUE;
|
||||
caps =
|
||||
gst_caps_from_string
|
||||
("image/x-jxsc, alignment=(string)frame, interlace-mode=(string)progressive");
|
||||
|
||||
/* interlace-mode, sampling, depth */
|
||||
gst_caps_set_simple (caps, "width", G_TYPE_INT, jpegxs.horizontal_size,
|
||||
"height", G_TYPE_INT, jpegxs.vertical_size, "depth", G_TYPE_INT,
|
||||
(jpegxs.schar >> 4) & 0xf, NULL);
|
||||
switch (jpegxs.schar & 0xf) {
|
||||
case 0:
|
||||
gst_caps_set_simple (caps, "sampling", G_TYPE_STRING, "YCbCr-4:2:2",
|
||||
NULL);
|
||||
break;
|
||||
case 1:
|
||||
gst_caps_set_simple (caps, "sampling", G_TYPE_STRING, "YCbCr-4:4:4",
|
||||
NULL);
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (demux, "Unsupported JPEG-XS sampling format");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ST_VIDEO_DIRAC:
|
||||
if (bstream->registration_id == 0x64726163) {
|
||||
GST_LOG_OBJECT (demux, "dirac");
|
||||
|
@ -3119,6 +3167,50 @@ error:
|
|||
}
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
parse_jpegxs_access_unit (TSDemuxStream * stream)
|
||||
{
|
||||
GstByteReader br;
|
||||
guint32 header_tag;
|
||||
guint32 header_size;
|
||||
GstBuffer *retbuf;
|
||||
|
||||
if (stream->current_size < 30) {
|
||||
GST_ERROR_OBJECT (stream->pad, "Not enough data for header");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_byte_reader_init (&br, stream->data, stream->current_size);
|
||||
|
||||
/* Should start with `jxes` box header */
|
||||
header_size = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
header_tag = gst_byte_reader_get_uint32_be_unchecked (&br);
|
||||
if (header_size != 30 || header_tag != 0x6a786573) {
|
||||
GST_ERROR_OBJECT (stream->pad,
|
||||
"Invalid 'jxes' header (size:%u, tag:%" GST_FOURCC_FORMAT ")",
|
||||
header_size, GST_FOURCC_ARGS (header_tag));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME : Parse/extract timecode */
|
||||
|
||||
/* Ignore the rest of that box */
|
||||
retbuf =
|
||||
gst_buffer_new_wrapped_full (0, stream->data, stream->current_size,
|
||||
header_size, stream->current_size - header_size, stream->data, g_free);
|
||||
stream->data = NULL;
|
||||
stream->current_size = 0;
|
||||
return retbuf;
|
||||
|
||||
error:
|
||||
GST_ERROR ("Failed to parse JPEG-XS access unit");
|
||||
g_free (stream->data);
|
||||
stream->data = NULL;
|
||||
stream->current_size = 0;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* interlaced mode is disabled at the moment */
|
||||
/*#define TSDEMUX_JP2K_SUPPORT_INTERLACE */
|
||||
static GstBuffer *
|
||||
|
@ -3472,6 +3564,8 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream,
|
|||
} else if (bs->stream_type == GST_MPEGTS_STREAM_TYPE_METADATA_PES_PACKETS
|
||||
&& bs->registration_id == DRF_ID_KLVA) {
|
||||
buffer_list = parse_pes_metadata_frame (stream);
|
||||
} else if (bs->stream_type == GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS) {
|
||||
buffer = parse_jpegxs_access_unit (stream);
|
||||
} else {
|
||||
buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);
|
||||
}
|
||||
|
@ -3522,6 +3616,8 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream,
|
|||
} else if (bs->stream_type == GST_MPEGTS_STREAM_TYPE_METADATA_PES_PACKETS
|
||||
&& bs->registration_id == DRF_ID_KLVA) {
|
||||
buffer_list = parse_pes_metadata_frame (stream);
|
||||
} else if (bs->stream_type == GST_MPEGTS_STREAM_TYPE_VIDEO_JPEG_XS) {
|
||||
buffer = parse_jpegxs_access_unit (stream);
|
||||
} else {
|
||||
buffer = gst_buffer_new_wrapped (stream->data, stream->current_size);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "gstbasetsmuxttxt.h"
|
||||
#include "gstbasetsmuxopus.h"
|
||||
#include "gstbasetsmuxjpeg2000.h"
|
||||
#include "gstbasetsmuxjpegxs.h"
|
||||
|
||||
GST_DEBUG_CATEGORY (gst_base_ts_mux_debug);
|
||||
#define GST_CAT_DEFAULT gst_base_ts_mux_debug
|
||||
|
@ -440,6 +441,140 @@ release_buffer_cb (guint8 * data, void *user_data)
|
|||
stream_data_free ((StreamData *) user_data);
|
||||
}
|
||||
|
||||
static GstMpegtsJpegXsDescriptor *
|
||||
gst_base_ts_mux_jpegxs_descriptor (GstBaseTsMux * mux,
|
||||
GstBaseTsMuxPad * ts_pad, GstCaps * caps)
|
||||
{
|
||||
GstStructure *s = gst_caps_get_structure (caps, 0);
|
||||
gint codestream_length, depth;
|
||||
GstMpegtsJpegXsDescriptor *jpegxs_descriptor;
|
||||
GstVideoInfo video_info;
|
||||
const gchar *sampling;
|
||||
|
||||
if (!gst_video_info_from_caps (&video_info, caps))
|
||||
return NULL;
|
||||
|
||||
/* Get (and calculate) all fields from the caps information */
|
||||
sampling = gst_structure_get_string (s, "sampling");
|
||||
if (!gst_structure_get_int (s, "codestream-length", &codestream_length)
|
||||
|| !sampling || !gst_structure_get_int (s, "depth", &depth) || !depth) {
|
||||
GST_ERROR_OBJECT (ts_pad,
|
||||
"JPEG-XS caps doesn't contain all required fields");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jpegxs_descriptor = g_new0 (GstMpegtsJpegXsDescriptor, 1);
|
||||
|
||||
jpegxs_descriptor->horizontal_size = GST_VIDEO_INFO_WIDTH (&video_info);
|
||||
jpegxs_descriptor->vertical_size = GST_VIDEO_INFO_HEIGHT (&video_info);
|
||||
|
||||
{
|
||||
/* FIXME : Cap according to limit defined by profile/level */
|
||||
guint32 brat = G_MAXUINT32;
|
||||
if (GST_VIDEO_INFO_FPS_N (&video_info) > 0
|
||||
&& GST_VIDEO_INFO_FPS_D (&video_info) > 0) {
|
||||
// 125000 = * 8 / 1000000 (convert to bits, divide to Mbps)
|
||||
guint64 v =
|
||||
gst_util_uint64_scale_ceil (GST_VIDEO_INFO_FPS_N (&video_info),
|
||||
codestream_length,
|
||||
GST_VIDEO_INFO_FPS_D (&video_info) * 125000);
|
||||
if (v < G_MAXUINT32)
|
||||
brat = v & 0xffffffff;
|
||||
}
|
||||
jpegxs_descriptor->brat = brat;
|
||||
}
|
||||
|
||||
{
|
||||
guint32 frat = 0;
|
||||
gint fps_n = GST_VIDEO_INFO_FPS_N (&video_info);
|
||||
gint fps_d = GST_VIDEO_INFO_FPS_D (&video_info);
|
||||
gint denom_value = 1;
|
||||
|
||||
/* Only framerate divisible by 1 or 1.001 are allowed */
|
||||
if (fps_d == 1001) {
|
||||
fps_n /= 1000;
|
||||
denom_value = 2;
|
||||
} else if (fps_d != 1) {
|
||||
GST_ERROR_OBJECT (ts_pad, "framerate %d/%d is not allowed for JPEG-XS",
|
||||
fps_n, fps_d);
|
||||
goto free_return;
|
||||
}
|
||||
if (fps_n > G_MAXUINT16) {
|
||||
GST_ERROR_OBJECT (ts_pad, "framerate %d/%d exceeds limits for JPEG-XS",
|
||||
fps_n, fps_d);
|
||||
goto free_return;
|
||||
}
|
||||
|
||||
if (GST_VIDEO_INFO_IS_INTERLACED (&video_info)) {
|
||||
if (GST_VIDEO_INFO_FIELD_ORDER (&video_info) ==
|
||||
GST_VIDEO_FIELD_ORDER_TOP_FIELD_FIRST) {
|
||||
frat |= 1 << 30;
|
||||
} else if (GST_VIDEO_INFO_FIELD_ORDER (&video_info) ==
|
||||
GST_VIDEO_FIELD_ORDER_BOTTOM_FIELD_FIRST) {
|
||||
frat |= 1 << 31;
|
||||
} else {
|
||||
GST_ERROR_OBJECT (ts_pad, "Unknown interlace mode");
|
||||
goto free_return;
|
||||
}
|
||||
}
|
||||
|
||||
frat |= denom_value << 24;
|
||||
frat |= fps_n;
|
||||
|
||||
jpegxs_descriptor->frat = frat;
|
||||
}
|
||||
|
||||
{
|
||||
guint16 schar = (depth & 0xf) << 4;
|
||||
/* FIXME : Support all other variants */
|
||||
if (!g_strcmp0 (sampling, "YCbCr-4:2:2")) {
|
||||
schar |= 0;
|
||||
} else if (!g_strcmp0 (sampling, "YCbCr-4:4:4")) {
|
||||
schar |= 1;
|
||||
} else {
|
||||
GST_ERROR_OBJECT (ts_pad, "Unsupported sampling %s", sampling);
|
||||
goto free_return;
|
||||
}
|
||||
|
||||
/* schar is valid */
|
||||
schar |= 1 << 15;
|
||||
|
||||
jpegxs_descriptor->schar = schar;
|
||||
}
|
||||
|
||||
/* FIXME : Handle profile/level/sublevel once provided by caps. For now we are unrestricted */
|
||||
jpegxs_descriptor->Ppih = 0;
|
||||
jpegxs_descriptor->Plev = 0;
|
||||
|
||||
/* FIXME : Calculate max_buffer_size based on profile/level if specified */
|
||||
jpegxs_descriptor->max_buffer_size = jpegxs_descriptor->brat / 160;
|
||||
|
||||
/* Hardcoded buffer_model_type of 2 accordingly to H.222.0 specification */
|
||||
jpegxs_descriptor->buffer_model_type = 2;
|
||||
|
||||
jpegxs_descriptor->colour_primaries =
|
||||
gst_video_color_primaries_to_iso (video_info.colorimetry.primaries);
|
||||
jpegxs_descriptor->transfer_characteristics =
|
||||
gst_video_transfer_function_to_iso (video_info.colorimetry.transfer);
|
||||
jpegxs_descriptor->matrix_coefficients =
|
||||
gst_video_color_matrix_to_iso (video_info.colorimetry.matrix);
|
||||
jpegxs_descriptor->video_full_range_flag =
|
||||
video_info.colorimetry.range == GST_VIDEO_COLOR_RANGE_0_255;
|
||||
|
||||
/* We don't accept still pictures */
|
||||
jpegxs_descriptor->still_mode = FALSE;
|
||||
|
||||
/* FIXME : Add support for Mastering Display Metadata parsing */
|
||||
|
||||
return jpegxs_descriptor;
|
||||
|
||||
free_return:
|
||||
{
|
||||
g_free (jpegxs_descriptor);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Must be called with mux->lock held */
|
||||
static GstFlowReturn
|
||||
gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
||||
|
@ -459,6 +594,7 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
const gchar *stream_format = NULL;
|
||||
const char *interlace_mode = NULL;
|
||||
gchar *pmt_name;
|
||||
GstMpegtsDescriptor *pmt_descriptor = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (ts_pad,
|
||||
"%s stream with PID 0x%04x for caps %" GST_PTR_FORMAT,
|
||||
|
@ -676,6 +812,22 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
st = TSMUX_ST_PS_KLV;
|
||||
} else if (strcmp (mt, "meta/x-id3") == 0) {
|
||||
st = TSMUX_ST_PS_ID3;
|
||||
} else if (strcmp (mt, "image/x-jxsc") == 0) {
|
||||
/* FIXME: Get actual values from caps */
|
||||
GstMpegtsJpegXsDescriptor *jpegxs_descriptor =
|
||||
gst_base_ts_mux_jpegxs_descriptor (mux, ts_pad, caps);
|
||||
if (!jpegxs_descriptor)
|
||||
goto not_negotiated;
|
||||
|
||||
pmt_descriptor = gst_mpegts_descriptor_from_jpeg_xs (jpegxs_descriptor);
|
||||
if (!pmt_descriptor) {
|
||||
g_free (jpegxs_descriptor);
|
||||
goto not_negotiated;
|
||||
}
|
||||
st = TSMUX_ST_VIDEO_JPEG_XS;
|
||||
ts_pad->prepare_func = gst_base_ts_mux_prepare_jpegxs;
|
||||
ts_pad->prepare_data = jpegxs_descriptor;
|
||||
ts_pad->free_func = gst_base_ts_mux_free_jpegxs;
|
||||
} else if (strcmp (mt, "image/x-jpc") == 0) {
|
||||
/*
|
||||
* See this document for more details on standard:
|
||||
|
@ -802,6 +954,10 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (pmt_descriptor) {
|
||||
ts_pad->stream->pmt_descriptor = pmt_descriptor;
|
||||
}
|
||||
|
||||
pmt_name = g_strdup_printf ("PMT_%d", ts_pad->pid);
|
||||
if (mux->prog_map && gst_structure_has_field (mux->prog_map, pmt_name)) {
|
||||
gst_structure_get_int (mux->prog_map, pmt_name, &ts_pad->stream->pmt_index);
|
||||
|
@ -842,9 +998,13 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
|
||||
/* ERRORS */
|
||||
not_negotiated:
|
||||
if (pmt_descriptor)
|
||||
gst_mpegts_descriptor_free (pmt_descriptor);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
|
||||
error:
|
||||
if (pmt_descriptor)
|
||||
gst_mpegts_descriptor_free (pmt_descriptor);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
|
|
106
subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmuxjpegxs.c
Normal file
106
subprojects/gst-plugins-bad/gst/mpegtsmux/gstbasetsmuxjpegxs.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* JPEG-XS support for MPEG-TS
|
||||
*
|
||||
* Copyright (C) <2024> Centricular ltd
|
||||
* @author Edward Hervey <edward@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "gstbasetsmuxjpegxs.h"
|
||||
#include <string.h>
|
||||
#include <gst/base/gstbytewriter.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#define GST_CAT_DEFAULT gst_base_ts_mux_debug
|
||||
|
||||
GstBuffer *
|
||||
gst_base_ts_mux_prepare_jpegxs (GstBuffer * buf, GstBaseTsMuxPad * pad,
|
||||
GstBaseTsMux * mux)
|
||||
{
|
||||
GstMpegtsJpegXsDescriptor *private_data = pad->prepare_data;
|
||||
GstByteWriter wr;
|
||||
GstBuffer *out_buf = NULL;
|
||||
gsize header_size = 30;
|
||||
guint8 *jxes_header = NULL;
|
||||
GstClockTime seconds = buf->pts / GST_SECOND;
|
||||
GstClockTime minutes = seconds / 60;
|
||||
GstClockTime hours = minutes / 60;
|
||||
|
||||
/* FIXME : Instead of constantly allocating/freeing a new header, we should:
|
||||
* * Generate this header once
|
||||
* * Update it only for the new tcod
|
||||
*/
|
||||
|
||||
seconds = seconds % 60;
|
||||
minutes = minutes % 60;
|
||||
hours = hours % 24;
|
||||
|
||||
/* Box is fixed size */
|
||||
gst_byte_writer_init_with_size (&wr, header_size, FALSE);
|
||||
|
||||
gst_byte_writer_put_uint32_be (&wr, header_size);
|
||||
/* Elementary stream header box 'jxes' == 0x6a786573 */
|
||||
gst_byte_writer_put_uint32_be (&wr, 0x6a786573);
|
||||
|
||||
/* brat, frat are 32 bytes */
|
||||
gst_byte_writer_put_uint32_be (&wr, private_data->brat);
|
||||
gst_byte_writer_put_uint32_be (&wr, private_data->frat);
|
||||
|
||||
/* schar, Ppih, Plev */
|
||||
gst_byte_writer_put_uint16_be (&wr, private_data->schar);
|
||||
gst_byte_writer_put_uint16_be (&wr, private_data->Ppih);
|
||||
gst_byte_writer_put_uint16_be (&wr, private_data->Plev);
|
||||
|
||||
gst_byte_writer_put_uint8 (&wr, private_data->colour_primaries);
|
||||
gst_byte_writer_put_uint8 (&wr, private_data->transfer_characteristics);
|
||||
gst_byte_writer_put_uint8 (&wr, private_data->matrix_coefficients);
|
||||
|
||||
gst_byte_writer_put_uint8 (&wr, private_data->video_full_range_flag << 7);
|
||||
|
||||
/* put HHMMSSFF */
|
||||
gst_byte_writer_put_uint8 (&wr, (guint8) hours);
|
||||
gst_byte_writer_put_uint8 (&wr, (guint8) minutes);
|
||||
gst_byte_writer_put_uint8 (&wr, (guint8) seconds);
|
||||
gst_byte_writer_put_uint8 (&wr, 0x0);
|
||||
|
||||
/* Put jxes header in buffer */
|
||||
header_size = gst_byte_writer_get_size (&wr);
|
||||
jxes_header = gst_byte_writer_reset_and_get_data (&wr);
|
||||
out_buf = gst_buffer_new_wrapped (jxes_header, header_size);
|
||||
|
||||
/* Copy complete frame */
|
||||
gst_buffer_copy_into (out_buf, buf,
|
||||
GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS |
|
||||
GST_BUFFER_COPY_MEMORY, 0, -1);
|
||||
GST_DEBUG_OBJECT (mux, "Prepared JPEGXS PES of size %d",
|
||||
(int) gst_buffer_get_size (out_buf));
|
||||
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
void
|
||||
gst_base_ts_mux_free_jpegxs (gpointer prepare_data)
|
||||
{
|
||||
/* Free prepare data memory object */
|
||||
g_free (prepare_data);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* Support for JPEG-XS
|
||||
*
|
||||
* Copyright (C) <2024> Centricular ltd
|
||||
* @author Edward Hervey <edward@centricular.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef __BASETSMUX_JPEGXS_H__
|
||||
#define __BASETSMUX_JPEGXS_H__
|
||||
|
||||
#include "glib.h"
|
||||
#include "gstbasetsmux.h"
|
||||
|
||||
typedef struct jpegxs_private_data
|
||||
{
|
||||
guint32 brat;
|
||||
guint32 frat;
|
||||
guint16 schar;
|
||||
guint16 Ppih;
|
||||
guint16 Plev;
|
||||
guint8 color_primaries;
|
||||
guint8 transfer_characteristics;
|
||||
guint8 matrix_coefficients;
|
||||
gboolean video_full_range_flag;
|
||||
guint32 tcod;
|
||||
} jpegxs_private_data;
|
||||
|
||||
GstBuffer *gst_base_ts_mux_prepare_jpegxs (GstBuffer * buf, GstBaseTsMuxPad * pad,
|
||||
GstBaseTsMux * mux);
|
||||
|
||||
void gst_base_ts_mux_free_jpegxs (gpointer prepare_data);
|
||||
|
||||
#endif /* __BASETSMUX_JPEGXS_H__ */
|
|
@ -126,7 +126,8 @@ static GstStaticPadTemplate gst_mpeg_ts_mux_sink_factory =
|
|||
"channels = (int) [1, 255];"
|
||||
"subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
|
||||
"meta/x-id3, parsed=true;"
|
||||
"image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];"));
|
||||
"image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];"
|
||||
"image/x-jxsc, alignment = (string) frame, sampling = { YCbCr-4:2:2, YCbCr-4:4:4 };"));
|
||||
|
||||
static GstStaticPadTemplate gst_mpeg_ts_mux_src_factory =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
|
|
|
@ -5,6 +5,7 @@ tsmux_sources = [
|
|||
'gstbasetsmuxopus.c',
|
||||
'gstbasetsmuxttxt.c',
|
||||
'gstbasetsmuxjpeg2000.c',
|
||||
'gstbasetsmuxjpegxs.c',
|
||||
'gstmpegtsmux.c',
|
||||
'gstatscmux.c',
|
||||
'tsmux/tsmux.c',
|
||||
|
|
|
@ -153,6 +153,11 @@ tsmux_stream_new (guint16 pid, guint stream_type, guint stream_number)
|
|||
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
|
||||
stream->gst_stream_type = GST_STREAM_TYPE_VIDEO;
|
||||
break;
|
||||
case TSMUX_ST_VIDEO_JPEG_XS:
|
||||
stream->id = 0xBD; /* Private Stream 1 */
|
||||
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
|
||||
stream->gst_stream_type = GST_STREAM_TYPE_VIDEO;
|
||||
break;
|
||||
case TSMUX_ST_AUDIO_AAC:
|
||||
case TSMUX_ST_AUDIO_MPEG1:
|
||||
case TSMUX_ST_AUDIO_MPEG2:
|
||||
|
@ -296,6 +301,8 @@ tsmux_stream_free (TsMuxStream * stream)
|
|||
}
|
||||
g_list_free (stream->buffers);
|
||||
|
||||
if (stream->pmt_descriptor)
|
||||
gst_mpegts_descriptor_free (stream->pmt_descriptor);
|
||||
g_free (stream);
|
||||
}
|
||||
|
||||
|
@ -902,6 +909,12 @@ tsmux_stream_default_get_es_descrs (TsMuxStream * stream,
|
|||
g_ptr_array_add (pmt_stream->descriptors, descriptor);
|
||||
}
|
||||
break;
|
||||
case TSMUX_ST_VIDEO_JPEG_XS:
|
||||
{
|
||||
g_ptr_array_add (pmt_stream->descriptors,
|
||||
gst_mpegts_descriptor_copy (stream->pmt_descriptor));
|
||||
}
|
||||
break;
|
||||
case TSMUX_ST_PS_AUDIO_AC3:
|
||||
{
|
||||
/* This is only called for DVB, ATSC ignores this case in favour of its
|
||||
|
|
|
@ -121,7 +121,8 @@ enum TsMuxStreamType {
|
|||
TSMUX_ST_PES_METADATA = 0x15,
|
||||
TSMUX_ST_VIDEO_H264 = 0x1b,
|
||||
TSMUX_ST_VIDEO_HEVC = 0x24,
|
||||
TSMUX_ST_VIDEO_JP2K = 0x21,
|
||||
TSMUX_ST_VIDEO_JP2K = 0x21,
|
||||
TSMUX_ST_VIDEO_JPEG_XS = 0x32,
|
||||
|
||||
/* private stream types */
|
||||
TSMUX_ST_PS_AUDIO_AC3 = 0x81,
|
||||
|
@ -227,6 +228,9 @@ struct TsMuxStream {
|
|||
guint16 profile_and_level;
|
||||
gboolean interlace_mode;
|
||||
guint8 color_spec;
|
||||
|
||||
/* PMT descriptor for the stream */
|
||||
GstMpegtsDescriptor *pmt_descriptor;
|
||||
};
|
||||
|
||||
/* stream management */
|
||||
|
|
Loading…
Reference in a new issue