mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-05-18 08:22:51 +00:00
Merge branch '3485_support_pes_metadata' into 'main'
mpegtsmux: Support metadata in PES packets streams in TS Closes #3485 See merge request gstreamer/gstreamer!6793
This commit is contained in:
commit
a35ac5636e
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "mpegts.h"
|
||||
#include "gstmpegts-private.h"
|
||||
#include <gst/base/gstbytewriter.h>
|
||||
|
||||
#define GST_CAT_DEFAULT mpegts_debug
|
||||
|
||||
|
@ -46,6 +47,46 @@ G_DEFINE_BOXED_TYPE (GstMpegtsMetadataDescriptor,
|
|||
(GBoxedCopyFunc) _gst_mpegts_metadata_descriptor_copy,
|
||||
(GFreeFunc) _gst_mpegts_metadata_descriptor_free);
|
||||
|
||||
|
||||
GstMpegtsDescriptor *
|
||||
gst_mpegts_descriptor_from_metadata (const GstMpegtsMetadataDescriptor *
|
||||
metadata_descriptor)
|
||||
{
|
||||
g_return_val_if_fail (metadata_descriptor != NULL, NULL);
|
||||
|
||||
int wr_size = 0;
|
||||
guint8 *add_info = NULL;
|
||||
GstByteWriter writer;
|
||||
|
||||
// metadata_descriptor
|
||||
gst_byte_writer_init_with_size (&writer, 32, FALSE);
|
||||
|
||||
gst_byte_writer_put_uint16_be (&writer,
|
||||
metadata_descriptor->metadata_application_format);
|
||||
if (metadata_descriptor->metadata_application_format == 0xFFFF) {
|
||||
gst_byte_writer_put_uint32_be (&writer, metadata_descriptor->metadata_format_identifier); // metadata_application_format_identifier
|
||||
}
|
||||
|
||||
gst_byte_writer_put_uint8 (&writer, metadata_descriptor->metadata_format);
|
||||
if (metadata_descriptor->metadata_format ==
|
||||
GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) {
|
||||
gst_byte_writer_put_uint32_be (&writer, metadata_descriptor->metadata_format_identifier); // metadata_format_identifier
|
||||
}
|
||||
|
||||
gst_byte_writer_put_uint8 (&writer, metadata_descriptor->metadata_service_id);
|
||||
gst_byte_writer_put_uint8 (&writer, 0x0F); // decoder_config_flags = 000, DSM_CC_flag = 0, reserved = 1111
|
||||
|
||||
wr_size = gst_byte_writer_get_size (&writer);
|
||||
add_info = gst_byte_writer_reset_and_get_data (&writer);
|
||||
|
||||
GstMpegtsDescriptor *descriptor =
|
||||
gst_mpegts_descriptor_from_custom (GST_MTS_DESC_METADATA, add_info,
|
||||
wr_size);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_mpegts_descriptor_parse_metadata:
|
||||
* @descriptor: a %GST_TYPE_MPEGTS_METADATA_DESCRIPTOR #GstMpegtsDescriptor
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* Gstreamer
|
||||
* Copyright 2024 Juan Adarve <juanda0718@gmail.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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mpegts.h"
|
||||
#include "gstmpegts-private.h"
|
||||
#include <gst/base/gstbytewriter.h>
|
||||
|
||||
#define GST_CAT_DEFAULT mpegts_debug
|
||||
|
||||
|
||||
static GstMpegtsMetadataPointerDescriptor *
|
||||
_gst_mpegts_metadata_pointer_descriptor_copy (GstMpegtsMetadataPointerDescriptor
|
||||
* source)
|
||||
{
|
||||
GstMpegtsMetadataPointerDescriptor *copy =
|
||||
g_memdup2 (source, sizeof (GstMpegtsMetadataPointerDescriptor));
|
||||
return copy;
|
||||
}
|
||||
|
||||
static void
|
||||
_gst_mpegts_metadata_pointer_descriptor_free (GstMpegtsMetadataPointerDescriptor
|
||||
* desc)
|
||||
{
|
||||
g_free (desc);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GstMpegtsMetadataPointerDescriptor,
|
||||
gst_mpegts_metadata_pointer_descriptor,
|
||||
(GBoxedCopyFunc) _gst_mpegts_metadata_pointer_descriptor_copy,
|
||||
(GFreeFunc) _gst_mpegts_metadata_pointer_descriptor_free);
|
||||
|
||||
GstMpegtsDescriptor *
|
||||
gst_mpegts_descriptor_from_metadata_pointer (const
|
||||
GstMpegtsMetadataPointerDescriptor * metadata_pointer_descriptor)
|
||||
{
|
||||
g_return_val_if_fail (metadata_pointer_descriptor != NULL, NULL);
|
||||
|
||||
int wr_size = 0;
|
||||
guint8 *add_info = NULL;
|
||||
GstByteWriter writer;
|
||||
|
||||
// metadata_pointer_descriptor
|
||||
gst_byte_writer_init_with_size (&writer, 32, FALSE);
|
||||
|
||||
gst_byte_writer_put_uint16_be (&writer,
|
||||
metadata_pointer_descriptor->metadata_application_format);
|
||||
if (metadata_pointer_descriptor->metadata_application_format == 0xFFFF) {
|
||||
gst_byte_writer_put_uint32_be (&writer, metadata_pointer_descriptor->metadata_format_identifier); // metadata_application_format_identifier
|
||||
}
|
||||
|
||||
gst_byte_writer_put_uint8 (&writer,
|
||||
metadata_pointer_descriptor->metadata_format);
|
||||
if (metadata_pointer_descriptor->metadata_format ==
|
||||
GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD) {
|
||||
gst_byte_writer_put_uint32_be (&writer, metadata_pointer_descriptor->metadata_format_identifier); // metadata_format_identifier
|
||||
}
|
||||
|
||||
gst_byte_writer_put_uint8 (&writer,
|
||||
metadata_pointer_descriptor->metadata_service_id);
|
||||
gst_byte_writer_put_uint8 (&writer, 0x1F); // metadata_locator_record_flag = 0, MPEG_carriage_flag = 00, reserved = 11111
|
||||
gst_byte_writer_put_uint16_be (&writer, metadata_pointer_descriptor->program_number); // program_number
|
||||
|
||||
wr_size = gst_byte_writer_get_size (&writer);
|
||||
add_info = gst_byte_writer_reset_and_get_data (&writer);
|
||||
|
||||
GstMpegtsDescriptor *descriptor =
|
||||
gst_mpegts_descriptor_from_custom (GST_MTS_DESC_METADATA_POINTER,
|
||||
add_info,
|
||||
wr_size);
|
||||
|
||||
return descriptor;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Gstreamer
|
||||
* Copyright 2024 Juan Adarve <juanda0718@gmail.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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_MPEGTS_METADATA_POINTER_DESCRIPTOR_H__
|
||||
#define __GST_MPEGTS_METADATA_POINTER_DESCRIPTOR_H__
|
||||
|
||||
#include "gst/mpegts/gst-metadata-descriptor.h"
|
||||
#include <gst/gst.h>
|
||||
#include <gst/mpegts/mpegts-prelude.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* MPEG-TS Metadata Descriptor (0x25) */
|
||||
typedef struct _GstMpegtsMetadataPointerDescriptor
|
||||
GstMpegtsMetadataPointerDescriptor;
|
||||
|
||||
/**
|
||||
* GstMpegtsMetadataPointerDescriptor:
|
||||
* @metadata_application_format: specifies the application responsible for defining usage, syntax and semantics
|
||||
* @metadata_format: indicates the format and coding of the metadata
|
||||
* @metadata_format_identifier: format identifier (equivalent to registration descriptor), for example 0x4B4C4641 ('KLVA') to indicate SMPTE 336 KLV, or 0x49443320 ('ID3 ').
|
||||
* @metadata_service_id: metadata service to which this metadata descriptor applies, typically 0x00
|
||||
* @program_number: Indicates the program in which the metadata is carried.
|
||||
*
|
||||
* This structure is not complete. The following fields are missing in comparison to the standard (ISO/IEC 13818-1:2023 Section 2.6.58):
|
||||
* * metadata_locator_record_flag: hardcoded to 0. Indicating no metadata_locator_record present in the descriptor.
|
||||
* * MPEG_carriage_flags: hardcoded to 0b00, indicating the metadata is carried in the same transport steam.
|
||||
* * metadata_locator_record_length.
|
||||
* * transport_stream_location.
|
||||
* * transport_stream_id.
|
||||
*
|
||||
* See also: gst_mpegts_descriptor_from_metadata_pointer
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
struct _GstMpegtsMetadataPointerDescriptor {
|
||||
guint16 metadata_application_format;
|
||||
GstMpegtsMetadataFormat metadata_format;
|
||||
guint32 metadata_format_identifier;
|
||||
guint8 metadata_service_id;
|
||||
guint16 program_number;
|
||||
};
|
||||
|
||||
#define GST_TYPE_MPEGTS_METADATA_POINTER_DESCRIPTOR \
|
||||
(gst_mpegts_metadata_pointer_descriptor_get_type())
|
||||
|
||||
GST_MPEGTS_API
|
||||
GType gst_mpegts_metadata_pointer_descriptor_get_type(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
|
@ -33,6 +33,7 @@
|
|||
#define GST_MPEGTS_DESCRIPTOR_H
|
||||
|
||||
#include "gst-metadata-descriptor.h"
|
||||
#include "gst-metadata-pointer-descriptor.h"
|
||||
#include <gst/gst.h>
|
||||
#include <gst/mpegts/mpegts-prelude.h>
|
||||
|
||||
|
@ -344,6 +345,9 @@ guint gst_mpegts_descriptor_parse_iso_639_language_nb (const GstMpegtsDescriptor
|
|||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor * gst_mpegts_descriptor_from_iso_639_language (const gchar * language);
|
||||
|
||||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor *gst_mpegts_descriptor_from_metadata(const GstMpegtsMetadataDescriptor *metadata_descriptor);
|
||||
|
||||
GST_MPEGTS_API
|
||||
gboolean gst_mpegts_descriptor_parse_metadata (const GstMpegtsDescriptor *descriptor, GstMpegtsMetadataDescriptor **res);
|
||||
|
||||
|
@ -353,6 +357,9 @@ gboolean gst_mpegts_descriptor_parse_metadata_std (const GstMpegtsDescriptor *de
|
|||
guint32 *metadata_buffer_size,
|
||||
guint32 *metadata_output_leak_rate);
|
||||
|
||||
GST_MPEGTS_API
|
||||
GstMpegtsDescriptor *gst_mpegts_descriptor_from_metadata_pointer(const GstMpegtsMetadataPointerDescriptor *metadata_pointer_descriptor);
|
||||
|
||||
/* GST_MTS_DESC_DTG_LOGICAL_CHANNEL (0x83) */
|
||||
typedef struct _GstMpegtsLogicalChannelDescriptor GstMpegtsLogicalChannelDescriptor;
|
||||
typedef struct _GstMpegtsLogicalChannel GstMpegtsLogicalChannel;
|
||||
|
|
|
@ -7,7 +7,8 @@ mpegts_sources = files(
|
|||
'gst-atsc-section.c',
|
||||
'gst-scte-section.c',
|
||||
'gst-mpegtspesmetadatameta.c',
|
||||
'gst-metadata-descriptor.c'
|
||||
'gst-metadata-descriptor.c',
|
||||
'gst-metadata-pointer-descriptor.c',
|
||||
)
|
||||
|
||||
mpegts_headers = files(
|
||||
|
@ -22,6 +23,7 @@ mpegts_headers = files(
|
|||
'gst-isdb-descriptor.h',
|
||||
'gst-mpegtspesmetadatameta.h',
|
||||
'gst-metadata-descriptor.h',
|
||||
'gst-metadata-pointer-descriptor.h',
|
||||
'mpegts-prelude.h',
|
||||
'mpegts.h',
|
||||
)
|
||||
|
@ -47,7 +49,7 @@ gstmpegts = library('gstmpegts-' + api_version,
|
|||
soversion : soversion,
|
||||
darwin_versions : osxversion,
|
||||
install : true,
|
||||
dependencies : [gst_dep],
|
||||
dependencies : [gst_dep, gstbase_dep],
|
||||
)
|
||||
|
||||
library_def = {'lib': gstmpegts}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <gst/mpegts/gst-hdmv-section.h>
|
||||
#include <gst/mpegts/gst-mpegtspesmetadatameta.h>
|
||||
#include <gst/mpegts/gst-metadata-descriptor.h>
|
||||
#include <gst/mpegts/gst-metadata-pointer-descriptor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
|
@ -674,6 +674,8 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
ts_pad->prepare_func = gst_base_ts_mux_prepare_opus;
|
||||
} else if (strcmp (mt, "meta/x-klv") == 0) {
|
||||
st = TSMUX_ST_PS_KLV;
|
||||
} else if (strcmp (mt, "application/x-metadata") == 0) {
|
||||
st = TSMUX_ST_PES_METADATA;
|
||||
} else if (strcmp (mt, "image/x-jpc") == 0) {
|
||||
/*
|
||||
* See this document for more details on standard:
|
||||
|
@ -826,6 +828,10 @@ gst_base_ts_mux_create_or_update_stream (GstBaseTsMux * mux,
|
|||
gst_structure_get_int (s, "width", &ts_pad->stream->horizontal_size);
|
||||
gst_structure_get_int (s, "height", &ts_pad->stream->vertical_size);
|
||||
|
||||
// metadata caps
|
||||
gst_structure_get_uint (s, "metadata-format-identifier",
|
||||
&ts_pad->stream->metadata_format_identifier);
|
||||
|
||||
ts_pad->stream->color_spec = color_spec;
|
||||
ts_pad->stream->max_bitrate = max_rate;
|
||||
ts_pad->stream->profile_and_level = profile | main_level;
|
||||
|
|
|
@ -125,6 +125,7 @@ static GstStaticPadTemplate gst_mpeg_ts_mux_sink_factory =
|
|||
"audio/x-opus, "
|
||||
"channels = (int) [1, 255];"
|
||||
"subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true;"
|
||||
"application/x-metadata;"
|
||||
"image/x-jpc, alignment = (string) frame, profile = (int)[0, 49151];"));
|
||||
|
||||
static GstStaticPadTemplate gst_mpeg_ts_mux_src_factory =
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <gst/mpegts/mpegts.h>
|
||||
#include <gst/base/gstbytewriter.h>
|
||||
|
||||
#include "tsmux.h"
|
||||
#include "tsmuxstream.h"
|
||||
|
@ -1853,6 +1854,28 @@ tsmux_write_pmt (TsMux * mux, TsMuxProgram * program)
|
|||
g_ptr_array_add (pmt->descriptors, descriptor);
|
||||
}
|
||||
|
||||
/* Scan the streams looking for metadata streams */
|
||||
for (i = 0; i < program->streams->len; i++) {
|
||||
TsMuxStream *stream = g_ptr_array_index (program->streams, i);
|
||||
|
||||
if (stream->is_application_metadata == TRUE) {
|
||||
// metadata_descriptor_pointer
|
||||
GstMpegtsMetadataPointerDescriptor metadata_pointer_descriptor;
|
||||
metadata_pointer_descriptor.metadata_application_format = 0xFFFF;
|
||||
metadata_pointer_descriptor.metadata_format =
|
||||
GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD;
|
||||
metadata_pointer_descriptor.metadata_format_identifier =
|
||||
stream->metadata_format_identifier;
|
||||
metadata_pointer_descriptor.metadata_service_id = 0;
|
||||
metadata_pointer_descriptor.program_number = program->pgm_number;
|
||||
|
||||
descriptor =
|
||||
gst_mpegts_descriptor_from_metadata_pointer
|
||||
(&metadata_pointer_descriptor);
|
||||
g_ptr_array_add (pmt->descriptors, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the entries */
|
||||
for (i = 0; i < program->streams->len; i++) {
|
||||
GstMpegtsPMTStream *pmt_stream;
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
|
||||
#include "tsmuxcommon.h"
|
||||
#include "tsmuxstream.h"
|
||||
#include "tsmux.h"
|
||||
|
||||
#define GST_CAT_DEFAULT gst_base_ts_mux_debug
|
||||
|
||||
|
@ -218,6 +219,15 @@ tsmux_stream_new (guint16 pid, guint stream_type, guint stream_number)
|
|||
TSMUX_PACKET_FLAG_PES_FULL_HEADER |
|
||||
TSMUX_PACKET_FLAG_PES_DATA_ALIGNMENT;
|
||||
break;
|
||||
case TSMUX_ST_PES_METADATA:
|
||||
stream->id = 0xBD; // private stream
|
||||
stream->stream_type = TSMUX_ST_PES_METADATA;
|
||||
stream->is_meta = TRUE;
|
||||
stream->is_application_metadata = TRUE;
|
||||
stream->metadata_format_identifier = 0;
|
||||
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER |
|
||||
TSMUX_PACKET_FLAG_PES_DATA_ALIGNMENT;
|
||||
break;
|
||||
case TSMUX_ST_PS_OPUS:
|
||||
/* FIXME: assign sequential extended IDs? */
|
||||
stream->id = 0xBD;
|
||||
|
@ -494,6 +504,12 @@ tsmux_stream_initialize_pes_packet (TsMuxStream * stream)
|
|||
if ((stream->cur_pes_payload_size + hdr_len - 6) > G_MAXUINT16)
|
||||
stream->cur_pes_payload_size = 0;
|
||||
}
|
||||
// stream_type specific flags
|
||||
switch (stream->stream_type) {
|
||||
case TSMUX_ST_PES_METADATA:
|
||||
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_DATA_ALIGNMENT;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -909,6 +925,33 @@ tsmux_stream_default_get_es_descrs (TsMuxStream * stream,
|
|||
gst_mpegts_descriptor_from_custom (GST_MTS_DESC_DVB_TELETEXT, 0, 1);
|
||||
|
||||
g_ptr_array_add (pmt_stream->descriptors, descriptor);
|
||||
break;
|
||||
case TSMUX_ST_PES_METADATA:
|
||||
|
||||
// metadata_descriptor
|
||||
GstMpegtsMetadataDescriptor metadata_descriptor;
|
||||
|
||||
metadata_descriptor.metadata_application_format = 0xFFFF;
|
||||
metadata_descriptor.metadata_format =
|
||||
GST_MPEGTS_METADATA_FORMAT_IDENTIFIER_FIELD;
|
||||
metadata_descriptor.metadata_format_identifier =
|
||||
stream->metadata_format_identifier;
|
||||
metadata_descriptor.metadata_service_id = 0;
|
||||
metadata_descriptor.decoder_config_flags = 0x00;
|
||||
metadata_descriptor.dsm_cc_flag = FALSE;
|
||||
|
||||
descriptor = gst_mpegts_descriptor_from_metadata (&metadata_descriptor);
|
||||
g_ptr_array_add (pmt_stream->descriptors, descriptor);
|
||||
|
||||
// registration_descriptor
|
||||
guint32 format_identifier = 0;
|
||||
GST_WRITE_UINT32_BE (&format_identifier,
|
||||
metadata_descriptor.metadata_format_identifier);
|
||||
|
||||
descriptor = gst_mpegts_descriptor_from_registration ((const char *)
|
||||
&format_identifier, NULL, 0);
|
||||
g_ptr_array_add (pmt_stream->descriptors, descriptor);
|
||||
|
||||
break;
|
||||
case TSMUX_ST_PS_DVB_SUBPICTURE:
|
||||
/* fallthrough ...
|
||||
|
|
|
@ -118,6 +118,7 @@ enum TsMuxStreamType {
|
|||
/* later extensions */
|
||||
TSMUX_ST_AUDIO_AAC = 0x0f,
|
||||
TSMUX_ST_VIDEO_MPEG4 = 0x10,
|
||||
TSMUX_ST_PES_METADATA = 0x15,
|
||||
TSMUX_ST_VIDEO_H264 = 0x1b,
|
||||
TSMUX_ST_VIDEO_HEVC = 0x24,
|
||||
TSMUX_ST_VIDEO_JP2K = 0x21,
|
||||
|
@ -226,6 +227,9 @@ struct TsMuxStream {
|
|||
guint16 profile_and_level;
|
||||
gboolean interlace_mode;
|
||||
guint8 color_spec;
|
||||
|
||||
gboolean is_application_metadata;
|
||||
guint32 metadata_format_identifier;
|
||||
};
|
||||
|
||||
/* stream management */
|
||||
|
|
Loading…
Reference in a new issue