gst_plugins_base/gst/gdp/gstgdppay.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    19 
    19 
    20 /**
    20 /**
    21  * SECTION:element-gdppay
    21  * SECTION:element-gdppay
    22  * @see_also: gdpdepay
    22  * @see_also: gdpdepay
    23  *
    23  *
    24  * <refsect2>
       
    25  * <para>
       
    26  * This element payloads GStreamer buffers and events using the
    24  * This element payloads GStreamer buffers and events using the
    27  * GStreamer Data Protocol.
    25  * GStreamer Data Protocol.
    28  * </para>
    26  *
    29  * <para>
    27  * <refsect2>
    30  * <programlisting>
    28  * |[
    31  * gst-launch -v -m videotestsrc num-buffers=50 ! gdppay ! filesink location=test.gdp
    29  * gst-launch -v -m videotestsrc num-buffers=50 ! gdppay ! filesink location=test.gdp
    32  * </programlisting>
    30  * ]| This pipeline creates a serialized video stream that can be played back
    33  * This pipeline creates a serialized video stream that can be played back
       
    34  * with the example shown in gdpdepay.
    31  * with the example shown in gdpdepay.
    35  * </para>
       
    36  * </refsect2>
    32  * </refsect2>
    37  */
    33  */
    38 
    34 
    39 #ifdef HAVE_CONFIG_H
    35 #ifdef HAVE_CONFIG_H
    40 #include "config.h"
    36 #include "config.h"
    84 
    80 
    85 GST_BOILERPLATE_FULL (GstGDPPay, gst_gdp_pay, GstElement,
    81 GST_BOILERPLATE_FULL (GstGDPPay, gst_gdp_pay, GstElement,
    86     GST_TYPE_ELEMENT, _do_init);
    82     GST_TYPE_ELEMENT, _do_init);
    87 
    83 
    88 static void gst_gdp_pay_reset (GstGDPPay * this);
    84 static void gst_gdp_pay_reset (GstGDPPay * this);
       
    85 
    89 static GstFlowReturn gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer);
    86 static GstFlowReturn gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer);
    90 
    87 
    91 static gboolean gst_gdp_pay_src_event (GstPad * pad, GstEvent * event);
    88 static gboolean gst_gdp_pay_src_event (GstPad * pad, GstEvent * event);
       
    89 
    92 static gboolean gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event);
    90 static gboolean gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event);
    93 
    91 
    94 static GstStateChangeReturn gst_gdp_pay_change_state (GstElement *
    92 static GstStateChangeReturn gst_gdp_pay_change_state (GstElement *
    95     element, GstStateChange transition);
    93     element, GstStateChange transition);
    96 
    94 
   116 
   114 
   117 static void
   115 static void
   118 gst_gdp_pay_class_init (GstGDPPayClass * klass)
   116 gst_gdp_pay_class_init (GstGDPPayClass * klass)
   119 {
   117 {
   120   GObjectClass *gobject_class;
   118   GObjectClass *gobject_class;
       
   119 
   121   GstElementClass *gstelement_class;
   120   GstElementClass *gstelement_class;
   122 
   121 
   123   gobject_class = (GObjectClass *) klass;
   122   gobject_class = (GObjectClass *) klass;
   124   gstelement_class = (GstElementClass *) klass;
   123   gstelement_class = (GstElementClass *) klass;
   125 
   124 
   128   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gdp_pay_finalize);
   127   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gdp_pay_finalize);
   129 
   128 
   130   g_object_class_install_property (gobject_class, PROP_CRC_HEADER,
   129   g_object_class_install_property (gobject_class, PROP_CRC_HEADER,
   131       g_param_spec_boolean ("crc-header", "CRC Header",
   130       g_param_spec_boolean ("crc-header", "CRC Header",
   132           "Calculate and store a CRC checksum on the header",
   131           "Calculate and store a CRC checksum on the header",
   133           DEFAULT_CRC_HEADER, G_PARAM_READWRITE));
   132           DEFAULT_CRC_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   134   g_object_class_install_property (gobject_class, PROP_CRC_PAYLOAD,
   133   g_object_class_install_property (gobject_class, PROP_CRC_PAYLOAD,
   135       g_param_spec_boolean ("crc-payload", "CRC Payload",
   134       g_param_spec_boolean ("crc-payload", "CRC Payload",
   136           "Calculate and store a CRC checksum on the payload",
   135           "Calculate and store a CRC checksum on the payload",
   137           DEFAULT_CRC_PAYLOAD, G_PARAM_READWRITE));
   136           DEFAULT_CRC_PAYLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   138   g_object_class_install_property (gobject_class, PROP_VERSION,
   137   g_object_class_install_property (gobject_class, PROP_VERSION,
   139       g_param_spec_enum ("version", "Version",
   138       g_param_spec_enum ("version", "Version",
   140           "Version of the GStreamer Data Protocol",
   139           "Version of the GStreamer Data Protocol",
   141           GST_TYPE_DP_VERSION, DEFAULT_VERSION, G_PARAM_READWRITE));
   140           GST_TYPE_DP_VERSION, DEFAULT_VERSION,
       
   141           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   142 
   142 
   143   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_gdp_pay_change_state);
   143   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_gdp_pay_change_state);
   144 }
   144 }
   145 
   145 
   146 static void
   146 static void
   187   /* clear the queued buffers */
   187   /* clear the queued buffers */
   188   while (this->queue) {
   188   while (this->queue) {
   189     GstBuffer *buffer;
   189     GstBuffer *buffer;
   190 
   190 
   191     buffer = GST_BUFFER_CAST (this->queue->data);
   191     buffer = GST_BUFFER_CAST (this->queue->data);
   192     GST_DEBUG_OBJECT (this, "Pushing queued GDP buffer %p", buffer);
       
   193 
   192 
   194     /* delete buffer from queue now */
   193     /* delete buffer from queue now */
   195     this->queue = g_list_delete_link (this->queue, this->queue);
   194     this->queue = g_list_delete_link (this->queue, this->queue);
       
   195 
       
   196     gst_buffer_unref (buffer);
   196   }
   197   }
   197   if (this->caps) {
   198   if (this->caps) {
   198     gst_caps_unref (this->caps);
   199     gst_caps_unref (this->caps);
   199     this->caps = NULL;
   200     this->caps = NULL;
   200   }
   201   }
   225 
   226 
   226 static GstBuffer *
   227 static GstBuffer *
   227 gst_gdp_buffer_from_caps (GstGDPPay * this, GstCaps * caps)
   228 gst_gdp_buffer_from_caps (GstGDPPay * this, GstCaps * caps)
   228 {
   229 {
   229   GstBuffer *headerbuf;
   230   GstBuffer *headerbuf;
       
   231 
   230   GstBuffer *payloadbuf;
   232   GstBuffer *payloadbuf;
       
   233 
   231   guint8 *header, *payload;
   234   guint8 *header, *payload;
       
   235 
   232   guint len;
   236   guint len;
   233 
   237 
   234   if (!this->packetizer->packet_from_caps (caps, this->header_flag, &len,
   238   if (!this->packetizer->packet_from_caps (caps, this->header_flag, &len,
   235           &header, &payload))
   239           &header, &payload))
   236     goto packet_failed;
   240     goto packet_failed;
   257 
   261 
   258 static GstBuffer *
   262 static GstBuffer *
   259 gst_gdp_pay_buffer_from_buffer (GstGDPPay * this, GstBuffer * buffer)
   263 gst_gdp_pay_buffer_from_buffer (GstGDPPay * this, GstBuffer * buffer)
   260 {
   264 {
   261   GstBuffer *headerbuf;
   265   GstBuffer *headerbuf;
       
   266 
   262   guint8 *header;
   267   guint8 *header;
       
   268 
   263   guint len;
   269   guint len;
   264 
   270 
   265   if (!this->packetizer->header_from_buffer (buffer, this->header_flag, &len,
   271   if (!this->packetizer->header_from_buffer (buffer, this->header_flag, &len,
   266           &header))
   272           &header))
   267     goto no_buffer;
   273     goto no_buffer;
   286 
   292 
   287 static GstBuffer *
   293 static GstBuffer *
   288 gst_gdp_buffer_from_event (GstGDPPay * this, GstEvent * event)
   294 gst_gdp_buffer_from_event (GstGDPPay * this, GstEvent * event)
   289 {
   295 {
   290   GstBuffer *headerbuf;
   296   GstBuffer *headerbuf;
       
   297 
   291   GstBuffer *payloadbuf;
   298   GstBuffer *payloadbuf;
       
   299 
   292   guint8 *header, *payload;
   300   guint8 *header, *payload;
       
   301 
   293   guint len;
   302   guint len;
       
   303 
   294   gboolean ret;
   304   gboolean ret;
   295 
   305 
   296   ret =
   306   ret =
   297       this->packetizer->packet_from_event (event, this->header_flag, &len,
   307       this->packetizer->packet_from_event (event, this->header_flag, &len,
   298       &header, &payload);
   308       &header, &payload);
   328 {
   338 {
   329   GstCaps *caps;
   339   GstCaps *caps;
   330 
   340 
   331   /* We use copies of these to avoid circular refcounts */
   341   /* We use copies of these to avoid circular refcounts */
   332   GstBuffer *new_segment_buf, *caps_buf, *tag_buf;
   342   GstBuffer *new_segment_buf, *caps_buf, *tag_buf;
       
   343 
   333   GstStructure *structure;
   344   GstStructure *structure;
       
   345 
   334   GstFlowReturn r = GST_FLOW_OK;
   346   GstFlowReturn r = GST_FLOW_OK;
       
   347 
   335   gboolean version_one_zero = TRUE;
   348   gboolean version_one_zero = TRUE;
   336 
   349 
   337   GValue array = { 0 };
   350   GValue array = { 0 };
   338   GValue value = { 0 };
   351   GValue value = { 0 };
   339 
   352 
   362   if (version_one_zero) {
   375   if (version_one_zero) {
   363     gst_gdp_stamp_buffer (this, this->new_segment_buf);
   376     gst_gdp_stamp_buffer (this, this->new_segment_buf);
   364     GST_DEBUG_OBJECT (this, "1.0, appending copy of new segment buffer %p",
   377     GST_DEBUG_OBJECT (this, "1.0, appending copy of new segment buffer %p",
   365         this->new_segment_buf);
   378         this->new_segment_buf);
   366     new_segment_buf = gst_buffer_copy (this->new_segment_buf);
   379     new_segment_buf = gst_buffer_copy (this->new_segment_buf);
       
   380     gst_buffer_set_caps (new_segment_buf, NULL);
   367     g_value_init (&value, GST_TYPE_BUFFER);
   381     g_value_init (&value, GST_TYPE_BUFFER);
   368     gst_value_set_buffer (&value, new_segment_buf);
   382     gst_value_set_buffer (&value, new_segment_buf);
   369     gst_value_array_append_value (&array, &value);
   383     gst_value_array_append_value (&array, &value);
   370     g_value_unset (&value);
   384     g_value_unset (&value);
   371     gst_buffer_unref (new_segment_buf);
   385     gst_buffer_unref (new_segment_buf);
   373     if (this->tag_buf) {
   387     if (this->tag_buf) {
   374       gst_gdp_stamp_buffer (this, this->tag_buf);
   388       gst_gdp_stamp_buffer (this, this->tag_buf);
   375       GST_DEBUG_OBJECT (this, "1.0, appending copy of tag buffer %p",
   389       GST_DEBUG_OBJECT (this, "1.0, appending copy of tag buffer %p",
   376           this->tag_buf);
   390           this->tag_buf);
   377       tag_buf = gst_buffer_copy (this->tag_buf);
   391       tag_buf = gst_buffer_copy (this->tag_buf);
       
   392       gst_buffer_set_caps (tag_buf, NULL);
   378       g_value_init (&value, GST_TYPE_BUFFER);
   393       g_value_init (&value, GST_TYPE_BUFFER);
   379       gst_value_set_buffer (&value, tag_buf);
   394       gst_value_set_buffer (&value, tag_buf);
   380       gst_value_array_append_value (&array, &value);
   395       gst_value_array_append_value (&array, &value);
   381       g_value_unset (&value);
   396       g_value_unset (&value);
   382       gst_buffer_unref (tag_buf);
   397       gst_buffer_unref (tag_buf);
   384   }
   399   }
   385 
   400 
   386   gst_gdp_stamp_buffer (this, this->caps_buf);
   401   gst_gdp_stamp_buffer (this, this->caps_buf);
   387   GST_DEBUG_OBJECT (this, "appending copy of caps buffer %p", this->caps_buf);
   402   GST_DEBUG_OBJECT (this, "appending copy of caps buffer %p", this->caps_buf);
   388   caps_buf = gst_buffer_copy (this->caps_buf);
   403   caps_buf = gst_buffer_copy (this->caps_buf);
       
   404   gst_buffer_set_caps (caps_buf, NULL);
   389   g_value_init (&value, GST_TYPE_BUFFER);
   405   g_value_init (&value, GST_TYPE_BUFFER);
   390   gst_value_set_buffer (&value, caps_buf);
   406   gst_value_set_buffer (&value, caps_buf);
   391   gst_value_array_append_value (&array, &value);
   407   gst_value_array_append_value (&array, &value);
   392   g_value_unset (&value);
   408   g_value_unset (&value);
   393   gst_buffer_unref (caps_buf);
   409   gst_buffer_unref (caps_buf);
   395   /* we also need to add GDP serializations of the streamheaders of the
   411   /* we also need to add GDP serializations of the streamheaders of the
   396    * incoming caps */
   412    * incoming caps */
   397   structure = gst_caps_get_structure (this->caps, 0);
   413   structure = gst_caps_get_structure (this->caps, 0);
   398   if (gst_structure_has_field (structure, "streamheader")) {
   414   if (gst_structure_has_field (structure, "streamheader")) {
   399     const GValue *sh;
   415     const GValue *sh;
       
   416 
   400     GArray *buffers;
   417     GArray *buffers;
       
   418 
   401     GstBuffer *buffer;
   419     GstBuffer *buffer;
       
   420 
   402     int i;
   421     int i;
   403 
   422 
   404     sh = gst_structure_get_value (structure, "streamheader");
   423     sh = gst_structure_get_value (structure, "streamheader");
   405     buffers = g_value_peek_pointer (sh);
   424     buffers = g_value_peek_pointer (sh);
   406     GST_DEBUG_OBJECT (this,
   425     GST_DEBUG_OBJECT (this,
   407         "Need to serialize %d incoming streamheader buffers on ours",
   426         "Need to serialize %d incoming streamheader buffers on ours",
   408         buffers->len);
   427         buffers->len);
   409     for (i = 0; i < buffers->len; ++i) {
   428     for (i = 0; i < buffers->len; ++i) {
   410       GValue *bufval;
   429       GValue *bufval;
       
   430 
   411       GstBuffer *outbuffer;
   431       GstBuffer *outbuffer;
   412 
   432 
   413       bufval = &g_array_index (buffers, GValue, i);
   433       bufval = &g_array_index (buffers, GValue, i);
   414       buffer = g_value_peek_pointer (bufval);
   434       buffer = g_value_peek_pointer (bufval);
   415       outbuffer = gst_gdp_pay_buffer_from_buffer (this, buffer);
   435       outbuffer = gst_gdp_pay_buffer_from_buffer (this, buffer);
   464   if (r != GST_FLOW_OK) {
   484   if (r != GST_FLOW_OK) {
   465     GST_WARNING_OBJECT (this, "pushing GDP newsegment buffer returned %d", r);
   485     GST_WARNING_OBJECT (this, "pushing GDP newsegment buffer returned %d", r);
   466     goto done;
   486     goto done;
   467   }
   487   }
   468   if (this->tag_buf) {
   488   if (this->tag_buf) {
       
   489     gst_buffer_set_caps (this->tag_buf, caps);
   469     GST_DEBUG_OBJECT (this, "Pushing GDP tag buffer %p", this->tag_buf);
   490     GST_DEBUG_OBJECT (this, "Pushing GDP tag buffer %p", this->tag_buf);
   470     /* we stored these bufs with refcount 1, so make sure we keep a ref */
   491     /* we stored these bufs with refcount 1, so make sure we keep a ref */
   471     r = gst_pad_push (this->srcpad, gst_buffer_ref (this->tag_buf));
   492     r = gst_pad_push (this->srcpad, gst_buffer_ref (this->tag_buf));
   472     if (r != GST_FLOW_OK) {
   493     if (r != GST_FLOW_OK) {
   473       GST_WARNING_OBJECT (this, "pushing GDP tag buffer returned %d", r);
   494       GST_WARNING_OBJECT (this, "pushing GDP tag buffer returned %d", r);
   521 gst_gdp_queue_buffer (GstGDPPay * this, GstBuffer * buffer)
   542 gst_gdp_queue_buffer (GstGDPPay * this, GstBuffer * buffer)
   522 {
   543 {
   523   if (this->sent_streamheader) {
   544   if (this->sent_streamheader) {
   524     GST_LOG_OBJECT (this, "Pushing GDP buffer %p, caps %" GST_PTR_FORMAT,
   545     GST_LOG_OBJECT (this, "Pushing GDP buffer %p, caps %" GST_PTR_FORMAT,
   525         buffer, this->caps);
   546         buffer, this->caps);
       
   547     gst_buffer_set_caps (buffer, GST_PAD_CAPS (this->srcpad));
   526     return gst_pad_push (this->srcpad, buffer);
   548     return gst_pad_push (this->srcpad, buffer);
   527   }
   549   }
   528 
   550 
   529   /* store it on an internal queue. buffer remains reffed. */
   551   /* store it on an internal queue. buffer remains reffed. */
   530   this->queue = g_list_append (this->queue, buffer);
   552   this->queue = g_list_append (this->queue, buffer);
   537 
   559 
   538 static GstFlowReturn
   560 static GstFlowReturn
   539 gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer)
   561 gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer)
   540 {
   562 {
   541   GstGDPPay *this;
   563   GstGDPPay *this;
       
   564 
   542   GstCaps *caps;
   565   GstCaps *caps;
       
   566 
   543   GstBuffer *outbuffer;
   567   GstBuffer *outbuffer;
       
   568 
   544   GstFlowReturn ret;
   569   GstFlowReturn ret;
   545 
   570 
   546   this = GST_GDP_PAY (gst_pad_get_parent (pad));
   571   this = GST_GDP_PAY (gst_pad_get_parent (pad));
   547 
   572 
   548   /* we should have received a new_segment before, otherwise it's a bug.
   573   /* we should have received a new_segment before, otherwise it's a bug.
   584       goto no_caps_buffer;
   609       goto no_caps_buffer;
   585 
   610 
   586     GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer);
   611     GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer);
   587     GST_BUFFER_DURATION (outbuffer) = 0;
   612     GST_BUFFER_DURATION (outbuffer) = 0;
   588     GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS);
   613     GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS);
       
   614 
       
   615     if (this->caps_buf)
       
   616       gst_buffer_unref (this->caps_buf);
   589     this->caps_buf = outbuffer;
   617     this->caps_buf = outbuffer;
   590     gst_gdp_pay_reset_streamheader (this);
   618     gst_gdp_pay_reset_streamheader (this);
   591   }
   619   }
   592 
   620 
   593   if (caps)
   621   if (caps)
   650 
   678 
   651 static gboolean
   679 static gboolean
   652 gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event)
   680 gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event)
   653 {
   681 {
   654   GstBuffer *outbuffer;
   682   GstBuffer *outbuffer;
       
   683 
   655   GstGDPPay *this = GST_GDP_PAY (gst_pad_get_parent (pad));
   684   GstGDPPay *this = GST_GDP_PAY (gst_pad_get_parent (pad));
       
   685 
   656   GstFlowReturn flowret;
   686   GstFlowReturn flowret;
       
   687 
   657   gboolean ret = TRUE;
   688   gboolean ret = TRUE;
   658 
   689 
   659   GST_DEBUG_OBJECT (this, "received event %p of type %s (%d)",
   690   GST_DEBUG_OBJECT (this, "received event %p of type %s (%d)",
   660       event, gst_event_type_get_name (event->type), event->type);
   691       event, gst_event_type_get_name (event->type), event->type);
   661 
   692 
   733 
   764 
   734 static gboolean
   765 static gboolean
   735 gst_gdp_pay_src_event (GstPad * pad, GstEvent * event)
   766 gst_gdp_pay_src_event (GstPad * pad, GstEvent * event)
   736 {
   767 {
   737   GstGDPPay *this;
   768   GstGDPPay *this;
       
   769 
   738   gboolean res = TRUE;
   770   gboolean res = TRUE;
   739 
   771 
   740   this = GST_GDP_PAY (gst_pad_get_parent (pad));
   772   this = GST_GDP_PAY (gst_pad_get_parent (pad));
   741 
   773 
   742   switch (GST_EVENT_TYPE (event)) {
   774   switch (GST_EVENT_TYPE (event)) {
   813 
   845 
   814 static GstStateChangeReturn
   846 static GstStateChangeReturn
   815 gst_gdp_pay_change_state (GstElement * element, GstStateChange transition)
   847 gst_gdp_pay_change_state (GstElement * element, GstStateChange transition)
   816 {
   848 {
   817   GstStateChangeReturn ret;
   849   GstStateChangeReturn ret;
       
   850 
   818   GstGDPPay *this = GST_GDP_PAY (element);
   851   GstGDPPay *this = GST_GDP_PAY (element);
   819 
   852 
   820   switch (transition) {
   853   switch (transition) {
   821     case GST_STATE_CHANGE_READY_TO_PAUSED:
   854     case GST_STATE_CHANGE_READY_TO_PAUSED:
   822       break;
   855       break;