www.pudn.com > gsts2ps.rar > gstts2ps.c


/////////gstts2ps.c    
  #include   "gstts2ps.h"    
  #include       
  #include       
  #include       
  #include       
     
  GST_DEBUG_CATEGORY_STATIC   (gstts2ps_debug);    
  #define   GST_CAT_DEFAULT   (gstts2ps_debug)    
     
  static   GstElementDetails   ts2ps_details   =   {    
      "TS2PS",    
      "Filter/TS2PS",    
      "Mpeg   Transport   Stream   to   Program   Stream   Converter",    
      "P2P-VCR,   C-Lab,   University   of   Paderborn"    
  };    
     
  /*   Object   signals   and   args   */    
  enum   {    
      LAST_SIGNAL    
  };    
     
  /*   Arguments   */    
  enum   {    
      ARG_0,    
      ARG_TS2PS_V_PID,    
      ARG_TS2PS_A_PID,    
      ARG_TS2PS_BUFFERSIZE    
  };    
     
     
  static   GstStaticPadTemplate   ps_src_factory   =    
  GST_STATIC_PAD_TEMPLATE   (    
      "src",    
      GST_PAD_SRC,    
      GST_PAD_ALWAYS,    
      GST_STATIC_CAPS   ("video/mpeg,   "    
              "mpegversion   =   (int)   2,   "    
              "systemstream   =   (boolean)   TRUE"    
      )    
  );    
     
     
  static   void                           gst_ts2ps_base_init             (GstTs2PsClass   *klass);    
  static   void                           gst_ts2ps_class_init             (GstTs2PsClass   *klass);    
  static   void                           gst_ts2ps_init               (GstTs2Ps   *object);    
  static   void                                     gst_ts2ps_dispose                   (GObject   *object);    
  static   void                                     gst_ts2ps_finalize                 (GObject   *object);    
  static   void                           gst_ts2ps_set_property         (GObject   *object,   guint   prop_id,   const   GValue   *value,   GParamSpec   *pspec);    
  static   void                           gst_ts2ps_get_property         (GObject   *object,   guint   prop_id,   GValue   *value,   GParamSpec   *pspec);    
     
  static   GstPadLinkReturn             gst_ts2ps_srcconnect_func   (GstPad   *pad,   GstCaps   *caps,   gboolean   newcaps);    
  //static   GstElementStateReturn   gst_ts2ps_change_state         (GstElement   *element);    
  static   void                                     gst_ts2ps_loop                         (GstElement*   element);    
  GstBuffer   *                                     gst_ts2ps_get                           (GstPad   *   pad);    
  static   void                                     gst_ts2ps_push                         (uint8_t   *buf,   int   count,   void     *p);    
     
  void                                                   gst_ts2ps_parse_payload       (GstTsParse   *ts_parse,   guint8   *data,   int   length);    
  static   void                                     gst_ts2ps_handle_event         (GstTsParse   *ts_parse,   GstEvent   *event);    
     
     
  static   GstTsParseClass   *parent_class   =   NULL;    
     
     
     
  /*    
    ******************************    
    *                                                         *    
    *             Private-Methods               *    
    *                                                     *    
    *                                                         *    
    ******************************    
    */    
     
     
     
     
     
  /*    
    ******************************    
    *                                                         *    
    *             GObject   Related               *    
    *                                                     *    
    *                                                         *    
    ******************************    
    */    
     
     
  GType    
  gst_ts2ps_get_type   (void)    
  {    
      static   GType   gst_ts2ps_type   =   0;    
     
      if   (!gst_ts2ps_type)    
      {    
          static   const   GTypeInfo   ts2ps_info   =    
          {    
              sizeof   (GstTs2PsClass),    
              (GBaseInitFunc)   gst_ts2ps_base_init,    
              NULL,    
              (GClassInitFunc)   gst_ts2ps_class_init,    
              NULL,    
              NULL,    
              sizeof   (GstTs2Ps),    
              0,    
              (GInstanceInitFunc)   gst_ts2ps_init,    
          };    
          gst_ts2ps_type   =   g_type_register_static   (GST_TYPE_TSPARSE,    
              "GstTs2Ps",    
              &ts2ps_info,   0);    
          GST_DEBUG_CATEGORY_INIT   (gstts2ps_debug,   "ts2ps",   0,   "Mpeg   TS   to   PS   Element");    
     
      }    
      return   gst_ts2ps_type;    
  }    
     
  /*   initialize   the   plugin's   class   */    
  static   void    
  gst_ts2ps_base_init   (GstTs2PsClass   *klass)    
  {    
      GObjectClass   *gobject_class;    
      GstElementClass   *element_class   =   (GstElementClass*)   klass;    
     
      gst_element_class_add_pad_template   (element_class,    
  gst_static_pad_template_get   (&ps_src_factory));    
  }    
     
  /*   initialize   the   plugin's   class   */    
  static   void    
  gst_ts2ps_class_init   (GstTs2PsClass   *klass)    
  {    
      GObjectClass   *gobject_class;    
      GstElementClass   *gstelement_class;    
      GstTsParseClass   *ts_parse_class;    
     
      GST_INFO("gst_ts2ps_class_init");    
     
      gobject_class   =   (GObjectClass*)   klass;    
      gstelement_class   =   (GstElementClass*)   klass;    
      ts_parse_class   =   (GstTsParseClass*)   klass;    
     
      parent_class   =   g_type_class_ref   (GST_TYPE_TSPARSE);    
     
      gobject_class->set_property   =   gst_ts2ps_set_property;    
      gobject_class->get_property   =   gst_ts2ps_get_property;    
      gobject_class->dispose   =   gst_ts2ps_dispose;    
      gobject_class->finalize   =   gst_ts2ps_finalize;    
     
      g_object_class_install_property   (gobject_class,   ARG_TS2PS_V_PID,    
        g_param_spec_int   ("vpid",    
            "vpid",    
            "Video   Program   ID",    
            0,   G_MAXINT,   0,    
            G_PARAM_READWRITE)    
        );    
     
      g_object_class_install_property   (gobject_class,   ARG_TS2PS_A_PID,    
        g_param_spec_int   ("apid",    
            "apid",    
            "Audio   Program   ID",    
            0,   G_MAXINT,   0,    
            G_PARAM_READWRITE)    
        );    
     
      g_object_class_install_property   (gobject_class,   ARG_TS2PS_BUFFERSIZE,    
        g_param_spec_int   ("buffersize",    
            "buffersize",    
            "Buffersize   in   bytes",    
            2048,   G_MAXINT,   DEFAULT_BUFFERSIZE,    
            G_PARAM_READWRITE)    
        );    
     
      ts_parse_class->parse_payload   =   gst_ts2ps_parse_payload;    
      ts_parse_class->handle_event   =   gst_ts2ps_handle_event;    
  }    
     
  /*   initialize   the   new   element    
    *   instantiate   pads   and   add   them   to   element    
    *   set   functions    
    *   initialize   structure    
    */    
  static   void    
  gst_ts2ps_init   (GstTs2Ps   *object)    
  {    
      GstTsParse   *ts_parse   =   (GstTsParse*)   object;    
      GST_INFO("gst_ts2ps_init");    
     
      object->buffersize   =   DEFAULT_BUFFERSIZE;    
     
      /*   set   to   something   sane   for   testing   purpose   */    
      //*   3SAT   (Germany)    
      object->apid   =   220;    
      object->vpid   =   210;    
      //*/    
     
      object->ps_buffer   =   g_malloc(object->buffersize);    
      object->ps_off   =   0;    
     
      init_ipack(&object->pa,   2048,   gst_ts2ps_push,   1);    
      init_ipack(&object->pv,   2048,   gst_ts2ps_push,   1);    
     
      /*   Set   private   data   in   packet   to   our   object   */    
      object->pa.data   =   object;    
      object->pv.data   =   object;    
     
         
      gst_element_remove_pad   (GST_ELEMENT   (ts_parse),   ts_parse->srcpad);    
      ts_parse->srcpad   =   gst_pad_new_from_template(    
      gst_static_pad_template_get   (&ps_src_factory),   "src");    
      gst_element_add_pad   (GST_ELEMENT   (ts_parse),   ts_parse->srcpad);    
  }    
 
static   void    
  gst_ts2ps_set_property   (GObject   *_object,   guint   prop_id,    
    const   GValue   *value,   GParamSpec   *pspec)    
  {    
      GstTs2Ps   *object;    
     
      g_return_if_fail   (GST_IS_TS2PS   (_object));    
      object   =   GST_TS2PS   (_object);    
     
      switch   (prop_id)   {    
      case   ARG_TS2PS_V_PID:    
          object->vpid   =   g_value_get_int(value);    
          break;    
      case   ARG_TS2PS_A_PID:    
          object->apid   =   g_value_get_int(value);    
          break;    
      case   ARG_TS2PS_BUFFERSIZE:    
          object->buffersize   =   g_value_get_int(value);    
          g_free(object->ps_buffer);    
          object->ps_buffer   =   g_malloc(object->buffersize);    
          break;    
      default:    
          G_OBJECT_WARN_INVALID_PROPERTY_ID   (object,   prop_id,   pspec);    
      }    
  }    
     
     
  static   void    
  gst_ts2ps_get_property   (GObject   *_object,   guint   prop_id,    
    GValue   *value,   GParamSpec   *pspec)    
  {    
      GstTs2Ps   *object;    
     
      g_return_if_fail   (GST_IS_TS2PS   (_object));    
      object   =   GST_TS2PS   (_object);    
     
      switch   (prop_id)    
      {    
      case   ARG_TS2PS_V_PID:      
          g_value_set_int(value,   object->vpid);    
          break;    
      case   ARG_TS2PS_A_PID:    
          g_value_set_int(value,   object->apid);    
          break;    
      case   ARG_TS2PS_BUFFERSIZE:    
          g_value_set_int(value,   object->buffersize);    
          break;    
      default:    
          G_OBJECT_WARN_INVALID_PROPERTY_ID   (object,   prop_id,   pspec);    
      }    
  }    
     
     
     
  static   void    
  gst_ts2ps_dispose   (GObject   *_object)    
  {    
      GstTs2Ps   *object;    
     
      GST_DEBUG("gst_ts2ps_dispose");    
     
      g_return_if_fail   (GST_IS_TS2PS   (_object));    
      object   =   GST_TS2PS   (_object);    
     
      G_OBJECT_CLASS   (parent_class)->dispose   (_object);    
  }    
     
  static   void    
  gst_ts2ps_finalize   (GObject   *_object)    
  {    
      GstTs2Ps   *object;    
     
      GST_DEBUG("gst_ts2ps_finalize");    
     
      g_return_if_fail   (GST_IS_TS2PS   (_object));    
      object   =   GST_TS2PS   (_object);    
     
      G_OBJECT_CLASS   (parent_class)->finalize   (_object);    
  }    
     
     
     
  /*    
    ******************************    
    *                                                         *    
    *             Plugin   Realisation         *    
    *                                                         *    
    ******************************    
    */    
     
     
  /*   entry   point   to   initialize   the   plug-in    
    *   initialize   the   plug-in   itself    
    *   register   the   element   factories   and   pad   templates    
    *   register   the   features    
    */    
  gboolean    
  gst_ts2ps_plugin_init   (GstPlugin   *plugin)    
  {    
      return   gst_element_register   (plugin,   "ts2ps",   GST_RANK_NONE,   GST_TYPE_TS2PS);    
  }    
     
  static   void    
  gst_ts2ps_handle_event(GstTsParse   *ts_parse,   GstEvent   *event)   {    
      GstTs2Ps   *object   =   GST_TS2PS(ts_parse);    
      gint   etype;    
     
      etype   =   event   ?   GST_EVENT_TYPE   (event)   :   GST_EVENT_EOS;    
         
      switch   (etype)   {    
          case   GST_EVENT_EOS:    
              break;    
          case   GST_EVENT_DISCONTINUOUS:    
              fprintf(stderr,   "gst_ts2ps   handling   discont\n");    
                 
              if   (GST_EVENT_DISCONT_NEW_MEDIA(event))   {    
  init_ipack(&object->pa,   2048,   gst_ts2ps_push,   1);    
  init_ipack(&object->pv,   2048,   gst_ts2ps_push,   1);    
              }    
              break;    
          case   GST_EVENT_FLUSH:    
              break;    
          }    
         
      parent_class->handle_event(object,   event);    
     
  }    
     
     
  /*   The   output   routine   for   sending   a   PS   */    
  static   void      
  gst_ts2ps_push(uint8_t   *buf,   int   count,   void     *p)    
  {    
      GstTs2Ps   *object   =   GST_TS2PS(p);    
      GstBuffer   *gst_buf;    
      GST_DEBUG("%s   (...,   %d,   ...)",   __FUNCTION__,   count);    
     
     
      /*   will   we   fill   the   ps_buffer?   */    
      if   (object->ps_off+count   >=   object->buffersize)   {    
          int   r   =   object->ps_off   +count   -   object->buffersize;    
     
          /*   fill   buffer,   and   make   a   copy   */    
          memcpy(object->ps_buffer   +   object->ps_off,   buf,   count-r);    
          object->out_buffer   =   g_memdup(object->ps_buffer,   object->buffersize);    
     
          /*   take   care   about   the   rest   */    
          memcpy(object->ps_buffer,   buf+count-r,   r);    
          object->ps_off   =   r;    
             
          /*   one   buffer   finished   */    
          object->finished   =   TRUE;    
      }    
      else   {    
          memcpy(object->ps_buffer   +   object->ps_off,   buf,   count);    
          object->ps_off   +=   count;    
      }    
     
         
     
  }    
     
     
  void    
  gst_ts2ps_parse_payload   (GstTsParse   *ts_parse,   guint8   *data,   int   length)    
  {    
      GstTs2Ps   *object   =   GST_TS2PS(ts_parse);    
      GstBuffer*   buf;    
      ipack*   p;    
     
      GST_DEBUG("Data:   0x%x,   Length:   %d",   data,   length);    
     
      if   (ts_parse->transport_error)   {    
          GST_DEBUG("Transport   Error");    
          return;    
      }    
         
      if   (ts_parse->pid   ==   object->vpid)   {    
          GST_DEBUG("Video   PID");    
          p   =   &object->pv;    
      }    
      else   if   (ts_parse->pid   ==   object->apid)   {    
          GST_DEBUG("Audio   PID");    
          p   =   &object->pa;    
      }    
      else   {    
          GST_INFO("Additional   PID   in   TS:   %d\n",   ts_parse->pid);    
          return;    
      }    
         
      if   (ts_parse->unit_start)   {    
          if   (p->plength   ==   MMAX_PLENGTH-6){    
              p->plength   =   p->found-6;    
              p->found   =   0;    
              GST_DEBUG("Unit   Start   pushing???");    
              send_ipack(p);    
              reset_ipack(p);    
          }    
      }    
         
      instant_repack(data,   length,   p);    
         
      if   (object->finished)   {    
          GST_DEBUG   ("pushing   buffer");    
          buf   =   gst_buffer_new();    
          GST_BUFFER_DATA(buf)   =   object->out_buffer;    
          GST_BUFFER_SIZE(buf)   =   object->buffersize;    
          GST_BUFFER_TIMESTAMP(buf)   =   GST_CLOCK_TIME_NONE;    
          gst_pad_push(ts_parse->srcpad,   GST_DATA(buf));    
          object->finished   =   FALSE;    
      }    
  }