Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
  3.  *
  4.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  5.  *
  6.  * NetSurf is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; version 2 of the License.
  9.  *
  10.  * NetSurf is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include <gst/gst.h>
  20.  
  21. #include "content/content_factory.h"
  22. #include "content/content_protected.h"
  23. #include "image/video.h"
  24.  
  25. typedef struct nsvideo_content {
  26.         struct content base;
  27.  
  28.         GstElement *playbin;
  29.         GstElement *appsrc;
  30. } nsvideo_content;
  31.  
  32. static gboolean nsvideo_bus_call(GstBus *bus, GstMessage *msg,
  33.                 nsvideo_content *video)
  34. {
  35.         switch (GST_MESSAGE_TYPE(msg)) {
  36.         case GST_MESSAGE_ERROR:
  37.                 break;
  38.         case GST_MESSAGE_EOS:
  39.                 break;
  40.         default:
  41.                 break;
  42.         }
  43.  
  44.         return TRUE;
  45. }
  46.  
  47. static void nsvideo_need_data_event(GstElement *playbin, guint size,
  48.                 nsvideo_content *video)
  49. {
  50. }
  51.  
  52. static void nsvideo_enough_data_event(GstElement *playbin,
  53.                 nsvideo_content *video)
  54. {
  55. }
  56.  
  57. static void nsvideo_source_event(GObject *object, GObject *orig,
  58.                 GParamSpec *pspec, nsvideo_content *video)
  59. {
  60.         g_object_get(orig, pspec->name, &video->appsrc, NULL);
  61.  
  62.         g_signal_connect(video->appsrc, "need-data",
  63.                         G_CALLBACK(nsvideo_need_data_event), video);
  64.         g_signal_connect(video->appsrc, "enough-data",
  65.                         G_CALLBACK(nsvideo_enough_data_event), video);
  66. }
  67.  
  68. static nserror nsvideo_create(const content_handler *handler,
  69.                 lwc_string *imime_type, const http_parameter *params,
  70.                 llcache_handle *llcache,
  71.                 const char *fallback_charset, bool quirks,
  72.                 struct content **c)
  73. {
  74.         nsvideo_content *video;
  75.         nserror error;
  76.         GstBus *bus;
  77.  
  78.         video = calloc(1, sizeof(nsvideo_content));
  79.         if (video == NULL)
  80.                 return NSERROR_NOMEM;
  81.  
  82.         error = content__init(&video->base, handler, imime_type, params,
  83.                         llcache, fallback_charset, quirks);
  84.         if (error != NSERROR_OK) {
  85.                 free(video);
  86.                 return error;
  87.         }
  88.  
  89.         error = llcache_handle_force_stream(llcache);
  90.         if (error != NSERROR_OK) {
  91.                 free(video);
  92.                 return error;
  93.         }
  94.  
  95.         video->playbin = gst_element_factory_make("playbin2", NULL);
  96.         if (video->playbin == NULL) {
  97.                 free(video);
  98.                 return NSERROR_NOMEM;
  99.         }
  100.  
  101.         bus = gst_pipeline_get_bus(GST_PIPELINE(video->playbin));
  102.         gst_bus_add_watch(bus, (GstBusFunc) nsvideo_bus_call, video);
  103.         gst_object_unref(bus);
  104.  
  105.         g_object_set(video->playbin, "uri", "appsrc://", NULL);
  106.         g_signal_connect(video->playbin, "deep-notify::source",
  107.                         G_CALLBACK(nsvideo_source_event), video);
  108.  
  109.         /** \todo Create appsink & register with playbin */
  110.  
  111.         gst_element_set_state(video->playbin, GST_STATE_PLAYING);
  112.        
  113.         *c = (struct content *) video;
  114.  
  115.         return NSERROR_OK;
  116. }
  117.  
  118. static bool nsvideo_process_data(struct content *c, const char *data,
  119.                 unsigned int size)
  120. {
  121.         nsvideo_content *video = (nsvideo_content *) c;
  122.         GstBuffer *buffer;
  123.         GstFlowReturn ret;
  124.  
  125.         buffer = gst_buffer_new();
  126.         GST_BUFFER_DATA(buffer) = (guint8 *) data;
  127.         GST_BUFFER_SIZE(buffer) = (gsize) size;
  128.  
  129.         /* Send data to appsrc */
  130.         g_signal_emit_by_name(video->appsrc, "push-buffer", buffer, &ret);
  131.  
  132.         return ret == GST_FLOW_OK;
  133. }
  134.  
  135. static bool nsvideo_convert(struct content *c)
  136. {
  137.         nsvideo_content *video = (nsvideo_content *) c;
  138.         GstFlowReturn ret;
  139.  
  140.         /* Tell appsrc we're done */
  141.         g_signal_emit_by_name(video->appsrc, "end-of-stream", &ret);
  142.  
  143.         /* Appsink will flag DONE on receipt of first frame */
  144.  
  145.         return ret == GST_FLOW_OK;
  146. }
  147.  
  148. static void nsvideo_destroy(struct content *c)
  149. {
  150.         nsvideo_content *video = (nsvideo_content *) c;
  151.  
  152.         gst_element_set_state(video->playbin, GST_STATE_NULL);
  153.         gst_object_unref(video->playbin);
  154. }
  155.  
  156. static bool nsvideo_redraw(struct content *c, struct content_redraw_data *data,
  157.                 const struct rect *clip, const struct redraw_context *ctx)
  158. {
  159.         /** \todo Implement */
  160.         return true;
  161. }
  162.  
  163. static nserror nsvideo_clone(const struct content *old, struct content **newc)
  164. {
  165.         /** \todo Implement */
  166.         return NSERROR_CLONE_FAILED;
  167. }
  168.  
  169. static content_type nsvideo_type(void)
  170. {
  171.         /** \todo Lies */
  172.         return CONTENT_IMAGE;
  173. }
  174.  
  175. static void *nsvideo_get_internal(const struct content *c, void *context)
  176. {
  177.         /** \todo Return pointer to bitmap containing current frame, if any? */
  178.         return NULL;
  179. }
  180.  
  181. static const content_handler nsvideo_content_handler = {
  182.         .create = nsvideo_create,
  183.         .process_data = nsvideo_process_data,
  184.         .data_complete = nsvideo_convert,
  185.         .destroy = nsvideo_destroy,
  186.         .redraw = nsvideo_redraw,
  187.         .clone = nsvideo_clone,
  188.         .type = nsvideo_type,
  189.         .get_internal = nsvideo_get_internal,
  190.         /* Can't share videos because we stream them */
  191.         .no_share = true
  192. };
  193.  
  194. static const char *nsvideo_types[] = {
  195.         "video/mp4",
  196.         "video/webm"
  197. };
  198.  
  199. CONTENT_FACTORY_REGISTER_TYPES(nsvideo, nsvideo_types,
  200.                 nsvideo_content_handler);
  201.  
  202.