How to play ts stream with specified pid

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

How to play ts stream with specified pid

lessonZhang
Hi all,

I am working on a feature that play specified program in one ts stream with relevant video pid and audio pid,
eg, there is a ts file named test.ts, it has following program info which get from pat&pmt,

program1, video pid=201, audio pid=401,
program2, video pid=202, audio pid=402,
program3, video pid=203, audio pid=403,

it can play out the stream with cmd
#gst-launch-0.10 filesrc location=test.ts ! decodebin ! ffmpegcolorspace ! videoscale ! ximagesink sync=false

but i don't know how to play the specified program, or play with specified pid, can somebody help me?

Kind regards!
lesson
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

Arjen Veenhuizen
Foremost, move to gstreamer 1.0. 0.10 is no longer maintained since a couple of years.

To answer your question, you can use the program-number property of tsdemux:
gst-launch-0.10 filesrc location=test.ts ! tsdemux program-number=xxx ! decodebin ! ffmpegcolorspace ! videoscale ! ximagesink sync=false 
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

lessonZhang
Hi Arjen,

Thanks for your reply!

After modification, i use gst-launch-1.0 to play the file, and it played well,
#gst-launch-1.0 -v filesrc location=test.ts ! decodebin ! videoconvert ! videoscale ! ximagesink sync=false

then add program-number ,
#gst-launch-1.0 -v filesrc location=test.ts ! tsdemux program-number=1 ! decodebin ! videoconvert ! videoscale ! ximagesink sync=false

but it failed,

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstTSDemux:tsdemux0: Internal data stream error.
Additional debug info:
mpegtsbase.c(1307): mpegts_base_loop (): /GstPipeline:pipeline0/GstTSDemux:tsdemux0:
No program activated before EOS
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...



Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

lessonZhang
Hi,

Sorry for disturbing, but the problem is still there.

If i use following cmd,
#gst-launch-1.0 -v filesrc location=test.ts ! tsdemux ! decodebin ! videoconvert ! videoscale ! ximagesink sync=false

it can play video out, and print info

Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink.GstProxyPad:proxypad0: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:sink: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpegvParse:mpegvparse0.GstPad:sink: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpegvParse:mpegvparse0.GstPad:src: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false, parsed=(boolean)true, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)64/45, codec_data=(buffer)000001b32d024033249f23821020202620262c2c2c2c2c2c343034363636343434343636363a3a3a4444443a3a3a36363a3a404044444a4c4a464644464c4c50505060605c5c7070748a8aa7111111151215191919191b1b201d202222222121212324242427272730303029292926262b2b2f2f3232373b39363635363e3e41414152524f4f6565688282a4000001b5148200010000, profile=(string)main, level=(string)main, interlace-mode=(string)mixed
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpeg2dec:mpeg2dec0.GstPad:sink: caps = video/mpeg, mpegversion=(int)2, systemstream=(boolean)false, parsed=(boolean)true, width=(int)720, height=(int)576, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)64/45, codec_data=(buffer)000001b32d024033249f23821020202620262c2c2c2c2c2c343034363636343434343636363a3a3a4444443a3a3a36363a3a404044444a4c4a464644464c4c50505060605c5c7070748a8aa7111111151215191919191b1b201d202222222121212324242427272730303029292926262b2b2f2f3232373b39363635363e3e41414152524f4f6565688282a4000001b5148200010000, profile=(string)main, level=(string)main, interlace-mode=(string)mixed
Redistribute latency...
/GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMpeg2dec:mpeg2dec0.GstPad:src: caps = video/x-raw, format=(string)I420, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)64/45, interlace-mode=(string)mixed, chroma-site=(string)mpeg2, colorimetry=(string)bt601, framerate=(fraction)25/1
/GstPipeline:pipeline0/GstVideoConvert:videoconvert0.GstPad:src: caps = video/x-raw, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)64/45, interlace-mode=(string)mixed, framerate=(fraction)25/1, format=(string)BGRx
/GstPipeline:pipeline0/GstVideoScale:videoscale0.GstPad:src: caps = video/x-raw, width=(int)1024, height=(int)576, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)mixed, framerate=(fraction)25/1, format=(string)BGRx
/GstPipeline:pipeline0/GstXImageSink:ximagesink0.GstPad:sink: caps = video/x-raw, width=(int)1024, height=(int)576, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)mixed, framerate=(fraction)25/1, format=(string)BGRx
/GstPipeline:pipeline0/GstVideoScale:videoscale0.GstPad:sink: caps = video/x-raw, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)64/45, interlace-mode=(string)mixed, framerate=(fraction)25/1, format=(string)BGRx
/GstPipeline:pipeline0/GstVideoConvert:videoconvert0.GstPad:sink: caps = video/x-raw, format=(string)I420, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)64/45, interlace-mode=(string)mixed, chroma-site=(string)mpeg2, colorimetry=(string)bt601, framerate=(fraction)25/1
/GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstDecodePad:src_0.GstProxyPad:proxypad1: caps = video/x-raw, format=(string)I420, width=(int)720, height=(int)576, pixel-aspect-ratio=(fraction)64/45, interlace-mode=(string)mixed, chroma-site=(string)mpeg2, colorimetry=(string)bt601, framerate=(fraction)25/1

but if i add the property "program-number=1", it will return err,
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
ERROR: from element /GstPipeline:pipeline0/GstTSDemux:tsdemux0: Internal data stream error.
Additional debug info:
mpegtsbase.c(1307): mpegts_base_loop (): /GstPipeline:pipeline0/GstTSDemux:tsdemux0:
No program activated before EOS
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

Arjen Veenhuizen
Are you sure that your program number is actually 1? (you can use ffprobe to verify that).
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

lessonZhang
Here is the file information got from ffprobe,

ffprobe version 3.1.3 Copyright (c) 2007-2016 the FFmpeg developers
  built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
  configuration: --enable-memalign-hack --disable-yasm --disable-debug
  libavutil      55. 28.100 / 55. 28.100
  libavcodec     57. 48.101 / 57. 48.101
  libavformat    57. 41.100 / 57. 41.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 47.100 /  6. 47.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  1.100 /  2.  1.100
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[mpeg2video @ 0x275a160] Invalid frame dimensions 0x0.
    Last message repeated 1 times
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[mpeg2video @ 0x275a160] Invalid frame dimensions 0x0.
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[NULL @ 0x2870be0] SPS unavailable in decode_picture_timing
[NULL @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[mpeg2video @ 0x275a160] Invalid frame dimensions 0x0.
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
    Last message repeated 1 times
[mpeg2video @ 0x275a160] Invalid frame dimensions 0x0.
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[mpeg2video @ 0x27744e0] Invalid frame dimensions 0x0.
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] SPS unavailable in decode_picture_timing
[h264 @ 0x2870be0] non-existing PPS 0 referenced
[h264 @ 0x2870be0] decode_slice_header error
[h264 @ 0x2870be0] no frame!
[h264 @ 0x2870be0] Increasing reorder buffer to 2
[mpegts @ 0x2736ba0] PES packet size mismatch
    Last message repeated 1 times
Input #0, mpegts, from '../../test.ts':
  Duration: 00:01:00.28, start: 0.333333, bitrate: 26351 kb/s
  Program 40001
    Metadata:
      service_name    : TVE-HD Pruebas
      service_provider: TVE
    Stream #0:9[0x3e9]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:3[0x44c](spa): Audio: eac3 ([6][0][0][0] / 0x0006), 48000 Hz, stereo, fltp, 128 kb/s
  Program 40002
    Metadata:
      service_name    : tdp Pruebas
      service_provider: RTVE
    Stream #0:0[0x7d1]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x7d2](spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 192 kb/s
  Program 40003
    Metadata:
      service_name    : Pruebas TVE
      service_provider: RTVE
    Stream #0:6[0xbb9]: Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p(tv), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:8[0xbba](spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 192 kb/s
  Program 40005
    Metadata:
      service_name    : Radio Cl醩ica
      service_provider: NoName
    Stream #0:7[0x7da](spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 320 kb/s
  Program 40006
    Metadata:
      service_name    : Radio 3
      service_provider: NoName
    Stream #0:5[0xbc2](spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, s16p, 256 kb/s
  No Program
    Stream #0:2[0x21]: Video: mpeg2video (Main), yuv420p(tv), 720x576 [SAR 16:15 DAR 4:3], 6000 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:4[0x23]: Audio: mp2, 48000 Hz, stereo, s16p, 224 kb/s
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

lessonZhang
I understand where is the problem, the program-number should be the number read from PAT, eg,40001.
i just thought its a logical number from 0~4 , thanks very much.
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

Arjen Veenhuizen
That is indeed what you have to do. Great that you got it working.
Reply | Threaded
Open this post in threaded view
|

Re: How to play ts stream with specified pid

lessonZhang
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);  
}