How to play ts stream with specified pid
lessonZhang
176237766 at qq.com
Fri Sep 2 09:47:54 UTC 2016
Then i implement the above workflow in c code, and found that if play video
only, it can work as expect, but when play video and audio at same time, it
will return err:
Received new pad 'video_07d1' from 'mpg-demux':
Link succeeded (type 'video/mpeg').
Received new pad 'src_0' from 'mpeg-decoder':
Link succeeded (type 'video/x-raw').
Received new pad 'audio_07d2' from 'mpg-demux':
Link succeeded (type 'audio/mpeg').
Error: Internal data stream error.
Debug details: mpegtsbase.c(1311): mpegts_base_loop (): /GstPipeline:VIDEO
PLAYER/GstTSDemux:mpg-demux:
stream stopped, reason not-negotiated
below the code:
#include<gst/gst.h>
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer
data);
static void on_decpad_added(GstElement *element, GstPad *pad );
static void on_dmxpad_added(GstElement *element, GstPad *pad ) ;
GstElement *pipeline, *src, *demux, *decoderv, *sinkv, *decodera, *convertv,
*convert, *resample, *sinka;
GstElement *queueA, *queueV;
int main(int argc, char *argv[])
{
GstStateChangeReturn ret;
GMainLoop *loop;
GstBus *bus;
/*initialization*/
gst_init(&argc,&argv);
loop = g_main_loop_new(NULL, FALSE);
if(argc != 2)
{
g_print("Usage: %s <mpg/mpeg video file>", argv[0]);
return -1;
}
pipeline = gst_pipeline_new("VIDEO PLAYER");
bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
gst_bus_add_watch(bus, bus_call, loop);
gst_object_unref (bus);
src = gst_element_factory_make("filesrc", "filesource");
demux = gst_element_factory_make("tsdemux", "mpg-demux");
g_object_set (G_OBJECT (demux), "program-number", 40002, NULL); //the
program number get from PAT
/*Gstreamer video elements*/
decoderv = gst_element_factory_make("decodebin", "mpeg-decoder");
convertv = gst_element_factory_make("videoconvert", "video-convert");
sinkv = gst_element_factory_make("xvimagesink", "video-out");
if(!decoderv || !sinkv)
{
g_print("\nthe video could not playback\n");
return -1;
}
/*Gstreamer audio elements*/
decodera = gst_element_factory_make("mad", "decoder-audio");
convert = gst_element_factory_make("audioconvert", "a-convert");
resample = gst_element_factory_make("audioresample", "a-resample");
sinka = gst_element_factory_make("alsasink", "play audio");
if(!decodera || !convert || !resample || !sinka)
{
g_print("\nthe audio could not playback\n");
return -1;
}
queueA = gst_element_factory_make("queue", "queue-audio");
queueV = gst_element_factory_make("queue", "queue-video");
g_object_set (G_OBJECT (src), "location", argv[1], NULL);
//gst_bin_add_many(GST_BIN(pipeline), src, demux, queueV, decoderv,
convertv,sinkv, NULL); //decode video only
gst_bin_add_many(GST_BIN(pipeline), src, demux, queueV, decoderv,
convertv,sinkv,
queueA, decodera,convert, resample, sinka, NULL);
//link video source
gst_element_link (src, demux);
//gst_element_link (queueV, decoderv);
gst_element_link (convertv, sinkv);
// gst_element_link (queueA, convert);
//link audio source
gst_element_link (decodera, convert);
gst_element_link (convert, resample);
gst_element_link (resample, sinka);
g_signal_connect (demux, "pad-added",G_CALLBACK(on_dmxpad_added),demux);
g_signal_connect (decoderv,
"pad-added",G_CALLBACK(on_decpad_added),decoderv);
/* run */
ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE)
{
GstMessage *msg;
g_print ("Failed to start up pipeline!\n");
/* check if there is an error message with details on the bus */
msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
if (msg) {
GError *err = NULL;
g_print("\nDISPLAY ERROR:\n");
gst_message_parse_error (msg, &err, NULL);
g_print ("ERROR: %s\n", err->message);
g_error_free (err);
gst_message_unref (msg);
}
return -1;
}
g_main_loop_run (loop);
/* clean up */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer
data)
{
GMainLoop *loop = data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End-of-stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR: {
gchar *debug = NULL;
GError *err = NULL;
gst_message_parse_error (msg, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
if (debug) {
g_print ("Debug details: %s\n", debug);
g_free (debug);
}
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
static void on_dmxpad_added(GstElement *element, GstPad *pad )
{
GstPad *sink_padv = gst_element_get_static_pad (decoderv, "sink");
GstPad *sink_pada = gst_element_get_static_pad (decodera, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;
g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (pad),
GST_ELEMENT_NAME (element));
/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps (pad);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (g_str_has_prefix (new_pad_type, "video")) {
/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_padv)) {
g_print (" We are already linked. Ignoring.\n");
goto exit;
}
/* Attempt the link */
ret = gst_pad_link (pad, sink_padv);
}
else if (g_str_has_prefix (new_pad_type, "audio")) {
/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pada)) {
g_print (" We are already linked. Ignoring.\n");
goto exit;
}
/* Attempt the link */
ret = gst_pad_link (pad, sink_pada);
}
if (GST_PAD_LINK_FAILED (ret)) {
g_print (" Type is '%s' but link failed.\n", new_pad_type);
} else {
g_print (" Link succeeded (type '%s').\n", new_pad_type);
}
exit:
/* Unreference the new pad's caps, if we got them */
if (new_pad_caps != NULL)
gst_caps_unref (new_pad_caps);
/* Unreference the sink pad */
gst_object_unref (sink_padv);
gst_object_unref (sink_pada);
}
static void on_decpad_added(GstElement *element, GstPad *pad )
{
GstPad *sink_pad = gst_element_get_static_pad (convertv, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;
g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (pad),
GST_ELEMENT_NAME (element));
/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pad)) {
g_print (" We are already linked. Ignoring.\n");
goto exit;
}
/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps (pad);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "video")) {
g_print (" It has type '%s' which is not raw audio. Ignoring.\n",
new_pad_type);
goto exit;
}
/* Attempt the link */
ret = gst_pad_link (pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
g_print (" Type is '%s' but link failed.\n", new_pad_type);
} else {
g_print (" Link succeeded (type '%s').\n", new_pad_type);
}
exit:
/* Unreference the new pad's caps, if we got them */
if (new_pad_caps != NULL)
gst_caps_unref (new_pad_caps);
/* Unreference the sink pad */
gst_object_unref (sink_pad);
}
--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/How-to-play-ts-stream-with-specified-pid-tp4679308p4679374.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
More information about the gstreamer-devel
mailing list