gstreamer_core/plugins/elements/gstfdsink.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    20  * Boston, MA 02111-1307, USA.
    20  * Boston, MA 02111-1307, USA.
    21  */
    21  */
    22 
    22 
    23 /**
    23 /**
    24  * SECTION:element-fdsink
    24  * SECTION:element-fdsink
       
    25  * @short_description: write to a unix file descriptor
    25  * @see_also: #GstFdSrc
    26  * @see_also: #GstFdSrc
    26  *
    27  *
    27  * Write data to a unix file descriptor.
    28  * Write data to a unix file descriptor.
    28  *
    29  *
    29  * This element will synchronize on the clock before writing the data on the
    30  * This element will synchronize on the clock before writing the data on the
    35 
    36 
    36 #ifdef HAVE_CONFIG_H
    37 #ifdef HAVE_CONFIG_H
    37 #  include "config.h"
    38 #  include "config.h"
    38 #endif
    39 #endif
    39 
    40 
       
    41 #ifdef __SYMBIAN32__
       
    42 #include <gst_global.h>
       
    43 #endif
    40 #include "../../gst/gst-i18n-lib.h"
    44 #include "../../gst/gst-i18n-lib.h"
    41 
    45 
    42 #include <sys/types.h>
    46 #include <sys/types.h>
    43 
       
    44 #ifdef G_OS_WIN32
       
    45 #include <io.h>                 /* lseek, open, close, read */
       
    46 #undef lseek
       
    47 #define lseek _lseeki64
       
    48 #undef off_t
       
    49 #define off_t guint64
       
    50 #endif
       
    51 
       
    52 #include <sys/stat.h>
    47 #include <sys/stat.h>
    53 #include <sys/socket.h>
    48 #include <sys/socket.h>
    54 #include <fcntl.h>
    49 #include <fcntl.h>
    55 #include <stdio.h>
    50 #include <stdio.h>
    56 #ifdef HAVE_UNISTD_H
    51 #ifdef HAVE_UNISTD_H
    61 #endif
    56 #endif
    62 #include <errno.h>
    57 #include <errno.h>
    63 #include <string.h>
    58 #include <string.h>
    64 
    59 
    65 #include "gstfdsink.h"
    60 #include "gstfdsink.h"
       
    61 #ifdef __SYMBIAN32__
       
    62 #include <glib_global.h>
       
    63 #include <gobject_global.h>
       
    64 #include <gstpoll.h>
       
    65 #include <gstelement.h>
       
    66 #endif
    66 
    67 
    67 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
    68 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
    68     GST_PAD_SINK,
    69     GST_PAD_SINK,
    69     GST_PAD_ALWAYS,
    70     GST_PAD_ALWAYS,
    70     GST_STATIC_CAPS_ANY);
    71     GST_STATIC_CAPS_ANY);
   118     GstBuffer * buffer);
   119     GstBuffer * buffer);
   119 static gboolean gst_fd_sink_start (GstBaseSink * basesink);
   120 static gboolean gst_fd_sink_start (GstBaseSink * basesink);
   120 static gboolean gst_fd_sink_stop (GstBaseSink * basesink);
   121 static gboolean gst_fd_sink_stop (GstBaseSink * basesink);
   121 static gboolean gst_fd_sink_unlock (GstBaseSink * basesink);
   122 static gboolean gst_fd_sink_unlock (GstBaseSink * basesink);
   122 static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink);
   123 static gboolean gst_fd_sink_unlock_stop (GstBaseSink * basesink);
   123 static gboolean gst_fd_sink_event (GstBaseSink * sink, GstEvent * event);
       
   124 
       
   125 static gboolean gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset);
       
   126 
   124 
   127 static void
   125 static void
   128 gst_fd_sink_base_init (gpointer g_class)
   126 gst_fd_sink_base_init (gpointer g_class)
   129 {
   127 {
   130   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   128   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
   154   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_fd_sink_render);
   152   gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_fd_sink_render);
   155   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_fd_sink_start);
   153   gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_fd_sink_start);
   156   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
   154   gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_fd_sink_stop);
   157   gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
   155   gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock);
   158   gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
   156   gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_fd_sink_unlock_stop);
   159   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_fd_sink_event);
   157   gstbasesink_class->event = NULL;
   160 
   158 
   161   g_object_class_install_property (gobject_class, ARG_FD,
   159   g_object_class_install_property (gobject_class, ARG_FD,
   162       g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
   160       g_param_spec_int ("fd", "fd", "An open file descriptor to write to",
   163           0, G_MAXINT, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   161           0, G_MAXINT, 1, G_PARAM_READWRITE));
   164 }
   162 }
   165 
   163 
   166 static void
   164 static void
   167 gst_fd_sink_init (GstFdSink * fdsink, GstFdSinkClass * klass)
   165 gst_fd_sink_init (GstFdSink * fdsink, GstFdSinkClass * klass)
   168 {
   166 {
   172   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_fd_sink_query));
   170   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_fd_sink_query));
   173 
   171 
   174   fdsink->fd = 1;
   172   fdsink->fd = 1;
   175   fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
   173   fdsink->uri = g_strdup_printf ("fd://%d", fdsink->fd);
   176   fdsink->bytes_written = 0;
   174   fdsink->bytes_written = 0;
   177   fdsink->current_pos = 0;
       
   178 
   175 
   179   GST_BASE_SINK (fdsink)->sync = TRUE;
   176   GST_BASE_SINK (fdsink)->sync = TRUE;
   180 }
   177 }
   181 
   178 
   182 static void
   179 static void
   202     case GST_QUERY_POSITION:
   199     case GST_QUERY_POSITION:
   203       gst_query_parse_position (query, &format, NULL);
   200       gst_query_parse_position (query, &format, NULL);
   204       switch (format) {
   201       switch (format) {
   205         case GST_FORMAT_DEFAULT:
   202         case GST_FORMAT_DEFAULT:
   206         case GST_FORMAT_BYTES:
   203         case GST_FORMAT_BYTES:
   207           gst_query_set_position (query, GST_FORMAT_BYTES, fdsink->current_pos);
   204           gst_query_set_position (query, GST_FORMAT_BYTES,
       
   205               fdsink->bytes_written);
   208           return TRUE;
   206           return TRUE;
   209         default:
   207         default:
   210           return FALSE;
   208           return FALSE;
   211       }
   209       }
   212 
   210 
   213     case GST_QUERY_FORMATS:
   211     case GST_QUERY_FORMATS:
   214       gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
   212       gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES);
   215       return TRUE;
       
   216 
       
   217     case GST_QUERY_URI:
       
   218       gst_query_set_uri (query, fdsink->uri);
       
   219       return TRUE;
   213       return TRUE;
   220 
   214 
   221     default:
   215     default:
   222       return gst_pad_query_default (pad, query);
   216       return gst_pad_query_default (pad, query);
   223   }
   217   }
   275 
   269 
   276   /* all is fine when we get here */
   270   /* all is fine when we get here */
   277   size -= written;
   271   size -= written;
   278   data += written;
   272   data += written;
   279   fdsink->bytes_written += written;
   273   fdsink->bytes_written += written;
   280   fdsink->current_pos += written;
       
   281 
   274 
   282   GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
   275   GST_DEBUG_OBJECT (fdsink, "wrote %d bytes, %d left", written, size);
   283 
   276 
   284   /* short write, select and try to write the remainder */
   277   /* short write, select and try to write the remainder */
   285   if (G_UNLIKELY (size > 0))
   278   if (G_UNLIKELY (size > 0))
   307     switch (errno) {
   300     switch (errno) {
   308       case ENOSPC:
   301       case ENOSPC:
   309         GST_ELEMENT_ERROR (fdsink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL));
   302         GST_ELEMENT_ERROR (fdsink, RESOURCE, NO_SPACE_LEFT, (NULL), (NULL));
   310         break;
   303         break;
   311       default:{
   304       default:{
   312         GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL),
   305         GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
   313             ("Error while writing to file descriptor %d: %s",
   306             (_("Error while writing to file descriptor \"%d\"."), fdsink->fd),
   314                 fdsink->fd, g_strerror (errno)));
   307             ("%s", g_strerror (errno)));
   315       }
   308       }
   316     }
   309     }
   317     return GST_FLOW_ERROR;
   310     return GST_FLOW_ERROR;
   318   }
   311   }
   319 }
   312 }
   341 
   334 
   342       case ESPIPE:
   335       case ESPIPE:
   343         goto not_seekable;
   336         goto not_seekable;
   344     }
   337     }
   345   } else
   338   } else
   346     GST_DEBUG_OBJECT (fdsink, "File descriptor %d is seekable", fd);
   339     GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is seekable", fd);
   347 
   340 
   348   return TRUE;
   341   return TRUE;
   349 
   342 
   350 invalid:
   343 invalid:
   351   {
   344   {
   352     GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE, (NULL),
   345     GST_ELEMENT_ERROR (fdsink, RESOURCE, WRITE,
   353         ("File descriptor %d is not valid: %s", fd, g_strerror (errno)));
   346         (_("File descriptor \"%d\" is not valid."), fd),
       
   347         ("%s", g_strerror (errno)));
   354     return FALSE;
   348     return FALSE;
   355   }
   349   }
   356 not_seekable:
   350 not_seekable:
   357   {
   351   {
   358     GST_DEBUG_OBJECT (fdsink, "File descriptor %d is a pipe", fd);
   352     GST_DEBUG_OBJECT (fdsink, "File descriptor \"%d\" is a pipe", fd);
   359     return TRUE;
   353     return TRUE;
   360   }
   354   }
   361 }
   355 }
   362 
   356 
   363 static gboolean
   357 static gboolean
   374     goto socket_pair;
   368     goto socket_pair;
   375 
   369 
   376   fd.fd = fdsink->fd;
   370   fd.fd = fdsink->fd;
   377   gst_poll_add_fd (fdsink->fdset, &fd);
   371   gst_poll_add_fd (fdsink->fdset, &fd);
   378   gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
   372   gst_poll_fd_ctl_write (fdsink->fdset, &fd, TRUE);
   379 
       
   380   fdsink->bytes_written = 0;
       
   381   fdsink->current_pos = 0;
       
   382 
   373 
   383   return TRUE;
   374   return TRUE;
   384 
   375 
   385   /* ERRORS */
   376   /* ERRORS */
   386 socket_pair:
   377 socket_pair:
   505     default:
   496     default:
   506       break;
   497       break;
   507   }
   498   }
   508 }
   499 }
   509 
   500 
   510 static gboolean
       
   511 gst_fd_sink_do_seek (GstFdSink * fdsink, guint64 new_offset)
       
   512 {
       
   513   off_t result;
       
   514 
       
   515   result = lseek (fdsink->fd, new_offset, SEEK_SET);
       
   516 
       
   517   if (result == -1)
       
   518     goto seek_failed;
       
   519 
       
   520   fdsink->current_pos = new_offset;
       
   521 
       
   522   GST_DEBUG_OBJECT (fdsink, "File desciptor %d to seek to position "
       
   523       "%" G_GUINT64_FORMAT, fdsink->fd, fdsink->current_pos);
       
   524 
       
   525   return TRUE;
       
   526 
       
   527   /* ERRORS */
       
   528 seek_failed:
       
   529   {
       
   530     GST_DEBUG_OBJECT (fdsink, "File desciptor %d failed to seek to position "
       
   531         "%" G_GUINT64_FORMAT, fdsink->fd, new_offset);
       
   532     return FALSE;
       
   533   }
       
   534 }
       
   535 
       
   536 static gboolean
       
   537 gst_fd_sink_event (GstBaseSink * sink, GstEvent * event)
       
   538 {
       
   539   GstEventType type;
       
   540   GstFdSink *fdsink;
       
   541 
       
   542   fdsink = GST_FD_SINK (sink);
       
   543 
       
   544   type = GST_EVENT_TYPE (event);
       
   545 
       
   546   switch (type) {
       
   547     case GST_EVENT_NEWSEGMENT:
       
   548     {
       
   549       gint64 start, stop, pos;
       
   550       GstFormat format;
       
   551       gst_event_parse_new_segment (event, NULL, NULL, &format, &start,
       
   552           &stop, &pos);
       
   553 
       
   554       if (format == GST_FORMAT_BYTES) {
       
   555         /* only try to seek and fail when we are going to a different
       
   556          * position */
       
   557         if (fdsink->current_pos != start) {
       
   558           /* FIXME, the seek should be performed on the pos field, start/stop are
       
   559            * just boundaries for valid bytes offsets. We should also fill the file
       
   560            * with zeroes if the new position extends the current EOF (sparse streams
       
   561            * and segment accumulation). */
       
   562           if (!gst_fd_sink_do_seek (fdsink, (guint64) start))
       
   563             goto seek_failed;
       
   564         }
       
   565       } else {
       
   566         GST_DEBUG_OBJECT (fdsink,
       
   567             "Ignored NEWSEGMENT event of format %u (%s)", (guint) format,
       
   568             gst_format_get_name (format));
       
   569       }
       
   570       break;
       
   571     }
       
   572     default:
       
   573       break;
       
   574   }
       
   575 
       
   576   return TRUE;
       
   577 
       
   578 seek_failed:
       
   579   {
       
   580     GST_ELEMENT_ERROR (fdsink, RESOURCE, SEEK, (NULL),
       
   581         ("Error while seeking on file descriptor %d: %s",
       
   582             fdsink->fd, g_strerror (errno)));
       
   583     return FALSE;
       
   584   }
       
   585 
       
   586 }
       
   587 
       
   588 /*** GSTURIHANDLER INTERFACE *************************************************/
   501 /*** GSTURIHANDLER INTERFACE *************************************************/
   589 
   502 #ifdef __SYMBIAN32__
   590 static GstURIType
   503 GstURIType
       
   504 #else
       
   505 static guint
       
   506 #endif 
   591 gst_fd_sink_uri_get_type (void)
   507 gst_fd_sink_uri_get_type (void)
   592 {
   508 {
   593   return GST_URI_SINK;
   509   return GST_URI_SINK;
   594 }
   510 }
   595 
       
   596 static gchar **
   511 static gchar **
   597 gst_fd_sink_uri_get_protocols (void)
   512 gst_fd_sink_uri_get_protocols (void)
   598 {
   513 {
   599   static gchar *protocols[] = { "fd", NULL };
   514   static gchar *protocols[] = { "fd", NULL };
   600 
   515 
   601   return protocols;
   516   return protocols;
   602 }
   517 }
   603 
       
   604 static const gchar *
   518 static const gchar *
   605 gst_fd_sink_uri_get_uri (GstURIHandler * handler)
   519 gst_fd_sink_uri_get_uri (GstURIHandler * handler)
   606 {
   520 {
   607   GstFdSink *sink = GST_FD_SINK (handler);
   521   GstFdSink *sink = GST_FD_SINK (handler);
   608 
   522