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