mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 08:17:01 +00:00
transcodebin: Implement support for upstream stream selection
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3128>
This commit is contained in:
parent
31acfcd875
commit
bf964f896f
2 changed files with 85 additions and 31 deletions
|
@ -29,8 +29,6 @@
|
||||||
|
|
||||||
#include <gst/pbutils/missing-plugins.h>
|
#include <gst/pbutils/missing-plugins.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstTranscodeBin!sink_%u:
|
* GstTranscodeBin!sink_%u:
|
||||||
*
|
*
|
||||||
|
@ -109,6 +107,7 @@ typedef struct
|
||||||
GstElement *video_filter;
|
GstElement *video_filter;
|
||||||
|
|
||||||
GPtrArray *transcoding_streams;
|
GPtrArray *transcoding_streams;
|
||||||
|
gboolean upstream_selected;
|
||||||
} GstTranscodeBin;
|
} GstTranscodeBin;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -127,6 +126,9 @@ G_DEFINE_TYPE (GstTranscodeBin, gst_transcode_bin, GST_TYPE_BIN);
|
||||||
GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (transcodebin, "transcodebin", GST_RANK_NONE,
|
GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (transcodebin, "transcodebin", GST_RANK_NONE,
|
||||||
GST_TYPE_TRANSCODE_BIN, transcodebin_element_init (plugin));
|
GST_TYPE_TRANSCODE_BIN, transcodebin_element_init (plugin));
|
||||||
|
|
||||||
|
static GstPad *
|
||||||
|
get_encodebin_pad_from_stream (GstTranscodeBin * self, GstStream * stream);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
@ -316,17 +318,52 @@ done:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TranscodingStream *
|
||||||
|
setup_stream (GstTranscodeBin * self, GstStream * stream)
|
||||||
|
{
|
||||||
|
TranscodingStream *res = NULL;
|
||||||
|
GstPad *encodebin_pad = get_encodebin_pad_from_stream (self, stream);
|
||||||
|
|
||||||
|
if (encodebin_pad) {
|
||||||
|
GST_INFO_OBJECT (self,
|
||||||
|
"Going to transcode stream %s (encodebin pad: %" GST_PTR_FORMAT ")",
|
||||||
|
gst_stream_get_stream_id (stream), encodebin_pad);
|
||||||
|
|
||||||
|
res = transcoding_stream_new (stream, encodebin_pad);
|
||||||
|
GST_OBJECT_LOCK (self);
|
||||||
|
g_ptr_array_add (self->transcoding_streams, res);
|
||||||
|
GST_OBJECT_UNLOCK (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_transcode_bin_link_encodebin_pad (GstTranscodeBin * self, GstPad * pad,
|
gst_transcode_bin_link_encodebin_pad (GstTranscodeBin * self, GstPad * pad,
|
||||||
const gchar * stream_id)
|
GstEvent * sstart)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstPadLinkReturn lret;
|
GstPadLinkReturn lret;
|
||||||
TranscodingStream *stream = find_stream (self, stream_id, NULL);
|
const gchar *stream_id;
|
||||||
|
TranscodingStream *stream;
|
||||||
|
|
||||||
|
gst_event_parse_stream_start (sstart, &stream_id);
|
||||||
|
stream = find_stream (self, stream_id, NULL);
|
||||||
|
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
GST_ERROR_OBJECT (self, "%s -> Got not stream, decodebin3 bug?", stream_id);
|
if (self->upstream_selected) {
|
||||||
return;
|
GstStream *tmpstream;
|
||||||
|
|
||||||
|
gst_event_parse_stream (sstart, &tmpstream);
|
||||||
|
|
||||||
|
stream = setup_stream (self, tmpstream);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream) {
|
||||||
|
GST_ERROR_OBJECT (self, "Could not find any stream with ID: %s",
|
||||||
|
stream_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
caps = gst_pad_query_caps (pad, NULL);
|
caps = gst_pad_query_caps (pad, NULL);
|
||||||
|
@ -371,15 +408,13 @@ static GstPadProbeReturn
|
||||||
wait_stream_start_probe (GstPad * pad,
|
wait_stream_start_probe (GstPad * pad,
|
||||||
GstPadProbeInfo * info, GstTranscodeBin * self)
|
GstPadProbeInfo * info, GstTranscodeBin * self)
|
||||||
{
|
{
|
||||||
const gchar *stream_id;
|
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (info->data) != GST_EVENT_STREAM_START)
|
if (GST_EVENT_TYPE (info->data) != GST_EVENT_STREAM_START)
|
||||||
return GST_PAD_PROBE_OK;
|
return GST_PAD_PROBE_OK;
|
||||||
|
|
||||||
gst_event_parse_stream_start (info->data, &stream_id);
|
GST_INFO_OBJECT (self,
|
||||||
GST_INFO_OBJECT (self, "Got pad %" GST_PTR_FORMAT " with stream ID: %s",
|
"Got pad %" GST_PTR_FORMAT " with stream:: %" GST_PTR_FORMAT, pad,
|
||||||
pad, stream_id);
|
info->data);
|
||||||
gst_transcode_bin_link_encodebin_pad (self, pad, stream_id);
|
gst_transcode_bin_link_encodebin_pad (self, pad, info->data);
|
||||||
|
|
||||||
return GST_PAD_PROBE_REMOVE;
|
return GST_PAD_PROBE_REMOVE;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +434,7 @@ decodebin_pad_added_cb (GstElement * decodebin, GstPad * pad,
|
||||||
gst_event_parse_stream_start (sstart_event, &stream_id);
|
gst_event_parse_stream_start (sstart_event, &stream_id);
|
||||||
GST_INFO_OBJECT (self, "Got pad %" GST_PTR_FORMAT " with stream ID: %s",
|
GST_INFO_OBJECT (self, "Got pad %" GST_PTR_FORMAT " with stream ID: %s",
|
||||||
pad, stream_id);
|
pad, stream_id);
|
||||||
gst_transcode_bin_link_encodebin_pad (self, pad, stream_id);
|
gst_transcode_bin_link_encodebin_pad (self, pad, sstart_event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,8 +584,7 @@ caps_is_raw (GstCaps * caps, GstStreamType stype)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPad *
|
static GstPad *
|
||||||
get_encodebin_pad_from_stream (GstTranscodeBin * self,
|
get_encodebin_pad_from_stream (GstTranscodeBin * self, GstStream * stream)
|
||||||
GstEncodingProfile * profile, GstStream * stream)
|
|
||||||
{
|
{
|
||||||
GstCaps *caps = gst_stream_get_caps (stream);
|
GstCaps *caps = gst_stream_get_caps (stream);
|
||||||
GstPad *sinkpad = get_encodebin_pad_for_caps (self, caps);
|
GstPad *sinkpad = get_encodebin_pad_for_caps (self, caps);
|
||||||
|
@ -597,22 +631,9 @@ select_stream_cb (GstElement * decodebin,
|
||||||
|
|
||||||
for (i = 0; i < gst_stream_collection_get_size (collection); i++) {
|
for (i = 0; i < gst_stream_collection_get_size (collection); i++) {
|
||||||
GstStream *tmpstream = gst_stream_collection_get_stream (collection, i);
|
GstStream *tmpstream = gst_stream_collection_get_stream (collection, i);
|
||||||
GstPad *encodebin_pad =
|
|
||||||
get_encodebin_pad_from_stream (self, self->profile, tmpstream);
|
|
||||||
|
|
||||||
if (encodebin_pad) {
|
if (setup_stream (self, tmpstream) && stream == tmpstream)
|
||||||
if (stream == tmpstream)
|
transcode_stream = TRUE;
|
||||||
transcode_stream = TRUE;
|
|
||||||
|
|
||||||
GST_INFO_OBJECT (self,
|
|
||||||
"Going to transcode stream %s (encodebin pad: %" GST_PTR_FORMAT,
|
|
||||||
gst_stream_get_stream_id (tmpstream), encodebin_pad);
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (self);
|
|
||||||
g_ptr_array_add (self->transcoding_streams,
|
|
||||||
transcoding_stream_new (tmpstream, encodebin_pad));
|
|
||||||
GST_OBJECT_UNLOCK (self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_OBJECT_LOCK (self);
|
GST_OBJECT_LOCK (self);
|
||||||
|
@ -737,6 +758,38 @@ remove_all_children (GstTranscodeBin * self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
sink_event_function (GstPad * sinkpad, GstTranscodeBin * self, GstEvent * event)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_STREAM_START:
|
||||||
|
{
|
||||||
|
GstQuery *q = gst_query_new_selectable ();
|
||||||
|
|
||||||
|
/* Query whether upstream can handle stream selection or not */
|
||||||
|
if (gst_pad_peer_query (sinkpad, q)) {
|
||||||
|
GST_FIXME_OBJECT (self, "We force `transcodebin` to upstream selection"
|
||||||
|
" mode if *any* of the inputs is. This means things might break if"
|
||||||
|
" there's a mix");
|
||||||
|
gst_query_parse_selectable (q, &self->upstream_selected);
|
||||||
|
GST_DEBUG_OBJECT (sinkpad, "Upstream is selectable : %d",
|
||||||
|
self->upstream_selected);
|
||||||
|
} else {
|
||||||
|
self->upstream_selected = FALSE;
|
||||||
|
GST_DEBUG_OBJECT (sinkpad, "Upstream does not handle SELECTABLE query");
|
||||||
|
}
|
||||||
|
gst_query_unref (q);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gst_pad_event_default (sinkpad, GST_OBJECT (self), event);
|
||||||
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_transcode_bin_change_state (GstElement * element, GstStateChange transition)
|
gst_transcode_bin_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -851,6 +904,7 @@ gst_transcode_bin_request_pad (GstElement * element, GstPadTemplate * temp,
|
||||||
}
|
}
|
||||||
|
|
||||||
gpad = gst_ghost_pad_new_from_template (name, decodebin_pad, temp);
|
gpad = gst_ghost_pad_new_from_template (name, decodebin_pad, temp);
|
||||||
|
gst_pad_set_event_function (gpad, (GstPadEventFunction) sink_event_function);
|
||||||
gst_element_add_pad (element, GST_PAD (gpad));
|
gst_element_add_pad (element, GST_PAD (gpad));
|
||||||
gst_object_unref (decodebin_pad);
|
gst_object_unref (decodebin_pad);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <gst/pbutils/missing-plugins.h>
|
#include <gst/pbutils/missing-plugins.h>
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_transcodebin_debug);
|
GST_DEBUG_CATEGORY (gst_transcodebin_debug);
|
||||||
#define GST_CAT_DEFAULT gst_transcodebin_debug
|
#define GST_CAT_DEFAULT gst_transcodebin_debug
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue