现有一项目是关于mpeg2传输流和节目流转换的:
在收到传输流包(Transport package)后转换为PES(Package Elementary Stream)再转换为PS(节目流)。
请问有没有关于这个的开源代码或者别的什么资料,实现起来是不是很复杂。我对mpeg完全是个初哥,下了标准(is138181,is138182)看得很是头晕。

解决方案 »

  1.   

    /////////////gstts2ps.h
    #ifndef __GST_TS2PS_H__
    #define __GST_TS2PS_H__#include <gst/gst.h>
    #include <gsttsparse.h>
    #include <mpegtools/transform.h>G_BEGIN_DECLS#define DEFAULT_BUFFERSIZE 4096/* #define's don't like whitespacey bits */
    #define GST_TYPE_TS2PS \
      (gst_ts2ps_get_type())
    #define GST_TS2PS(obj) \
      (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TS2PS,GstTs2Ps))
    #define GST_TS2PS_CLASS(klass) \
      (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TS2PS,GstTs2PsClass))
    #define GST_IS_TS2PS(obj) \
      (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TS2PS))
    #define GST_IS_TS2PS_CLASS(obj) \
      (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TS2PS))typedef struct _GstTs2Ps      GstTs2Ps;
    typedef struct _GstTs2PsClass GstTs2PsClass;struct _GstTs2Ps
    {
      GstTsParse ts_parse;  /* TODO: parse to pes or ps
               PES-only streams currently not supported by the mpegdemuxer
      gboolean ps;  */  ipack pa;
      ipack pv;  
      
      uint8_t* ps_buffer;
      int ps_off;
      gboolean finished;  uint8_t* out_buffer;  
      int buffersize;  uint16_t vpid;
      uint16_t apid;};struct _GstTs2PsClass 
    {
      GstTsParseClass parent_class;
      
      void (*handle_event) (GstTsParse *object, GstEvent *event);
    };
    GType gst_ts2ps_get_type (void);
    gboolean gst_ts2ps_plugin_init (GstPlugin *plugin);G_END_DECLS#endif /* __GST_TS2PS_H__ */
      

  2.   

    /////////gstts2ps.c
    #include "gstts2ps.h"
    #include <gst/gst.h>
    #include <errno.h>
    #include <string.h>
    #include <mpegtools/transform.h>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);
    }
      

  3.   

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

  4.   

    非常感谢楼上提供的代码,请问有没有具体一点得demo,还有哪有传输流文件,一般象dvd,vob得文件应该都是节目流吧