mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-30 02:58:24 +00:00
mpegtsmux: misc code cleanups and refactoring
This commit is contained in:
parent
d97d49d237
commit
30c782e062
1 changed files with 122 additions and 109 deletions
|
@ -377,130 +377,115 @@ release_buffer_cb (guint8 * data, void *user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data, GstPad * pad)
|
mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_ERROR;
|
GstFlowReturn ret = GST_FLOW_ERROR;
|
||||||
GstCaps *caps = gst_pad_get_negotiated_caps (pad);
|
GstCaps *caps;
|
||||||
GstStructure *s;
|
GstStructure *s;
|
||||||
|
GstPad *pad;
|
||||||
|
TsMuxStreamType st = TSMUX_ST_RESERVED;
|
||||||
|
const gchar *mt;
|
||||||
|
const GValue *value = NULL;
|
||||||
|
GstBuffer *codec_data = NULL;
|
||||||
|
|
||||||
if (caps == NULL) {
|
pad = ts_data->collect.pad;
|
||||||
GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing");
|
caps = gst_pad_get_negotiated_caps (pad);
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
if (caps == NULL)
|
||||||
}
|
goto not_negotiated;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pad, "Creating stream with PID 0x%04x for caps %"
|
||||||
|
GST_PTR_FORMAT, caps);
|
||||||
|
|
||||||
s = gst_caps_get_structure (caps, 0);
|
s = gst_caps_get_structure (caps, 0);
|
||||||
g_return_val_if_fail (s != NULL, FALSE);
|
g_return_val_if_fail (s != NULL, FALSE);
|
||||||
|
|
||||||
if (gst_structure_has_name (s, "video/x-dirac")) {
|
mt = gst_structure_get_name (s);
|
||||||
GST_DEBUG_OBJECT (pad, "Creating Dirac stream with PID 0x%04x",
|
value = gst_structure_get_value (s, "codec_data");
|
||||||
ts_data->pid);
|
if (value != NULL)
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_VIDEO_DIRAC,
|
codec_data = gst_value_get_buffer (value);
|
||||||
ts_data->pid);
|
|
||||||
} else if (gst_structure_has_name (s, "audio/x-ac3")) {
|
if (strcmp (mt, "video/x-dirac") == 0) {
|
||||||
GST_DEBUG_OBJECT (pad, "Creating AC3 stream with PID 0x%04x", ts_data->pid);
|
st = TSMUX_ST_VIDEO_DIRAC;
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_PS_AUDIO_AC3,
|
} else if (strcmp (mt, "audio/x-ac3") == 0) {
|
||||||
ts_data->pid);
|
st = TSMUX_ST_PS_AUDIO_AC3;
|
||||||
} else if (gst_structure_has_name (s, "audio/x-dts")) {
|
} else if (strcmp (mt, "audio/x-dts") == 0) {
|
||||||
GST_DEBUG_OBJECT (pad, "Creating DTS stream with PID 0x%04x", ts_data->pid);
|
st = TSMUX_ST_PS_AUDIO_DTS;
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_PS_AUDIO_DTS,
|
} else if (strcmp (mt, "audio/x-lpcm") == 0) {
|
||||||
ts_data->pid);
|
st = TSMUX_ST_PS_AUDIO_LPCM;
|
||||||
} else if (gst_structure_has_name (s, "audio/x-lpcm")) {
|
} else if (strcmp (mt, "video/x-h264") == 0) {
|
||||||
GST_DEBUG_OBJECT (pad, "Creating LPCM stream with PID 0x%04x",
|
st = TSMUX_ST_VIDEO_H264;
|
||||||
ts_data->pid);
|
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_PS_AUDIO_LPCM,
|
|
||||||
ts_data->pid);
|
|
||||||
} else if (gst_structure_has_name (s, "video/x-h264")) {
|
|
||||||
const GValue *value;
|
|
||||||
GST_DEBUG_OBJECT (pad, "Creating H264 stream with PID 0x%04x",
|
|
||||||
ts_data->pid);
|
|
||||||
/* Codec data contains SPS/PPS which need to go in stream for valid ES */
|
/* Codec data contains SPS/PPS which need to go in stream for valid ES */
|
||||||
value = gst_structure_get_value (s, "codec_data");
|
if (codec_data) {
|
||||||
if (value) {
|
|
||||||
ts_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
|
|
||||||
GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
|
GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
|
||||||
GST_BUFFER_SIZE (ts_data->codec_data));
|
GST_BUFFER_SIZE (codec_data));
|
||||||
|
ts_data->codec_data = gst_buffer_ref (codec_data);
|
||||||
ts_data->prepare_func = mpegtsmux_prepare_h264;
|
ts_data->prepare_func = mpegtsmux_prepare_h264;
|
||||||
ts_data->free_func = mpegtsmux_free_h264;
|
ts_data->free_func = mpegtsmux_free_h264;
|
||||||
} else {
|
} else {
|
||||||
ts_data->codec_data = NULL;
|
ts_data->codec_data = NULL;
|
||||||
}
|
}
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_VIDEO_H264,
|
} else if (strcmp (mt, "audio/mpeg") == 0) {
|
||||||
ts_data->pid);
|
|
||||||
} else if (gst_structure_has_name (s, "audio/mpeg")) {
|
|
||||||
gint mpegversion;
|
gint mpegversion;
|
||||||
|
|
||||||
if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
|
if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
|
||||||
GST_ELEMENT_ERROR (pad, STREAM, FORMAT,
|
GST_ERROR_OBJECT (pad, "caps missing mpegversion");
|
||||||
("Invalid data format presented"),
|
goto not_negotiated;
|
||||||
("Caps with type audio/mpeg did not have mpegversion"));
|
|
||||||
goto beach;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mpegversion) {
|
switch (mpegversion) {
|
||||||
case 1:
|
case 1:
|
||||||
GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 1 stream with "
|
st = TSMUX_ST_AUDIO_MPEG1;
|
||||||
"PID 0x%04x", ts_data->pid);
|
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_AUDIO_MPEG1,
|
|
||||||
ts_data->pid);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 2 stream with "
|
st = TSMUX_ST_AUDIO_MPEG2;
|
||||||
"PID 0x%04x", ts_data->pid);
|
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_AUDIO_MPEG2,
|
|
||||||
ts_data->pid);
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
const GValue *value;
|
st = TSMUX_ST_AUDIO_AAC;
|
||||||
/* Codec data contains SPS/PPS which need to go in stream for valid ES */
|
if (codec_data) {
|
||||||
value = gst_structure_get_value (s, "codec_data");
|
|
||||||
if (value) {
|
|
||||||
ts_data->codec_data = gst_buffer_ref (gst_value_get_buffer (value));
|
|
||||||
GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
|
GST_DEBUG_OBJECT (pad, "we have additional codec data (%d bytes)",
|
||||||
GST_BUFFER_SIZE (ts_data->codec_data));
|
GST_BUFFER_SIZE (codec_data));
|
||||||
|
ts_data->codec_data = gst_buffer_ref (codec_data);
|
||||||
ts_data->prepare_func = mpegtsmux_prepare_aac;
|
ts_data->prepare_func = mpegtsmux_prepare_aac;
|
||||||
} else {
|
} else {
|
||||||
ts_data->codec_data = NULL;
|
ts_data->codec_data = NULL;
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (pad, "Creating MPEG Audio, version 4 stream with "
|
|
||||||
"PID 0x%04x", ts_data->pid);
|
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_AUDIO_AAC,
|
|
||||||
ts_data->pid);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
|
GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
|
||||||
goto beach;
|
goto not_negotiated;
|
||||||
}
|
}
|
||||||
} else if (gst_structure_has_name (s, "video/mpeg")) {
|
} else if (strcmp (mt, "video/mpeg") == 0) {
|
||||||
gint mpegversion;
|
gint mpegversion;
|
||||||
|
|
||||||
if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
|
if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) {
|
||||||
GST_ELEMENT_ERROR (mux, STREAM, FORMAT,
|
GST_ERROR_OBJECT (pad, "caps missing mpegversion");
|
||||||
("Invalid data format presented"),
|
goto not_negotiated;
|
||||||
("Caps with type video/mpeg did not have mpegversion"));
|
|
||||||
goto beach;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpegversion == 1) {
|
switch (mpegversion) {
|
||||||
GST_DEBUG_OBJECT (pad,
|
case 1:
|
||||||
"Creating MPEG Video, version 1 stream with PID 0x%04x",
|
st = TSMUX_ST_VIDEO_MPEG1;
|
||||||
ts_data->pid);
|
break;
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_VIDEO_MPEG1,
|
case 2:
|
||||||
ts_data->pid);
|
st = TSMUX_ST_VIDEO_MPEG2;
|
||||||
} else if (mpegversion == 2) {
|
break;
|
||||||
GST_DEBUG_OBJECT (pad,
|
case 4:
|
||||||
"Creating MPEG Video, version 2 stream with PID 0x%04x",
|
st = TSMUX_ST_VIDEO_MPEG4;
|
||||||
ts_data->pid);
|
break;
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_VIDEO_MPEG2,
|
default:
|
||||||
ts_data->pid);
|
GST_WARNING_OBJECT (pad, "unsupported mpegversion %d", mpegversion);
|
||||||
} else {
|
goto not_negotiated;
|
||||||
GST_DEBUG_OBJECT (pad,
|
|
||||||
"Creating MPEG Video, version 4 stream with PID 0x%04x",
|
|
||||||
ts_data->pid);
|
|
||||||
ts_data->stream = tsmux_create_stream (mux->tsmux, TSMUX_ST_VIDEO_MPEG4,
|
|
||||||
ts_data->pid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (st != TSMUX_ST_RESERVED) {
|
||||||
|
ts_data->stream = tsmux_create_stream (mux->tsmux, st, ts_data->pid);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (pad, "Failed to determine stream type");
|
||||||
|
}
|
||||||
|
|
||||||
if (ts_data->stream != NULL) {
|
if (ts_data->stream != NULL) {
|
||||||
gst_structure_get_int (s, "rate", &ts_data->stream->audio_sampling);
|
gst_structure_get_int (s, "rate", &ts_data->stream->audio_sampling);
|
||||||
gst_structure_get_int (s, "channels", &ts_data->stream->audio_channels);
|
gst_structure_get_int (s, "channels", &ts_data->stream->audio_channels);
|
||||||
|
@ -512,9 +497,17 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data, GstPad * pad)
|
||||||
ret = GST_FLOW_OK;
|
ret = GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
beach:
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
not_negotiated:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (pad, "Sink pad caps were not set before pushing");
|
||||||
|
if (caps)
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -564,21 +557,27 @@ mpegtsmux_create_streams (MpegTsMux * mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts_data->stream == NULL) {
|
if (ts_data->stream == NULL) {
|
||||||
ret = mpegtsmux_create_stream (mux, ts_data, c_data->pad);
|
ret = mpegtsmux_create_stream (mux, ts_data);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto no_stream;
|
goto no_stream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
no_program:
|
no_program:
|
||||||
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
{
|
||||||
("Could not create new program"), (NULL));
|
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
||||||
return GST_FLOW_ERROR;
|
("Could not create new program"), (NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
no_stream:
|
no_stream:
|
||||||
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
{
|
||||||
("Could not create handler for stream"), (NULL));
|
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
||||||
return ret;
|
("Could not create handler for stream"), (NULL));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static MpegTsPadData *
|
static MpegTsPadData *
|
||||||
|
@ -872,13 +871,8 @@ mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
|
||||||
gint64 pts = -1;
|
gint64 pts = -1;
|
||||||
gboolean delta = TRUE;
|
gboolean delta = TRUE;
|
||||||
|
|
||||||
if (prog == NULL) {
|
if (prog == NULL)
|
||||||
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
goto no_program;
|
||||||
("Stream on pad %" GST_PTR_FORMAT
|
|
||||||
" is not associated with any program", COLLECT_DATA_PAD (best)),
|
|
||||||
(NULL));
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) {
|
if (mux->force_key_unit_event != NULL && best->stream->is_video_stream) {
|
||||||
GstEvent *event;
|
GstEvent *event;
|
||||||
|
@ -968,8 +962,20 @@ mpegtsmux_collected (GstCollectPads2 * pads, MpegTsMux * mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
write_fail:
|
write_fail:
|
||||||
return mux->last_flow_ret;
|
{
|
||||||
|
return mux->last_flow_ret;
|
||||||
|
}
|
||||||
|
no_program:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (mux, STREAM, MUX,
|
||||||
|
("Stream on pad %" GST_PTR_FORMAT
|
||||||
|
" is not associated with any program", COLLECT_DATA_PAD (best)),
|
||||||
|
(NULL));
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPad *
|
static GstPad *
|
||||||
|
@ -1012,21 +1018,28 @@ mpegtsmux_request_new_pad (GstElement * element,
|
||||||
|
|
||||||
return pad;
|
return pad;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
stream_exists:
|
stream_exists:
|
||||||
GST_ELEMENT_ERROR (element, STREAM, MUX, ("Duplicate PID requested"), (NULL));
|
{
|
||||||
return NULL;
|
GST_ELEMENT_ERROR (element, STREAM, MUX, ("Duplicate PID requested"),
|
||||||
|
(NULL));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
could_not_add:
|
could_not_add:
|
||||||
GST_ELEMENT_ERROR (element, STREAM, FAILED,
|
{
|
||||||
("Internal data stream error."), ("Could not add pad to element"));
|
GST_ELEMENT_ERROR (element, STREAM, FAILED,
|
||||||
gst_collect_pads2_remove_pad (mux->collect, pad);
|
("Internal data stream error."), ("Could not add pad to element"));
|
||||||
gst_object_unref (pad);
|
gst_collect_pads2_remove_pad (mux->collect, pad);
|
||||||
return NULL;
|
gst_object_unref (pad);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pad_failure:
|
pad_failure:
|
||||||
GST_ELEMENT_ERROR (element, STREAM, FAILED,
|
{
|
||||||
("Internal data stream error."), ("Could not add pad to collectpads"));
|
GST_ELEMENT_ERROR (element, STREAM, FAILED,
|
||||||
gst_object_unref (pad);
|
("Internal data stream error."), ("Could not add pad to collectpads"));
|
||||||
return NULL;
|
gst_object_unref (pad);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in a new issue