Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3584 sourcerer 1
/*
2
 * Copyright 2011 John-Mark Bell 
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 .
17
 */
18
 
19
#include 
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