summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gst/mpegtsmux/atscmux.c117
-rw-r--r--gst/mpegtsmux/mpegtsmux.c9
-rw-r--r--gst/mpegtsmux/mpegtsmux.h1
-rw-r--r--gst/mpegtsmux/tsmux/tsmux.c4
-rw-r--r--gst/mpegtsmux/tsmux/tsmux.h4
-rw-r--r--gst/mpegtsmux/tsmux/tsmuxstream.c51
-rw-r--r--gst/mpegtsmux/tsmux/tsmuxstream.h14
7 files changed, 187 insertions, 13 deletions
diff --git a/gst/mpegtsmux/atscmux.c b/gst/mpegtsmux/atscmux.c
index 93c803fc6..ffd4e4bb8 100644
--- a/gst/mpegtsmux/atscmux.c
+++ b/gst/mpegtsmux/atscmux.c
@@ -26,10 +26,106 @@ GST_DEBUG_CATEGORY (atscmux_debug);
G_DEFINE_TYPE (ATSCMux, atscmux, GST_TYPE_MPEG_TSMUX)
#define parent_class atscmux_parent_class
- static TsMuxStream *atscmux_create_new_stream (guint16 new_pid,
+#define ATSCMUX_ST_PS_AUDIO_EAC3 0x87
+ static GstStaticPadTemplate atscmux_sink_factory =
+ GST_STATIC_PAD_TEMPLATE ("sink_%d",
+ GST_PAD_SINK,
+ GST_PAD_REQUEST,
+ GST_STATIC_CAPS ("video/mpeg, "
+ "parsed = (boolean) TRUE, "
+ "mpegversion = (int) 2, "
+ "systemstream = (boolean) false; "
+ "video/x-h264,stream-format=(string)byte-stream,"
+ "alignment=(string){au, nal}; "
+ "audio/x-ac3, framed = (boolean) TRUE;"
+ "audio/x-eac3, framed = (boolean) TRUE;"));
+
+ static void
+ atscmux_stream_get_es_descrs (TsMuxStream * stream,
+ GstMpegtsPMTStream * pmt_stream, MpegTsMux * mpegtsmux)
+{
+ GstMpegtsDescriptor *descriptor;
+
+ tsmux_stream_default_get_es_descrs (stream, pmt_stream);
+
+ if (stream->stream_type == ATSCMUX_ST_PS_AUDIO_EAC3) {
+ guint8 add_info[4];
+ guint8 *pos;
+
+ pos = add_info;
+
+ /* audio_stream_descriptor () | ATSC A/52-2018 Annex G
+ *
+ * descriptor_tag 8 uimsbf
+ * descriptor_length 8 uimsbf
+ * reserved 1 '1'
+ * bsid_flag 1 bslbf
+ * mainid_flag 1 bslbf
+ * asvc_flag 1 bslbf
+ * mixinfoexists 1 bslbf
+ * substream1_flag 1 bslbf
+ * substream2_flag 1 bslbf
+ * substream3_flag 1 bslbf
+ * reserved 1 '1'
+ * full_service_flag 1 bslbf
+ * audio_service_type 3 uimsbf
+ * number_of_channels 3 uimsbf
+ * [...]
+ */
+
+ *pos++ = 0xCC;
+ *pos++ = 2;
+
+ /* 1 bit reserved, all other flags unset */
+ *pos++ = 0x80;
+
+ /* 1 bit reserved,
+ * 1 bit set for full_service_flag,
+ * 3 bits hardcoded audio_service_type "Complete Main",
+ * 3 bits number_of_channels
+ */
+ switch (stream->audio_channels) {
+ case 1:
+ *pos++ = 0xC0; /* Mono */
+ break;
+ case 2:
+ *pos++ = 0xC0 | 0x2; /* 2-channel (stereo) */
+ case 3:
+ case 4:
+ case 5:
+ *pos++ = 0xC0 | 0x4; /* Multichannel audio (> 2 channels; <= 3/2 + LFE channels) */
+ break;
+ case 6:
+ default:
+ *pos++ = 0xC0 | 0x5; /* Multichannel audio(> 3/2 + LFE channels) */
+ }
+
+ descriptor = gst_mpegts_descriptor_from_registration ("EAC3", add_info, 4);
+ g_ptr_array_add (pmt_stream->descriptors, descriptor);
+
+ descriptor =
+ gst_mpegts_descriptor_from_custom (GST_MTS_DESC_ATSC_EAC3, add_info, 4);
+ g_ptr_array_add (pmt_stream->descriptors, descriptor);
+ }
+}
+
+static TsMuxStream *
+atscmux_create_new_stream (guint16 new_pid,
TsMuxStreamType stream_type, MpegTsMux * mpegtsmux)
{
- return tsmux_stream_new (new_pid, stream_type);
+ TsMuxStream *ret = tsmux_stream_new (new_pid, stream_type);
+
+ if (stream_type == ATSCMUX_ST_PS_AUDIO_EAC3) {
+ ret->id = 0xBD;
+ ret->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+ ret->is_audio = TRUE;
+ }
+
+ tsmux_stream_set_get_es_descriptors_func (ret,
+ (TsMuxStreamGetESDescriptorsFunc) atscmux_stream_get_es_descrs,
+ mpegtsmux);
+
+ return ret;
}
static TsMux *
@@ -43,6 +139,19 @@ atscmux_create_ts_mux (MpegTsMux * mpegtsmux)
return ret;
}
+static guint
+atscmux_handle_media_type (MpegTsMux * mux, const gchar * media_type,
+ MpegTsPadData * ts_data)
+{
+ guint ret = TSMUX_ST_RESERVED;
+
+ if (!g_strcmp0 (media_type, "audio/x-eac3")) {
+ ret = ATSCMUX_ST_PS_AUDIO_EAC3;
+ }
+
+ return ret;
+}
+
static void
atscmux_class_init (ATSCMuxClass * klass)
{
@@ -57,6 +166,10 @@ atscmux_class_init (ATSCMuxClass * klass)
"Mathieu Duponchelle <mathieu@centricular.com>");
mpegtsmux_class->create_ts_mux = atscmux_create_ts_mux;
+ mpegtsmux_class->handle_media_type = atscmux_handle_media_type;
+
+ gst_element_class_add_static_pad_template (gstelement_class,
+ &atscmux_sink_factory);
}
static void
diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
index c21d6865f..47c6d865c 100644
--- a/gst/mpegtsmux/mpegtsmux.c
+++ b/gst/mpegtsmux/mpegtsmux.c
@@ -624,7 +624,7 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
GstCaps *caps;
GstStructure *s;
GstPad *pad;
- TsMuxStreamType st = TSMUX_ST_RESERVED;
+ guint st = TSMUX_ST_RESERVED;
const gchar *mt;
const GValue *value = NULL;
GstBuffer *codec_data = NULL;
@@ -873,8 +873,15 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
ts_data->prepare_func = mpegtsmux_prepare_jpeg2000;
ts_data->prepare_data = private_data;
ts_data->free_func = mpegtsmux_free_jpeg2000;
+ } else {
+ MpegTsMuxClass *klass = GST_MPEG_TSMUX_GET_CLASS (mux);
+
+ if (klass->handle_media_type) {
+ st = klass->handle_media_type (mux, mt, ts_data);
+ }
}
+
if (st != TSMUX_ST_RESERVED) {
ts_data->stream = tsmux_create_stream (mux->tsmux, st, ts_data->pid,
ts_data->language);
diff --git a/gst/mpegtsmux/mpegtsmux.h b/gst/mpegtsmux/mpegtsmux.h
index 1ec4107d9..d6272738e 100644
--- a/gst/mpegtsmux/mpegtsmux.h
+++ b/gst/mpegtsmux/mpegtsmux.h
@@ -182,6 +182,7 @@ struct MpegTsMuxClass {
GstElementClass parent_class;
TsMux * (*create_ts_mux) (MpegTsMux *mux);
+ guint (*handle_media_type) (MpegTsMux *mux, const gchar *media_type, MpegTsPadData * ts_data);
};
struct MpegTsPadData {
diff --git a/gst/mpegtsmux/tsmux/tsmux.c b/gst/mpegtsmux/tsmux/tsmux.c
index aa2cc436e..a303e281e 100644
--- a/gst/mpegtsmux/tsmux/tsmux.c
+++ b/gst/mpegtsmux/tsmux/tsmux.c
@@ -561,7 +561,7 @@ tsmux_get_new_pid (TsMux * mux)
/**
* tsmux_create_stream:
* @mux: a #TsMux
- * @stream_type: a #TsMuxStreamType
+ * @stream_type: the stream type
* @pid: the PID of the new stream.
*
* Create a new stream of @stream_type in the muxer session @mux.
@@ -572,7 +572,7 @@ tsmux_get_new_pid (TsMux * mux)
* Returns: a new #TsMuxStream.
*/
TsMuxStream *
-tsmux_create_stream (TsMux * mux, TsMuxStreamType stream_type, guint16 pid,
+tsmux_create_stream (TsMux * mux, guint stream_type, guint16 pid,
gchar * language)
{
TsMuxStream *stream;
diff --git a/gst/mpegtsmux/tsmux/tsmux.h b/gst/mpegtsmux/tsmux/tsmux.h
index 42b877593..0f5713b4f 100644
--- a/gst/mpegtsmux/tsmux/tsmux.h
+++ b/gst/mpegtsmux/tsmux/tsmux.h
@@ -102,7 +102,7 @@ typedef struct TsMux TsMux;
typedef gboolean (*TsMuxWriteFunc) (GstBuffer * buf, void *user_data, gint64 new_pcr);
typedef void (*TsMuxAllocFunc) (GstBuffer ** buf, void *user_data);
-typedef TsMuxStream * (*TsMuxNewStreamFunc) (guint16 new_pid, TsMuxStreamType stream_type, void *user_data);
+typedef TsMuxStream * (*TsMuxNewStreamFunc) (guint16 new_pid, guint stream_type, void *user_data);
struct TsMuxSection {
TsMuxPacketInfo pi;
@@ -215,7 +215,7 @@ void tsmux_resend_si (TsMux *mux);
gboolean tsmux_add_mpegts_si_section (TsMux * mux, GstMpegtsSection * section);
/* stream management */
-TsMuxStream * tsmux_create_stream (TsMux *mux, TsMuxStreamType stream_type, guint16 pid, gchar *language);
+TsMuxStream * tsmux_create_stream (TsMux *mux, guint stream_type, guint16 pid, gchar *language);
TsMuxStream * tsmux_find_stream (TsMux *mux, guint16 pid);
void tsmux_program_add_stream (TsMuxProgram *program, TsMuxStream *stream);
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c
index 7945fc0f9..12397717f 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.c
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.c
@@ -122,7 +122,7 @@ struct TsMuxStreamBuffer
* Returns: a new #TsMuxStream.
*/
TsMuxStream *
-tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
+tsmux_stream_new (guint16 pid, guint stream_type)
{
TsMuxStream *stream = g_slice_new0 (TsMuxStream);
@@ -220,7 +220,7 @@ tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
break;
default:
- g_critical ("Stream type 0x%0x not yet implemented", stream_type);
+ /* Might be a custom stream type implemented by a subclass */
break;
}
@@ -232,6 +232,10 @@ tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
stream->pcr_ref = 0;
stream->next_pcr = -1;
+ stream->get_es_descrs =
+ (TsMuxStreamGetESDescriptorsFunc) tsmux_stream_default_get_es_descrs;
+ stream->get_es_descrs_data = NULL;
+
return stream;
}
@@ -295,6 +299,25 @@ tsmux_stream_set_buffer_release_func (TsMuxStream * stream,
stream->buffer_release = func;
}
+/**
+ * tsmux_stream_set_get_es_descriptors_func:
+ * @stream: a #TsMuxStream
+ * @func: a user callback function
+ * @user_data: user data passed to @func
+ *
+ * Set the callback function and user data to be called when @stream has
+ * to create Elementary Stream Descriptors.
+ */
+void
+tsmux_stream_set_get_es_descriptors_func (TsMuxStream * stream,
+ TsMuxStreamGetESDescriptorsFunc func, void *user_data)
+{
+ g_return_if_fail (stream != NULL);
+
+ stream->get_es_descrs = func;
+ stream->get_es_descrs_data = user_data;
+}
+
/* Advance the current packet stream position by len bytes.
* Mustn't consume more than available in the current packet */
static void
@@ -727,7 +750,7 @@ tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len,
}
/**
- * tsmux_stream_get_es_descrs:
+ * tsmux_stream_default_get_es_descrs:
* @stream: a #TsMuxStream
* @buf: a buffer to hold the ES descriptor
* @len: the length used in @buf
@@ -738,7 +761,7 @@ tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len,
* @buf and @len must be at least #TSMUX_MIN_ES_DESC_LEN.
*/
void
-tsmux_stream_get_es_descrs (TsMuxStream * stream,
+tsmux_stream_default_get_es_descrs (TsMuxStream * stream,
GstMpegtsPMTStream * pmt_stream)
{
GstMpegtsDescriptor *descriptor;
@@ -1040,6 +1063,26 @@ tsmux_stream_get_es_descrs (TsMuxStream * stream,
}
/**
+ * tsmux_stream_get_es_descrs:
+ * @stream: a #TsMuxStream
+ * @buf: a buffer to hold the ES descriptor
+ * @len: the length used in @buf
+ *
+ * Write an Elementary Stream Descriptor for @stream into @buf. the number of
+ * bytes consumed in @buf will be updated in @len.
+ *
+ * @buf and @len must be at least #TSMUX_MIN_ES_DESC_LEN.
+ */
+void
+tsmux_stream_get_es_descrs (TsMuxStream * stream,
+ GstMpegtsPMTStream * pmt_stream)
+{
+ g_return_if_fail (stream->get_es_descrs != NULL);
+
+ return stream->get_es_descrs (stream, pmt_stream, stream->get_es_descrs_data);
+}
+
+/**
* tsmux_stream_pcr_ref:
* @stream: a #TsMuxStream
*
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.h b/gst/mpegtsmux/tsmux/tsmuxstream.h
index 3b160207e..4b60d1fed 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.h
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.h
@@ -91,6 +91,7 @@ typedef enum TsMuxStreamState TsMuxStreamState;
typedef struct TsMuxStreamBuffer TsMuxStreamBuffer;
typedef void (*TsMuxStreamBufferReleaseFunc) (guint8 *data, void *user_data);
+typedef void (*TsMuxStreamGetESDescriptorsFunc) (TsMuxStream *stream, GstMpegtsPMTStream *pmt_stream, void *user_data);
/* Stream type assignments
*
@@ -159,7 +160,7 @@ enum TsMuxStreamState {
struct TsMuxStream {
TsMuxStreamState state;
TsMuxPacketInfo pi;
- TsMuxStreamType stream_type;
+ guint stream_type;
/* stream_id (13818-1) */
guint8 id;
@@ -181,6 +182,10 @@ struct TsMuxStream {
/* helper to release collected buffers */
TsMuxStreamBufferReleaseFunc buffer_release;
+ /* Override or extend the default Elementary Stream descriptors */
+ TsMuxStreamGetESDescriptorsFunc get_es_descrs;
+ void *get_es_descrs_data;
+
/* optional fixed PES size for stream type */
guint16 pes_payload_size;
/* current PES payload size being written */
@@ -232,7 +237,7 @@ struct TsMuxStream {
};
/* stream management */
-TsMuxStream * tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type);
+TsMuxStream * tsmux_stream_new (guint16 pid, guint stream_type);
void tsmux_stream_free (TsMuxStream *stream);
guint16 tsmux_stream_get_pid (TsMuxStream *stream);
@@ -240,6 +245,10 @@ guint16 tsmux_stream_get_pid (TsMuxStream *stream);
void tsmux_stream_set_buffer_release_func (TsMuxStream *stream,
TsMuxStreamBufferReleaseFunc func);
+void tsmux_stream_set_get_es_descriptors_func (TsMuxStream *stream,
+ TsMuxStreamGetESDescriptorsFunc func,
+ void *user_data);
+
/* Add a new buffer to the pool of available bytes. If pts or dts are not -1, they
* indicate the PTS or DTS of the first access unit within this packet */
void tsmux_stream_add_data (TsMuxStream *stream, guint8 *data, guint len,
@@ -252,6 +261,7 @@ gboolean tsmux_stream_is_pcr (TsMuxStream *stream);
gboolean tsmux_stream_at_pes_start (TsMuxStream *stream);
void tsmux_stream_get_es_descrs (TsMuxStream *stream, GstMpegtsPMTStream *pmt_stream);
+void tsmux_stream_default_get_es_descrs (TsMuxStream * stream, GstMpegtsPMTStream * pmt_stream);
gint tsmux_stream_bytes_in_buffer (TsMuxStream *stream);
gint tsmux_stream_bytes_avail (TsMuxStream *stream);