summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2008-12-10 12:44:29 +0100
committerBenjamin Otte <otte@gnome.org>2008-12-16 21:38:15 +0100
commit4d1e0e4db4c6db9db0710f2a2cee7e3bff95c7ca (patch)
tree0f156fe1f3cfbc572b5011aea4c03e9073fa7407
parent673db3e51dfa13fde8f11f7305c6c8d9d7517dee (diff)
handle Buffer.Full and Buffer.Empty messages
-rw-r--r--swfdec/swfdec_net_stream.c12
-rw-r--r--swfdec/swfdec_net_stream_video.c45
-rw-r--r--swfdec/swfdec_net_stream_video.h3
3 files changed, 53 insertions, 7 deletions
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 5d79cdaf..9fd98d02 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -177,6 +177,14 @@ swfdec_net_stream_mark (SwfdecGcObject *object)
}
static void
+swfdec_net_stream_video_buffer_status (SwfdecNetStreamVideo *video, GParamSpec *pspec,
+ SwfdecNetStream* stream)
+{
+ swfdec_net_stream_onstatus (stream, video->playing ?
+ SWFDEC_AS_STR_NetStream_Buffer_Full : SWFDEC_AS_STR_NetStream_Buffer_Empty);
+}
+
+static void
swfdec_net_stream_dispose (GObject *object)
{
SwfdecNetStream *stream = SWFDEC_NET_STREAM (object);
@@ -185,6 +193,8 @@ swfdec_net_stream_dispose (GObject *object)
swfdec_rtmp_rpc_free (stream->rpc);
stream->rpc = NULL;
}
+ g_signal_handlers_disconnect_by_func (stream->video,
+ swfdec_net_stream_video_buffer_status, stream);
G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object);
}
@@ -288,6 +298,8 @@ swfdec_net_stream_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
stream->conn = conn;
stream->rpc = swfdec_rtmp_rpc_new (conn, SWFDEC_AS_RELAY (stream));
stream->video = swfdec_net_stream_video_new (SWFDEC_PLAYER (cx));
+ g_signal_connect (stream->video, "notify::playing",
+ G_CALLBACK (swfdec_net_stream_video_buffer_status), stream);
swfdec_as_context_get_time (cx, &stream->rpc->last_send);
swfdec_as_object_set_relay (o, SWFDEC_AS_RELAY (stream));
}
diff --git a/swfdec/swfdec_net_stream_video.c b/swfdec/swfdec_net_stream_video.c
index 8f725609..13fd14fb 100644
--- a/swfdec/swfdec_net_stream_video.c
+++ b/swfdec/swfdec_net_stream_video.c
@@ -75,10 +75,31 @@ swfdec_net_stream_video_video_provider_init (SwfdecVideoProviderInterface *iface
/*** SWFDEC_NET_STREAM_VIDEO ***/
+enum {
+ PROP_0,
+ PROP_PLAYING
+};
+
G_DEFINE_TYPE_WITH_CODE (SwfdecNetStreamVideo, swfdec_net_stream_video, SWFDEC_TYPE_GC_OBJECT,
G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_VIDEO_PROVIDER, swfdec_net_stream_video_video_provider_init))
static void
+swfdec_net_stream_video_get_property (GObject *object, guint param_id, GValue *value,
+ GParamSpec * pspec)
+{
+ SwfdecNetStreamVideo *video = SWFDEC_NET_STREAM_VIDEO (object);
+
+ switch (param_id) {
+ case PROP_PLAYING:
+ g_value_set_boolean (value, video->playing);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
swfdec_net_stream_video_dispose (GObject *object)
{
SwfdecNetStreamVideo *video = SWFDEC_NET_STREAM_VIDEO (object);
@@ -106,11 +127,17 @@ swfdec_net_stream_video_class_init (SwfdecNetStreamVideoClass * g_class)
GObjectClass *object_class = G_OBJECT_CLASS (g_class);
object_class->dispose = swfdec_net_stream_video_dispose;
+ object_class->get_property = swfdec_net_stream_video_get_property;
+
+ g_object_class_install_property (object_class, PROP_PLAYING,
+ g_param_spec_boolean ("playing", "playing", "TRUE when the video is playing",
+ FALSE, G_PARAM_READABLE));
}
static void
swfdec_net_stream_video_init (SwfdecNetStreamVideo *video)
{
+ video->buffer_time = 100;
video->next = g_queue_new ();
}
@@ -221,8 +248,11 @@ swfdec_net_stream_video_decode (SwfdecNetStreamVideo *video)
for (;;) {
packet = g_queue_pop_head (video->next);
- if (packet == NULL)
+ if (packet == NULL) {
+ video->playing = FALSE;
+ g_object_notify (G_OBJECT (video), "playing");
return;
+ }
video->timeout.timestamp += SWFDEC_TICKS_PER_SECOND * packet->header.timestamp / 1000;
if (player->priv->time < video->timeout.timestamp) {
g_queue_push_head (video->next, packet);
@@ -231,6 +261,7 @@ swfdec_net_stream_video_decode (SwfdecNetStreamVideo *video)
return;
}
swfdec_net_stream_video_decode_one (video, packet->buffer);
+ video->next_length -= packet->header.timestamp;
swfdec_rtmp_packet_free (packet);
}
}
@@ -238,7 +269,9 @@ swfdec_net_stream_video_decode (SwfdecNetStreamVideo *video)
static void
swfdec_net_stream_video_start (SwfdecNetStreamVideo *video)
{
+ video->playing = TRUE;
video->timeout.timestamp = SWFDEC_PLAYER (swfdec_gc_object_get_context (video))->priv->time;
+ g_object_notify (G_OBJECT (video), "playing");
}
void
@@ -252,13 +285,11 @@ swfdec_net_stream_video_push (SwfdecNetStreamVideo *video,
packet = swfdec_rtmp_packet_new (header->channel, header->stream,
header->type, header->timestamp, buffer);
- if (g_queue_is_empty (video->next)) {
- g_queue_push_tail (video->next, packet);
- if (video->decoder == NULL)
- swfdec_net_stream_video_start (video);
+ g_queue_push_tail (video->next, packet);
+ video->next_length += header->timestamp;
+ if (!video->playing && video->next_length >= video->buffer_time) {
+ swfdec_net_stream_video_start (video);
swfdec_net_stream_video_decode (video);
- } else {
- g_queue_push_tail (video->next, packet);
}
}
diff --git a/swfdec/swfdec_net_stream_video.h b/swfdec/swfdec_net_stream_video.h
index ddd1ece9..163d048b 100644
--- a/swfdec/swfdec_net_stream_video.h
+++ b/swfdec/swfdec_net_stream_video.h
@@ -41,7 +41,10 @@ typedef struct _SwfdecNetStreamVideoClass SwfdecNetStreamVideoClass;
struct _SwfdecNetStreamVideo {
SwfdecGcObject object;
+ gulong buffer_time; /* time to buffer before starting to play */
GQueue * next; /* queue of pending packets */
+ gulong next_length; /* number of milliseconds in the next queue */
+ gboolean playing; /* TRUE if we're currently playing */
SwfdecTimeout timeout; /* time the next image should be decoded */
SwfdecVideoDecoder * decoder; /* the current decoder */
};