diff options
author | Benjamin Otte <otte@gnome.org> | 2008-12-09 14:51:44 +0100 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2008-12-16 15:16:38 +0100 |
commit | 28729e8096d5f24f5923d0e16ac957354d852d6b (patch) | |
tree | be39d825d44c3f7db2201db1e184b62b8a340120 | |
parent | 1152a1385217cc070888a2e6a86c85bda253bad6 (diff) |
make this stuff work without channels
-rw-r--r-- | swfdec/Makefile.am | 8 | ||||
-rw-r--r-- | swfdec/swfdec_net_connection.c | 18 | ||||
-rw-r--r-- | swfdec/swfdec_net_stream.c | 27 | ||||
-rw-r--r-- | swfdec/swfdec_net_stream.h | 5 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_channel.c | 214 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_channel.h | 81 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_connection.c | 272 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_connection.h | 22 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_control_channel.c | 187 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_control_channel.h | 56 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_packet.c | 7 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_packet.h | 4 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_rpc.c | 78 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_rpc.h | 13 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_rpc_channel.c | 319 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_rpc_channel.h | 70 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_socket.c | 52 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_video_channel.c | 99 | ||||
-rw-r--r-- | swfdec/swfdec_rtmp_video_channel.h | 52 |
19 files changed, 339 insertions, 1245 deletions
diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am index b64264bb..fc65e9df 100644 --- a/swfdec/Makefile.am +++ b/swfdec/Makefile.am @@ -131,18 +131,14 @@ libswfdec_source_files = \ swfdec_renderer.c \ swfdec_resource.c \ swfdec_ringbuffer.c \ - swfdec_rtmp_channel.c \ - swfdec_rtmp_control_channel.c \ swfdec_rtmp_connection.c \ swfdec_rtmp_handshake.c \ swfdec_rtmp_header.c \ swfdec_rtmp_packet.c \ - swfdec_rtmp_rpc_channel.c \ swfdec_rtmp_rpc.c \ swfdec_rtmp_socket.c \ swfdec_rtmp_socket_rtmp.c \ swfdec_rtmp_stream.c \ - swfdec_rtmp_video_channel.c \ swfdec_sandbox.c \ swfdec_script.c \ swfdec_selection.c \ @@ -333,18 +329,14 @@ noinst_HEADERS = \ swfdec_renderer_internal.h \ swfdec_resource.h \ swfdec_ringbuffer.h \ - swfdec_rtmp_channel.h \ - swfdec_rtmp_control_channel.h \ swfdec_rtmp_connection.h \ swfdec_rtmp_handshake.h \ swfdec_rtmp_header.h \ swfdec_rtmp_packet.h \ - swfdec_rtmp_rpc_channel.h \ swfdec_rtmp_rpc.h \ swfdec_rtmp_socket.h \ swfdec_rtmp_socket_rtmp.h \ swfdec_rtmp_stream.h \ - swfdec_rtmp_video_channel.h \ swfdec_sandbox.h \ swfdec_script_internal.h \ swfdec_shape.h \ diff --git a/swfdec/swfdec_net_connection.c b/swfdec/swfdec_net_connection.c index 1d0479a6..73a4ce72 100644 --- a/swfdec/swfdec_net_connection.c +++ b/swfdec/swfdec_net_connection.c @@ -35,7 +35,7 @@ #include "swfdec_debug.h" #include "swfdec_internal.h" #include "swfdec_player_internal.h" -#include "swfdec_rtmp_rpc_channel.h" +#include "swfdec_rtmp_rpc.h" #include "swfdec_sandbox.h" /*** AS CODE ***/ @@ -81,13 +81,25 @@ swfdec_net_connection_do_call (SwfdecAsContext *cx, SwfdecAsObject *object, { SwfdecRtmpConnection *conn; SwfdecAsObject *ret_cb = NULL; + SwfdecRtmpPacket *packet; SwfdecAsValue name; SWFDEC_AS_CHECK (SWFDEC_TYPE_RTMP_CONNECTION, &conn, "v|O", &name, &ret_cb); - swfdec_rtmp_rpc_channel_send (SWFDEC_RTMP_RPC_CHANNEL ( - swfdec_rtmp_connection_get_rpc_channel (conn)), name, + if (!swfdec_rtmp_connection_is_connected (conn)) { + SWFDEC_WARNING ("NetConnection.call does not work on closed connections."); + return; + } + + swfdec_rtmp_rpc_send (conn->rpc, name, ret_cb, MAX (2, argc) - 2, argv + 2); + /* FIXME: This should be done by some smart API */ + packet = swfdec_rtmp_rpc_pop (conn->rpc, FALSE); + if (packet) { + packet->header.channel = 3; + packet->header.stream = 0; + swfdec_rtmp_connection_send (conn, packet); + } } SWFDEC_AS_NATIVE (2100, 3, swfdec_net_connection_do_addHeader) diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c index 163a9e89..41a66e87 100644 --- a/swfdec/swfdec_net_stream.c +++ b/swfdec/swfdec_net_stream.c @@ -26,8 +26,6 @@ #include "swfdec_as_frame_internal.h" #include "swfdec_as_internal.h" #include "swfdec_debug.h" -#include "swfdec_rtmp_rpc_channel.h" -#include "swfdec_rtmp_video_channel.h" /*** NET STREAM ***/ @@ -47,14 +45,7 @@ swfdec_net_stream_mark (SwfdecGcObject *object) static void swfdec_net_stream_dispose (GObject *object) { - SwfdecNetStream *stream = SWFDEC_NET_STREAM (object); - - swfdec_rtmp_channel_unregister (stream->rpc_channel); - g_object_unref (stream->rpc_channel); - swfdec_rtmp_channel_unregister (stream->video_channel); - g_object_unref (stream->video_channel); - swfdec_rtmp_channel_unregister (stream->audio_channel); - g_object_unref (stream->audio_channel); + //SwfdecNetStream *stream = SWFDEC_NET_STREAM (object); G_OBJECT_CLASS (swfdec_net_stream_parent_class)->dispose (object); } @@ -157,12 +148,6 @@ swfdec_net_stream_construct (SwfdecAsContext *cx, SwfdecAsObject *object, stream = g_object_new (SWFDEC_TYPE_NET_STREAM, "context", cx, NULL); stream->conn = conn; swfdec_as_object_set_relay (o, SWFDEC_AS_RELAY (stream)); - stream->rpc_channel = swfdec_rtmp_rpc_channel_new (conn); - swfdec_rtmp_rpc_channel_set_target (SWFDEC_RTMP_RPC_CHANNEL (stream->rpc_channel), - swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (stream))); - stream->video_channel = swfdec_rtmp_video_channel_new (conn); - /* FIXME: new class for audio plz */ - stream->audio_channel = swfdec_rtmp_rpc_channel_new (conn); } SWFDEC_AS_NATIVE (2101, 201, swfdec_net_stream_onCreate) @@ -172,7 +157,7 @@ swfdec_net_stream_onCreate (SwfdecAsContext *cx, SwfdecAsObject *object, { SwfdecNetStream *stream; SwfdecAsObject *o; - guint stream_id, channel_id; + guint stream_id; SWFDEC_AS_CHECK (0, NULL, "oi", &o, &stream_id); @@ -180,11 +165,7 @@ swfdec_net_stream_onCreate (SwfdecAsContext *cx, SwfdecAsObject *object, return; stream = SWFDEC_NET_STREAM (o->relay); - stream->stream_id = stream_id; - channel_id = 4 + ((stream_id - 1) * 5); - swfdec_rtmp_channel_register (stream->rpc_channel, channel_id, stream_id); - swfdec_rtmp_channel_register (stream->video_channel, channel_id + 1, stream_id); - swfdec_rtmp_channel_register (stream->audio_channel, channel_id + 2, stream_id); + stream->stream = stream_id; } SWFDEC_AS_NATIVE (2101, 202, swfdec_net_stream_send_connection) @@ -202,8 +183,10 @@ swfdec_net_stream_send_connection (SwfdecAsContext *cx, SwfdecAsObject *object, return; stream = SWFDEC_NET_STREAM (o->relay); +#if 0 swfdec_rtmp_rpc_channel_send (SWFDEC_RTMP_RPC_CHANNEL ( stream->rpc_channel), name, ret_cb, MAX (3, argc) - 3, argv + 3); +#endif } diff --git a/swfdec/swfdec_net_stream.h b/swfdec/swfdec_net_stream.h index 89297b85..7ece9fc7 100644 --- a/swfdec/swfdec_net_stream.h +++ b/swfdec/swfdec_net_stream.h @@ -39,10 +39,7 @@ struct _SwfdecNetStream { SwfdecAsRelay relay; SwfdecRtmpConnection * conn; /* the connection in use */ - guint stream_id; /* id of this stream */ - SwfdecRtmpChannel * rpc_channel; /* channel used for RPC */ - SwfdecRtmpChannel * video_channel; /* channel used for video */ - SwfdecRtmpChannel * audio_channel; /* channel used for audio */ + guint stream; /* id of this stream */ }; struct _SwfdecNetStreamClass { diff --git a/swfdec/swfdec_rtmp_channel.c b/swfdec/swfdec_rtmp_channel.c deleted file mode 100644 index ea927613..00000000 --- a/swfdec/swfdec_rtmp_channel.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "swfdec_rtmp_channel.h" - -#include "swfdec_debug.h" -#include "swfdec_rtmp_socket.h" - -/*** SwfdecRtmpChannel ***/ - -enum { - PROP_0, - PROP_CONNECTION -}; - -G_DEFINE_ABSTRACT_TYPE (SwfdecRtmpChannel, swfdec_rtmp_channel, G_TYPE_OBJECT) - -static void -swfdec_rtmp_channel_get_property (GObject *object, guint param_id, GValue *value, - GParamSpec * pspec) -{ - SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object); - - switch (param_id) { - case PROP_CONNECTION: - g_value_set_object (value, channel->conn); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -swfdec_rtmp_channel_set_property (GObject *object, guint param_id, const GValue *value, - GParamSpec * pspec) -{ - SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object); - - switch (param_id) { - case PROP_CONNECTION: - channel->conn = g_value_get_object (value); - g_assert (channel->conn != NULL); - swfdec_rtmp_channel_get_time (channel, &channel->timestamp); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -swfdec_rtmp_channel_dispose (GObject *object) -{ - SwfdecRtmpChannel *channel = SWFDEC_RTMP_CHANNEL (object); - - if (channel->recv_queue) { - swfdec_buffer_queue_unref (channel->recv_queue); - channel->recv_queue = NULL; - } - if (channel->send_queue) { - swfdec_buffer_queue_unref (channel->send_queue); - channel->send_queue = NULL; - } - - G_OBJECT_CLASS (swfdec_rtmp_channel_parent_class)->dispose (object); -} - -static void -swfdec_rtmp_channel_class_init (SwfdecRtmpChannelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = swfdec_rtmp_channel_dispose; - object_class->get_property = swfdec_rtmp_channel_get_property; - object_class->set_property = swfdec_rtmp_channel_set_property; - - g_object_class_install_property (object_class, PROP_CONNECTION, - g_param_spec_object ("connection", "connection", "RTMP connection this channel belongs to", - SWFDEC_TYPE_RTMP_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -swfdec_rtmp_channel_init (SwfdecRtmpChannel *channel) -{ - swfdec_rtmp_header_invalidate (&channel->recv_cache); - channel->recv_queue = swfdec_buffer_queue_new (); - swfdec_rtmp_header_invalidate (&channel->send_cache); - channel->send_queue = swfdec_buffer_queue_new (); -} - -SwfdecBuffer * -swfdec_rtmp_channel_next_buffer (SwfdecRtmpChannel *channel) -{ - SwfdecRtmpChannelClass *klass; - SwfdecRtmpPacket *packet; - SwfdecRtmpHeader header; - SwfdecBuffer *buffer; - SwfdecBots *bots; - guint i; - - g_return_val_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel), NULL); - g_return_val_if_fail (swfdec_rtmp_channel_is_registered (channel), NULL); - - buffer = swfdec_buffer_queue_pull_buffer (channel->send_queue); - if (buffer) - return buffer; - - klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel); - swfdec_rtmp_header_copy (&header, &channel->send_cache); - packet = klass->send (channel); - if (packet == NULL) - return NULL; - - buffer = packet->buffer; - bots = swfdec_bots_new (); - header.channel = channel->channel_id; - header.type = packet->header.type; - header.timestamp = packet->header.timestamp; - header.size = buffer->length; - header.stream = channel->stream_id; - - swfdec_rtmp_header_write (&header, bots, - swfdec_rtmp_header_diff (&header, &channel->send_cache)); - swfdec_rtmp_header_copy (&channel->send_cache, &header); - - for (i = 0; i < buffer->length; i += SWFDEC_RTMP_BLOCK_SIZE) { - if (i != 0) { - /* write a continuation header */ - bots = swfdec_bots_new (); - swfdec_rtmp_header_write (&header, bots, SWFDEC_RTMP_HEADER_1_BYTE); - } - swfdec_bots_put_data (bots, buffer->data + i, MIN (SWFDEC_RTMP_BLOCK_SIZE, buffer->length - i)); - swfdec_buffer_queue_push (channel->send_queue, swfdec_bots_close (bots)); - } - swfdec_rtmp_packet_free (packet); - - return swfdec_buffer_queue_pull_buffer (channel->send_queue); -} - -static int -swfdec_rtmp_channel_compare (gconstpointer a, gconstpointer b) -{ - SwfdecRtmpChannel *ca = (SwfdecRtmpChannel *) a; - SwfdecRtmpChannel *cb = (SwfdecRtmpChannel *) b; - - return cb->channel_id - ca->channel_id; -} - -void -swfdec_rtmp_channel_register (SwfdecRtmpChannel *channel, - guint channel_id, guint stream_id) -{ - SwfdecRtmpConnection *conn; - - g_return_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel)); - g_return_if_fail (!swfdec_rtmp_channel_is_registered (channel)); - g_return_if_fail (channel_id > 1); - - if (channel_id >= 65536 + 64) { - SWFDEC_FIXME ("figure out how huge ids (like %u) are handled. Channel registration failed", channel_id); - return; - } - SWFDEC_DEBUG ("registering %s as channel %u for stream %u", G_OBJECT_TYPE_NAME (channel), - channel_id, stream_id); - - conn = channel->conn; - conn->channels = g_list_insert_sorted (conn->channels, channel, - swfdec_rtmp_channel_compare); - channel->channel_id = channel_id; - channel->stream_id = stream_id; - g_object_ref (channel); - - swfdec_rtmp_socket_send (channel->conn->socket); -} - -void -swfdec_rtmp_channel_unregister (SwfdecRtmpChannel *channel) -{ - g_return_if_fail (SWFDEC_IS_RTMP_CHANNEL (channel)); - - if (!swfdec_rtmp_channel_is_registered (channel)) - return; - - if (channel->conn->last_send->data == channel) { - channel->conn->last_send = channel->conn->last_send->next ? - channel->conn->last_send->next : channel->conn->last_send->prev; - } - channel->conn->channels = g_list_remove (channel->conn->channels, channel); - channel->channel_id = 0; - channel->stream_id = 0; - g_object_unref (channel); -} - diff --git a/swfdec/swfdec_rtmp_channel.h b/swfdec/swfdec_rtmp_channel.h deleted file mode 100644 index 4fa985a9..00000000 --- a/swfdec/swfdec_rtmp_channel.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifndef _SWFDEC_RTMP_CHANNEL_H_ -#define _SWFDEC_RTMP_CHANNEL_H_ - -#include <swfdec/swfdec_rtmp_connection.h> -#include <swfdec/swfdec_rtmp_header.h> -#include <swfdec/swfdec_rtmp_packet.h> - -G_BEGIN_DECLS - - -typedef struct _SwfdecRtmpChannelClass SwfdecRtmpChannelClass; - -#define SWFDEC_TYPE_RTMP_CHANNEL (swfdec_rtmp_channel_get_type()) -#define SWFDEC_IS_RTMP_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_CHANNEL)) -#define SWFDEC_IS_RTMP_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_CHANNEL)) -#define SWFDEC_RTMP_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannel)) -#define SWFDEC_RTMP_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannelClass)) -#define SWFDEC_RTMP_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_CHANNEL, SwfdecRtmpChannelClass)) - -struct _SwfdecRtmpChannel { - GObject object; - - SwfdecRtmpConnection * conn; /* Connection this channel belongs to */ - guint channel_id; /* channel id inside connection or 0 if no connection */ - guint stream_id; /* stream id inside connection */ - - GTimeVal timestamp; /* timestamp for various uses - set when constructing */ - SwfdecRtmpHeader recv_cache; /* cached header info for receiving data */ - SwfdecBufferQueue * recv_queue; /* Queue of semi-assembled packages when receiving */ - SwfdecRtmpHeader send_cache; /* cached header info for sending data */ - SwfdecBufferQueue * send_queue; /* Queue of outgoing waiting for delivery */ -}; - -struct _SwfdecRtmpChannelClass { - GObjectClass object_class; - - void (* mark) (SwfdecRtmpChannel * channel); - void (* receive) (SwfdecRtmpChannel * channel, - const SwfdecRtmpHeader *header, - SwfdecBuffer * buffer); - SwfdecRtmpPacket * (* send) (SwfdecRtmpChannel * channel); -}; - -GType swfdec_rtmp_channel_get_type (void); - -SwfdecBuffer * swfdec_rtmp_channel_next_buffer (SwfdecRtmpChannel * channel); - -#define swfdec_rtmp_channel_get_time(channel, tv) (swfdec_as_context_get_time (swfdec_gc_object_get_context ((channel)->conn), tv)) -#define swfdec_rtmp_channel_is_registered(channel) ((channel)->channel_id > 0) -#define swfdec_rtmp_channel_send(channel) G_STMT_START{\ - if (swfdec_rtmp_channel_is_registered(channel)) \ - swfdec_rtmp_socket_send (channel->conn->socket); \ -}G_STMT_END -void swfdec_rtmp_channel_register (SwfdecRtmpChannel * channel, - guint channel_id, - guint stream_id); -void swfdec_rtmp_channel_unregister (SwfdecRtmpChannel * channel); - - - -G_END_DECLS -#endif diff --git a/swfdec/swfdec_rtmp_connection.c b/swfdec/swfdec_rtmp_connection.c index fcf3418c..208cc632 100644 --- a/swfdec/swfdec_rtmp_connection.c +++ b/swfdec/swfdec_rtmp_connection.c @@ -28,34 +28,180 @@ #include "swfdec_as_strings.h" #include "swfdec_bots.h" #include "swfdec_debug.h" -#include "swfdec_rtmp_control_channel.h" +#include "swfdec_sandbox.h" #include "swfdec_rtmp_handshake.h" -#include "swfdec_rtmp_rpc_channel.h" +#include "swfdec_rtmp_rpc.h" #include "swfdec_rtmp_socket.h" #include "swfdec_rtmp_stream.h" +#include "swfdec_utils.h" /*** SwfdecRtmpStream ***/ static void +swfdec_rtmp_connection_push_control (SwfdecRtmpConnection *conn, + SwfdecRtmpPacket *packet) +{ + g_return_if_fail (packet->header.channel == 2); + + if (g_queue_is_empty (conn->control_packets)) { + g_queue_push_tail (conn->control_packets, NULL); + swfdec_rtmp_connection_send (conn, packet); + } else { + g_queue_push_tail (conn->control_packets, packet); + } +} + +static void +swfdec_rtmp_connection_handle_chunk_size (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer) +{ + SwfdecBits bits; + guint new_size; + + swfdec_bits_init (&bits, buffer); + new_size = swfdec_bits_get_bu32 (&bits); + SWFDEC_INFO ("altering read chunk size %u => %u", conn->read_size, new_size); + conn->read_size = new_size; + if (swfdec_bits_left (&bits)) { + SWFDEC_FIXME ("%u bytes left after chunk size", swfdec_bits_left (&bits) / 8); + } +} + +static void +swfdec_rtmp_connection_handle_ping (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer) +{ + SwfdecBits bits; + guint type, target; + + swfdec_bits_init (&bits, buffer); + type = swfdec_bits_get_bu16 (&bits); + target = swfdec_bits_get_bu32 (&bits); + SWFDEC_FIXME ("handle ping type %u for target %u", type, target); +} + +static void +swfdec_rtmp_connection_handle_server_bandwidth (SwfdecRtmpConnection *conn, + const SwfdecRtmpHeader *org_header, SwfdecBuffer *buffer) +{ + SwfdecBits bits; + SwfdecBots *bots; + guint new_bandwidth; + SwfdecRtmpPacket *packet; + GTimeVal tv; + long diff; + + swfdec_bits_init (&bits, buffer); + new_bandwidth = swfdec_bits_get_bu32 (&bits); + SWFDEC_INFO ("new server bandwidth set: %u => %u", + conn->server_bandwidth, new_bandwidth); + conn->server_bandwidth = new_bandwidth; + + /* I guess this is for telling the server to throttle if we know our bandwidth is smaller */ + bots = swfdec_bots_new (); + swfdec_bots_put_bu32 (bots, new_bandwidth); + buffer = swfdec_bots_close (bots); + /* send diff between the timestamp that the server sent and our current time. + * FIXME: Is that correct? */ + swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &tv); + diff = swfdec_time_val_diff (&conn->connect_time, &tv); + packet = swfdec_rtmp_packet_new (2, 0, SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH, + org_header->timestamp - diff, buffer); + swfdec_buffer_unref (buffer); + + swfdec_rtmp_connection_push_control (conn, packet); +} + +static void +swfdec_rtmp_connection_handle_client_bandwidth (SwfdecRtmpConnection *conn, SwfdecBuffer *buffer) +{ + SwfdecBits bits; + guint magic; + + swfdec_bits_init (&bits, buffer); + conn->client_bandwidth = swfdec_bits_get_bu32 (&bits); + magic = swfdec_bits_get_u8 (&bits); + SWFDEC_INFO ("client bandwidth is %u, magic value set to %u", + conn->client_bandwidth, magic); +} + +static void swfdec_rtmp_connection_rtmp_stream_receive (SwfdecRtmpStream *stream, const SwfdecRtmpHeader *header, SwfdecBuffer *buffer) { SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (stream); - SwfdecRtmpChannel *channel = swfdec_rtmp_connection_get_channel (conn, header->channel); - SwfdecRtmpChannelClass *klass; - - if (channel == NULL) { - SWFDEC_FIXME ("woot, no channel %u", header->channel); - return; + + switch ((guint) header->type) { + case SWFDEC_RTMP_PACKET_SIZE: + swfdec_rtmp_connection_handle_chunk_size (conn, buffer); + break; + case SWFDEC_RTMP_PACKET_PING: + swfdec_rtmp_connection_handle_ping (conn, buffer); + break; + case SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH: + swfdec_rtmp_connection_handle_server_bandwidth (conn, header, buffer); + break; + case SWFDEC_RTMP_PACKET_CLIENT_BANDWIDTH: + swfdec_rtmp_connection_handle_client_bandwidth (conn, buffer); + break; + case SWFDEC_RTMP_PACKET_INVOKE: + swfdec_sandbox_use (conn->sandbox); + if (swfdec_rtmp_rpc_receive (conn->rpc, buffer)) { + SwfdecRtmpPacket *packet = swfdec_rtmp_rpc_pop (conn->rpc, FALSE); + if (packet) { + packet->header.channel = 3; + packet->header.stream = 0; + swfdec_rtmp_connection_send (conn, packet); + } + } + swfdec_sandbox_unuse (conn->sandbox); + break; + default: + SWFDEC_FIXME ("what to do with header type %u (channel %u)?", header->type, + header->channel); + break; + } +} + +static SwfdecRtmpPacket * +swfdec_rtmp_connection_rtmp_stream_sent (SwfdecRtmpStream *stream, + const SwfdecRtmpPacket *packet) +{ + SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (stream); + SwfdecRtmpPacket *result = NULL; + + switch (packet->header.channel) { + case 2: + { + GList *list; + if (g_queue_pop_head (conn->control_packets) != NULL) { + g_assert_not_reached (); + } + list = g_queue_peek_head_link (conn->control_packets); + if (list) { + result = list->data; + list->data = NULL; + } + } + break; + case 3: + result = swfdec_rtmp_rpc_pop (conn->rpc, TRUE); + if (result) { + result->header.channel = 3; + result->header.stream = 0; + } + break; + default: + g_assert_not_reached (); + break; } - klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel); - klass->receive (channel, header, buffer); + + return result; } static void swfdec_rtmp_connection_rtmp_stream_init (SwfdecRtmpStreamInterface *iface) { iface->receive = swfdec_rtmp_connection_rtmp_stream_receive; + iface->sent = swfdec_rtmp_connection_rtmp_stream_sent; } /*** SwfdecRtmpConnection ***/ @@ -67,18 +213,22 @@ static void swfdec_rtmp_connection_mark (SwfdecGcObject *object) { SwfdecRtmpConnection *conn = SWFDEC_RTMP_CONNECTION (object); - GList *walk; - for (walk = conn->channels; walk; walk = walk->next) { - SwfdecRtmpChannel *channel = walk->data; - SwfdecRtmpChannelClass *klass = SWFDEC_RTMP_CHANNEL_GET_CLASS (channel); - if (klass->mark) - klass->mark (channel); - } + swfdec_rtmp_rpc_mark (conn->rpc); SWFDEC_GC_OBJECT_CLASS (swfdec_rtmp_connection_parent_class)->mark (object); } +/* This function is necessary because we use packet->buffer->length as our write counter */ +static void +swfdec_rtmp_connection_packets_free (gpointer packetp) +{ + SwfdecRtmpPacket *packet = packetp; + + packet->buffer->length = packet->header.size; + swfdec_rtmp_packet_free (packet); +} + static void swfdec_rtmp_connection_dispose (GObject *object) { @@ -98,6 +248,20 @@ swfdec_rtmp_connection_dispose (GObject *object) g_hash_table_destroy (conn->streams); conn->streams = NULL; } + if (conn->packets) { + g_queue_foreach (conn->packets, (GFunc) swfdec_rtmp_connection_packets_free, NULL); + g_queue_free (conn->packets); + conn->packets = NULL; + } + if (conn->control_packets) { + g_queue_foreach (conn->control_packets, (GFunc) swfdec_rtmp_packet_free, NULL); + g_queue_free (conn->control_packets); + conn->control_packets = NULL; + } + if (conn->rpc) { + swfdec_rtmp_rpc_free (conn->rpc); + conn->rpc = NULL; + } G_OBJECT_CLASS (swfdec_rtmp_connection_parent_class)->dispose (object); } @@ -119,6 +283,10 @@ swfdec_rtmp_connection_init (SwfdecRtmpConnection *conn) conn->incoming = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) swfdec_rtmp_packet_free); conn->streams = g_hash_table_new (g_direct_hash, g_direct_equal); + conn->packets = g_queue_new (); + + conn->control_packets = g_queue_new (); + conn->rpc = swfdec_rtmp_rpc_new (conn, SWFDEC_AS_RELAY (conn)); conn->read_size = SWFDEC_RTMP_BLOCK_SIZE; conn->write_size = SWFDEC_RTMP_BLOCK_SIZE; @@ -129,8 +297,6 @@ swfdec_rtmp_connection_init (SwfdecRtmpConnection *conn) void swfdec_rtmp_connection_connect (SwfdecRtmpConnection *conn, const SwfdecURL *url) { - SwfdecRtmpChannel *channel; - g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn)); swfdec_rtmp_connection_close (conn); @@ -145,16 +311,9 @@ swfdec_rtmp_connection_connect (SwfdecRtmpConnection *conn, const SwfdecURL *url if (conn->error) return; + swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &conn->connect_time); + conn->rpc->last_send = conn->connect_time; conn->handshake = swfdec_rtmp_handshake_new (conn); - - channel = swfdec_rtmp_control_channel_new (conn); - swfdec_rtmp_channel_register (channel, 2, 0); - g_object_unref (channel); - channel = swfdec_rtmp_rpc_channel_new (conn); - swfdec_rtmp_channel_register (channel, 3, 0); - g_object_unref (channel); - conn->last_send = conn->channels; - swfdec_rtmp_socket_send (conn->socket); } @@ -163,17 +322,13 @@ swfdec_rtmp_connection_close (SwfdecRtmpConnection *conn) { g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn)); - while (conn->channels) - swfdec_rtmp_channel_unregister (conn->channels->data); + if (!swfdec_rtmp_connection_is_connected (conn)) + return; - if (conn->socket) { - g_object_unref (conn->socket); - conn->socket = NULL; - } - if (conn->url) { - swfdec_url_free (conn->url); - conn->url = NULL; - } + g_object_unref (conn->socket); + conn->socket = NULL; + swfdec_url_free (conn->url); + conn->url = NULL; } void @@ -217,27 +372,6 @@ swfdec_rtmp_connection_on_status (SwfdecRtmpConnection *conn, SwfdecAsValue valu swfdec_as_relay_call (SWFDEC_AS_RELAY (conn), SWFDEC_AS_STR_onStatus, 1, &value, NULL); } -SwfdecRtmpChannel * -swfdec_rtmp_connection_get_channel (SwfdecRtmpConnection *conn, guint id) -{ - SwfdecRtmpChannel *channel; - GList *walk; - - g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL); - g_return_val_if_fail (conn->channels != NULL, NULL); - - for (walk = conn->channels; walk; walk = walk->next) { - channel = walk->data; - if (channel->channel_id < id) - continue; - if (channel->channel_id == id) - return channel; - return NULL; - } - - return NULL; -} - void swfdec_rtmp_register_stream (SwfdecRtmpConnection *conn, guint id, SwfdecRtmpStream *stream) @@ -263,3 +397,23 @@ swfdec_rtmp_unregister_stream (SwfdecRtmpConnection *conn, guint id) g_assert_not_reached (); } } + +void +swfdec_rtmp_connection_send (SwfdecRtmpConnection *conn, SwfdecRtmpPacket *packet) +{ + gboolean send; + + g_return_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn)); + g_return_if_fail (packet != NULL); + /* FIXME: I'd like a g_return_if_fail (packet->channel is not already sent), + * but that requires a g_queue_find_custom () and that's slow */ + + g_assert (packet->header.size == packet->buffer->length); + packet->buffer->length = 0; + send = g_queue_is_empty (conn->packets); + g_queue_push_tail (conn->packets, packet); + g_print ("pushed channel %u - %u packets now\n", packet->header.channel, + g_queue_get_length (conn->packets)); + if (send) + swfdec_rtmp_socket_send (conn->socket); +} diff --git a/swfdec/swfdec_rtmp_connection.h b/swfdec/swfdec_rtmp_connection.h index 2a900dfa..13fbd7fa 100644 --- a/swfdec/swfdec_rtmp_connection.h +++ b/swfdec/swfdec_rtmp_connection.h @@ -23,6 +23,7 @@ #include <swfdec/swfdec.h> #include <swfdec/swfdec_as_relay.h> #include <swfdec/swfdec_rtmp_header.h> +#include <swfdec/swfdec_rtmp_packet.h> #include <swfdec/swfdec_types.h> G_BEGIN_DECLS @@ -32,8 +33,8 @@ G_BEGIN_DECLS #define SWFDEC_RTMP_BLOCK_SIZE 128 /* forward declarations */ -typedef struct _SwfdecRtmpChannel SwfdecRtmpChannel; typedef struct _SwfdecRtmpHandshake SwfdecRtmpHandshake; +typedef struct _SwfdecRtmpRpc SwfdecRtmpRpc; typedef struct _SwfdecRtmpSocket SwfdecRtmpSocket; typedef struct _SwfdecRtmpStream SwfdecRtmpStream; @@ -53,15 +54,20 @@ struct _SwfdecRtmpConnection { SwfdecURL * url; /* URL in use by this connection */ SwfdecSandbox * sandbox; /* sandbox we execute functions in or NULL */ SwfdecRtmpSocket * socket; /* socket we're using for read/write */ - GList * channels; /* list of channels in use by this connection (ordered by channel) */ - GList * last_send; /* list entry of last channel sent to */ SwfdecRtmpHandshake * handshake; /* structure used for doing initial handshake or NULL */ char * error; /* NULL or debug string for error message */ GHashTable * incoming; /* channel id => incoming packets */ GHashTable * streams; /* stream id => stream */ + GQueue * packets; /* queue of packets in send order */ + GTimeVal connect_time; /* time at which this connectioon was opened */ + + GQueue * control_packets;/* packets waiting to be sent on queue 2 */ + SwfdecRtmpRpc * rpc; /* queue for rpc */ guint read_size; /* size of a block of data when reading */ guint write_size; /* size of a block of data when writing */ + guint server_bandwidth; /* ??? */ + guint client_bandwidth; /* ??? */ }; struct _SwfdecRtmpConnectionClass { @@ -70,15 +76,16 @@ struct _SwfdecRtmpConnectionClass { GType swfdec_rtmp_connection_get_type (void); +#define swfdec_rtmp_connection_is_connected(conn) ((conn)->socket != NULL) void swfdec_rtmp_connection_connect (SwfdecRtmpConnection * conn, const SwfdecURL * url); void swfdec_rtmp_connection_close (SwfdecRtmpConnection * conn); void swfdec_rtmp_connection_receive (SwfdecRtmpConnection * conn, SwfdecBufferQueue * queue); -void swfdec_rtmp_connection_send (SwfdecRtmpConnection * conn); -SwfdecRtmpChannel * swfdec_rtmp_connection_get_channel (SwfdecRtmpConnection * conn, - guint id); +void swfdec_rtmp_connection_send (SwfdecRtmpConnection * conn, + SwfdecRtmpPacket * packet); + void swfdec_rtmp_connection_error (SwfdecRtmpConnection * conn, const char * error, ...) G_GNUC_PRINTF (2, 3); @@ -94,9 +101,6 @@ void swfdec_rtmp_register_stream (SwfdecRtmpConnection * conn, void swfdec_rtmp_unregister_stream (SwfdecRtmpConnection * conn, guint id); -#define swfdec_rtmp_connection_get_command_channel(conn) (swfdec_rtmp_connection_get_channel (conn, 2)) -#define swfdec_rtmp_connection_get_rpc_channel(conn) (swfdec_rtmp_connection_get_channel (conn, 3)) - G_END_DECLS #endif diff --git a/swfdec/swfdec_rtmp_control_channel.c b/swfdec/swfdec_rtmp_control_channel.c deleted file mode 100644 index 013862aa..00000000 --- a/swfdec/swfdec_rtmp_control_channel.c +++ /dev/null @@ -1,187 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "swfdec_rtmp_control_channel.h" - -#include "swfdec_debug.h" -#include "swfdec_rtmp_socket.h" -#include "swfdec_utils.h" - -/*** SwfdecRtmpControlChannel ***/ - -G_DEFINE_TYPE (SwfdecRtmpControlChannel, swfdec_rtmp_control_channel, SWFDEC_TYPE_RTMP_CHANNEL) - -static void -swfdec_rtmp_control_channel_push (SwfdecRtmpControlChannel *control, - SwfdecRtmpPacket *packet) -{ - gboolean empty = g_queue_is_empty (control->send_packets); - - g_queue_push_tail (control->send_packets, packet); - - if (empty) - swfdec_rtmp_channel_send (SWFDEC_RTMP_CHANNEL (control)); -} - -static void -swfdec_rtmp_control_channel_handle_chunk_size (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer) -{ - SwfdecBits bits; - - swfdec_bits_init (&bits, buffer); - channel->conn->read_size = swfdec_bits_get_bu32 (&bits); - SWFDEC_INFO ("setting read chunk size to %u", channel->conn->read_size); - if (swfdec_bits_left (&bits)) { - SWFDEC_FIXME ("%u bytes left after chunk size", swfdec_bits_left (&bits) / 8); - } -} - -static void -swfdec_rtmp_control_channel_handle_ping (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer) -{ - SwfdecBits bits; - guint type, target; - - swfdec_bits_init (&bits, buffer); - type = swfdec_bits_get_bu16 (&bits); - target = swfdec_bits_get_bu32 (&bits); - SWFDEC_FIXME ("handle ping type %u for target %u", type, target); -} - -static void -swfdec_rtmp_control_channel_handle_server_bandwidth (SwfdecRtmpChannel *channel, - const SwfdecRtmpHeader *org_header, SwfdecBuffer *buffer) -{ - SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel); - SwfdecBits bits; - SwfdecBots *bots; - guint new_bandwidth; - SwfdecRtmpPacket *packet; - GTimeVal tv; - long diff; - - swfdec_bits_init (&bits, buffer); - new_bandwidth = swfdec_bits_get_bu32 (&bits); - SWFDEC_INFO ("new server bandwidth set: %u => %u", - control->server_bandwidth, new_bandwidth); - control->server_bandwidth = new_bandwidth; - - /* I guess this is for telling the server to throttle if we know our bandwidth is smaller */ - bots = swfdec_bots_new (); - swfdec_bots_put_bu32 (bots, new_bandwidth); - buffer = swfdec_bots_close (bots); - /* send diff between the timestamp that the server sent and our current time. - * FIXME: Is that correct? */ - swfdec_rtmp_channel_get_time (channel, &tv); - diff = swfdec_time_val_diff (&channel->timestamp, &tv); - packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH, - org_header->timestamp - diff, buffer); - swfdec_buffer_unref (buffer); - - swfdec_rtmp_control_channel_push (control, packet); -} - -static void -swfdec_rtmp_control_channel_handle_client_bandwidth (SwfdecRtmpChannel *channel, SwfdecBuffer *buffer) -{ - SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel); - SwfdecBits bits; - guint magic; - - swfdec_bits_init (&bits, buffer); - control->client_bandwidth = swfdec_bits_get_bu32 (&bits); - magic = swfdec_bits_get_u8 (&bits); - SWFDEC_INFO ("client bandwidth is %u, magic value set to %u", - control->client_bandwidth, magic); -} - -static void -swfdec_rtmp_control_channel_receive (SwfdecRtmpChannel *channel, - const SwfdecRtmpHeader *header, SwfdecBuffer *buffer) -{ - switch ((guint) header->type) { - case SWFDEC_RTMP_PACKET_SIZE: - swfdec_rtmp_control_channel_handle_chunk_size (channel, buffer); - break; - case SWFDEC_RTMP_PACKET_PING: - swfdec_rtmp_control_channel_handle_ping (channel, buffer); - break; - case SWFDEC_RTMP_PACKET_SERVER_BANDWIDTH: - swfdec_rtmp_control_channel_handle_server_bandwidth (channel, header, buffer); - break; - case SWFDEC_RTMP_PACKET_CLIENT_BANDWIDTH: - swfdec_rtmp_control_channel_handle_client_bandwidth (channel, buffer); - break; - default: - SWFDEC_FIXME ("what to do with header type %u?", header->type); - break; - } -} - -static SwfdecRtmpPacket * -swfdec_rtmp_control_channel_send (SwfdecRtmpChannel *channel) -{ - SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (channel); - - return g_queue_pop_head (control->send_packets); -} - -static void -swfdec_rtmp_control_channel_dispose (GObject *object) -{ - SwfdecRtmpControlChannel *control = SWFDEC_RTMP_CONTROL_CHANNEL (object); - - if (control->send_packets) { - g_queue_foreach (control->send_packets, (GFunc) swfdec_rtmp_packet_free, NULL); - g_queue_free (control->send_packets); - control->send_packets = NULL; - } - - G_OBJECT_CLASS (swfdec_rtmp_control_channel_parent_class)->dispose (object); -} - -static void -swfdec_rtmp_control_channel_class_init (SwfdecRtmpControlChannelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass); - - object_class->dispose = swfdec_rtmp_control_channel_dispose; - - channel_class->receive = swfdec_rtmp_control_channel_receive; - channel_class->send = swfdec_rtmp_control_channel_send; -} - -static void -swfdec_rtmp_control_channel_init (SwfdecRtmpControlChannel *control) -{ - control->send_packets = g_queue_new (); -} - -SwfdecRtmpChannel * -swfdec_rtmp_control_channel_new (SwfdecRtmpConnection *conn) -{ - g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL); - - return g_object_new (SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, "connection", conn, NULL); -} diff --git a/swfdec/swfdec_rtmp_control_channel.h b/swfdec/swfdec_rtmp_control_channel.h deleted file mode 100644 index 5a56bc6f..00000000 --- a/swfdec/swfdec_rtmp_control_channel.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifndef _SWFDEC_RTMP_CONTROL_CHANNEL_H_ -#define _SWFDEC_RTMP_CONTROL_CHANNEL_H_ - -#include <swfdec/swfdec_rtmp_channel.h> - -G_BEGIN_DECLS - - -typedef struct _SwfdecRtmpControlChannel SwfdecRtmpControlChannel; -typedef struct _SwfdecRtmpControlChannelClass SwfdecRtmpControlChannelClass; - -#define SWFDEC_TYPE_RTMP_CONTROL_CHANNEL (swfdec_rtmp_control_channel_get_type()) -#define SWFDEC_IS_RTMP_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL)) -#define SWFDEC_IS_RTMP_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL)) -#define SWFDEC_RTMP_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannel)) -#define SWFDEC_RTMP_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannelClass)) -#define SWFDEC_RTMP_CONTROL_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_CONTROL_CHANNEL, SwfdecRtmpControlChannelClass)) - -struct _SwfdecRtmpControlChannel { - SwfdecRtmpChannel channel; - - GQueue * send_packets; /* packets that still need to be sent */ - guint server_bandwidth; - guint client_bandwidth; -}; - -struct _SwfdecRtmpControlChannelClass { - SwfdecRtmpChannelClass channel_class; -}; - -GType swfdec_rtmp_control_channel_get_type (void); - -SwfdecRtmpChannel * swfdec_rtmp_control_channel_new (SwfdecRtmpConnection * conn); - - -G_END_DECLS -#endif diff --git a/swfdec/swfdec_rtmp_packet.c b/swfdec/swfdec_rtmp_packet.c index ae3d1332..be2c2a8e 100644 --- a/swfdec/swfdec_rtmp_packet.c +++ b/swfdec/swfdec_rtmp_packet.c @@ -30,16 +30,19 @@ swfdec_rtmp_packet_new_empty (void) } SwfdecRtmpPacket * -swfdec_rtmp_packet_new (SwfdecRtmpPacketType type, guint timestamp, - SwfdecBuffer *buffer) +swfdec_rtmp_packet_new (guint channel, guint stream, SwfdecRtmpPacketType type, + guint timestamp, SwfdecBuffer *buffer) { SwfdecRtmpPacket *packet; g_return_val_if_fail (buffer != NULL, NULL); packet = swfdec_rtmp_packet_new_empty (); + packet->header.channel = channel; + packet->header.stream = stream; packet->header.type = type; packet->header.timestamp = timestamp; + packet->header.size = buffer->length; packet->buffer = swfdec_buffer_ref (buffer); return packet; diff --git a/swfdec/swfdec_rtmp_packet.h b/swfdec/swfdec_rtmp_packet.h index 96482f04..eee13ccc 100644 --- a/swfdec/swfdec_rtmp_packet.h +++ b/swfdec/swfdec_rtmp_packet.h @@ -34,7 +34,9 @@ struct _SwfdecRtmpPacket { }; SwfdecRtmpPacket * swfdec_rtmp_packet_new_empty (void); -SwfdecRtmpPacket * swfdec_rtmp_packet_new (SwfdecRtmpPacketType type, +SwfdecRtmpPacket * swfdec_rtmp_packet_new (guint channel, + guint stream, + SwfdecRtmpPacketType type, guint timestamp, SwfdecBuffer * buffer); void swfdec_rtmp_packet_free (SwfdecRtmpPacket * packet); diff --git a/swfdec/swfdec_rtmp_rpc.c b/swfdec/swfdec_rtmp_rpc.c index 984552a6..45481819 100644 --- a/swfdec/swfdec_rtmp_rpc.c +++ b/swfdec/swfdec_rtmp_rpc.c @@ -77,7 +77,7 @@ swfdec_rtmp_rpc_do_send (SwfdecRtmpRpc *rpc, SwfdecAsValue name, buffer = swfdec_rtmp_rpc_encode (swfdec_gc_object_get_context (rpc->conn), name, id, special, argc, argv); - packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_INVOKE, + packet = swfdec_rtmp_packet_new (0, 0, SWFDEC_RTMP_PACKET_INVOKE, swfdec_rtmp_rpc_update_last_send (rpc), buffer); swfdec_buffer_unref (buffer); empty = g_queue_is_empty (rpc->packets); @@ -137,7 +137,7 @@ swfdec_rtmp_rpc_receive_reply (SwfdecRtmpRpc *rpc, } } -static void +static gboolean swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx, SwfdecAsValue val, SwfdecBits *bits) { @@ -149,7 +149,7 @@ swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx, name = swfdec_as_value_to_string (context, val); if (!swfdec_amf_decode (cx, bits, &val)) { SWFDEC_ERROR ("could not decode reply id"); - return; + return FALSE; } id = swfdec_as_value_to_integer (context, val); @@ -160,64 +160,69 @@ swfdec_rtmp_rpc_receive_call (SwfdecRtmpRpc *rpc, SwfdecAmfContext *cx, if (!swfdec_amf_decode (cx, bits, &args[i])) { SWFDEC_ERROR ("could not decode argument %u", i); - return; + return FALSE; } } - swfdec_as_object_call (rpc->target, name, i, args, &val); + swfdec_as_relay_call (rpc->target, name, i, args, &val); g_free (args); /* send reply */ if (id) { swfdec_rtmp_rpc_do_send (rpc, SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR__result), id, val, 0, NULL); + return TRUE; + } else { + return FALSE; } } -void -swfdec_rtmp_rpc_receive (SwfdecRtmpRpc *rpc, - const SwfdecRtmpHeader *header, SwfdecBuffer *buffer) +gboolean +swfdec_rtmp_rpc_receive (SwfdecRtmpRpc *rpc, SwfdecBuffer *buffer) { SwfdecAmfContext *cx; SwfdecAsContext *context; SwfdecAsValue val; SwfdecBits bits; + gboolean result; context = swfdec_gc_object_get_context (rpc->conn); cx = swfdec_amf_context_new (context); g_assert (context->global); + swfdec_bits_init (&bits, buffer); - switch ((guint) header->type) { - case SWFDEC_RTMP_PACKET_INVOKE: - swfdec_bits_init (&bits, buffer); - if (!swfdec_amf_decode (cx, &bits, &val)) { - SWFDEC_ERROR ("could not decode call name"); - break; - } - if (SWFDEC_AS_VALUE_IS_STRING (val) && - SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) { - swfdec_rtmp_rpc_receive_reply (rpc, cx, &bits); - } else { - swfdec_rtmp_rpc_receive_call (rpc, cx, val, &bits); - } - if (swfdec_bits_left (&bits)) { - SWFDEC_FIXME ("%u bytes left after invoke on channel %u (stream %u)", - swfdec_bits_left (&bits) / 8, header->channel, header->stream); - } - break; - default: - SWFDEC_FIXME ("channel %u: what to do with header type %u?", - header->channel, header->type); - break; + if (!swfdec_amf_decode (cx, &bits, &val)) { + SWFDEC_ERROR ("could not decode call name"); + return FALSE; + } + if (SWFDEC_AS_VALUE_IS_STRING (val) && + SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) { + swfdec_rtmp_rpc_receive_reply (rpc, cx, &bits); + result = FALSE; + } else { + result = swfdec_rtmp_rpc_receive_call (rpc, cx, val, &bits); } swfdec_amf_context_free (cx); + + if (swfdec_bits_left (&bits)) { + SWFDEC_FIXME ("%u bytes left after invoke", swfdec_bits_left (&bits) / 8); + } + + return result; } SwfdecRtmpPacket * -swfdec_rtmp_rpc_pop (SwfdecRtmpRpc *rpc) +swfdec_rtmp_rpc_pop (SwfdecRtmpRpc *rpc, gboolean pull_if_pending) { + SwfdecRtmpPacket *packet; + g_return_val_if_fail (rpc != NULL, NULL); - return g_queue_pop_head (rpc->packets); + if (!pull_if_pending && rpc->packet_pending) + return NULL; + + packet = g_queue_pop_head (rpc->packets); + rpc->packet_pending = (packet != NULL); + return packet; } void @@ -239,19 +244,18 @@ swfdec_rtmp_rpc_send (SwfdecRtmpRpc *rpc, SwfdecAsValue name, } SwfdecRtmpRpc * -swfdec_rtmp_rpc_new (SwfdecRtmpConnection *conn, SwfdecAsObject *target) +swfdec_rtmp_rpc_new (SwfdecRtmpConnection *conn, SwfdecAsRelay *target) { SwfdecRtmpRpc *rpc; g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL); - g_return_val_if_fail (target != NULL, NULL); + g_return_val_if_fail (SWFDEC_IS_AS_RELAY (target), NULL); - rpc = g_slice_new (SwfdecRtmpRpc); + rpc = g_slice_new0 (SwfdecRtmpRpc); rpc->conn = conn; rpc->target = target; rpc->pending = g_hash_table_new (g_direct_hash, g_direct_equal); rpc->packets = g_queue_new (); - swfdec_as_context_get_time (swfdec_gc_object_get_context (conn), &rpc->last_send); return rpc; } @@ -269,7 +273,7 @@ swfdec_rtmp_rpc_mark (SwfdecRtmpRpc *rpc) swfdec_as_object_mark (value); } - swfdec_as_object_mark (rpc->target); + swfdec_gc_object_mark (rpc->target); } void diff --git a/swfdec/swfdec_rtmp_rpc.h b/swfdec/swfdec_rtmp_rpc.h index 2dd5a80b..3ca46e61 100644 --- a/swfdec/swfdec_rtmp_rpc.h +++ b/swfdec/swfdec_rtmp_rpc.h @@ -26,19 +26,18 @@ G_BEGIN_DECLS -typedef struct _SwfdecRtmpRpc SwfdecRtmpRpc; - struct _SwfdecRtmpRpc { SwfdecRtmpConnection * conn; /* connection to use */ - SwfdecAsObject * target; /* object to call received calls on */ + SwfdecAsRelay * target; /* object to call received calls on */ guint id; /* last id used for RPC call */ GHashTable * pending; /* int => SwfdecAsObject mapping of calls having pending replies */ GQueue * packets; /* outstanding SwfdecRtmpPackets */ + gboolean packet_pending; /* if a packet is known to be pending */ GTimeVal last_send; /* time the last call was sent */ }; SwfdecRtmpRpc * swfdec_rtmp_rpc_new (SwfdecRtmpConnection * conn, - SwfdecAsObject * target); + SwfdecAsRelay * target); void swfdec_rtmp_rpc_free (SwfdecRtmpRpc * rpc); void swfdec_rtmp_rpc_mark (SwfdecRtmpRpc * rpc); @@ -49,14 +48,14 @@ SwfdecBuffer * swfdec_rtmp_rpc_encode (SwfdecAsContext * context, guint argc, const SwfdecAsValue * argv); -SwfdecRtmpPacket * swfdec_rtmp_rpc_pop (SwfdecRtmpRpc * rpc); +SwfdecRtmpPacket * swfdec_rtmp_rpc_pop (SwfdecRtmpRpc * rpc, + gboolean pull_if_pending); void swfdec_rtmp_rpc_send (SwfdecRtmpRpc * rpc, SwfdecAsValue name, SwfdecAsObject * reply_to, guint argc, const SwfdecAsValue * argv); -void swfdec_rtmp_rpc_receive (SwfdecRtmpRpc * rpc, - const SwfdecRtmpHeader *header, +gboolean swfdec_rtmp_rpc_receive (SwfdecRtmpRpc * rpc, SwfdecBuffer * buffer); diff --git a/swfdec/swfdec_rtmp_rpc_channel.c b/swfdec/swfdec_rtmp_rpc_channel.c deleted file mode 100644 index 47b7973f..00000000 --- a/swfdec/swfdec_rtmp_rpc_channel.c +++ /dev/null @@ -1,319 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "swfdec_rtmp_rpc_channel.h" - -#include "swfdec_amf.h" -#include "swfdec_as_strings.h" -#include "swfdec_debug.h" -#include "swfdec_rtmp_handshake.h" -#include "swfdec_rtmp_socket.h" -#include "swfdec_sandbox.h" -#include "swfdec_utils.h" - -/*** SwfdecRtmpRpcChannel ***/ - -G_DEFINE_TYPE (SwfdecRtmpRpcChannel, swfdec_rtmp_rpc_channel, SWFDEC_TYPE_RTMP_CHANNEL) - -static guint -swfdec_rtmp_rpc_channel_update_last_send (SwfdecRtmpChannel *channel) -{ - GTimeVal tv; - long diff; - - swfdec_rtmp_channel_get_time (channel, &tv); - diff = swfdec_time_val_diff (&channel->timestamp, &tv); - channel->timestamp = tv; - return diff; -} - -static void -swfdec_rtmp_rpc_channel_do_send (SwfdecRtmpRpcChannel *rpc, SwfdecAsValue name, - guint id, SwfdecAsValue special, guint argc, const SwfdecAsValue *argv) -{ - SwfdecRtmpChannel *channel; - SwfdecAsContext *context; - SwfdecRtmpPacket *packet; - SwfdecAmfContext *cx; - SwfdecBuffer *buffer; - SwfdecBots *bots; - gboolean empty; - guint i; - - channel = SWFDEC_RTMP_CHANNEL (rpc); - context = swfdec_gc_object_get_context (channel->conn); - - /* prepare buffer to encode */ - cx = swfdec_amf_context_new (context); - bots = swfdec_bots_new (); - swfdec_amf_encode (cx, bots, name); - swfdec_amf_encode (cx, bots, swfdec_as_value_from_number (context, id)); - swfdec_amf_encode (cx, bots, special); - for (i = 0; i < argc; i++) { - swfdec_amf_encode (cx, bots, argv[i]); - } - buffer = swfdec_bots_close (bots); - swfdec_amf_context_free (cx); - - packet = swfdec_rtmp_packet_new (SWFDEC_RTMP_PACKET_INVOKE, - swfdec_rtmp_rpc_channel_update_last_send (channel), buffer); - empty = g_queue_is_empty (rpc->packets); - g_queue_push_tail (rpc->packets, packet); - if (empty) - swfdec_rtmp_channel_send (channel); -} - -static void -swfdec_rtmp_rpc_channel_receive_reply (SwfdecRtmpChannel *channel, - SwfdecAmfContext *cx, SwfdecBits *bits) -{ - SwfdecAsContext *context = swfdec_gc_object_get_context (channel->conn); - SwfdecAsObject *reply_to; - SwfdecAsValue val[2], tmp; - guint id, i; - - if (!swfdec_amf_decode (cx, bits, &tmp)) { - SWFDEC_ERROR ("could not decode reply id"); - return; - } - id = swfdec_as_value_to_integer (context, tmp); - - for (i = 0; swfdec_bits_left (bits) && i < 2; i++) { - if (!swfdec_amf_decode (cx, bits, &val[i])) { - SWFDEC_ERROR ("could not decode reply value"); - return; - } - } - if (swfdec_bits_left (bits)) { - SWFDEC_FIXME ("more than 2 values in a reply?"); - } - - if (id == 1 && channel->conn->handshake) { - SwfdecRtmpConnection *conn = channel->conn; - - /* FIXME: Do something with the result value */ - - if (i >= 2) { - swfdec_rtmp_connection_on_status (conn, val[1]); - } else { - SWFDEC_ERROR ("no 2nd argument in connect reply"); - } - - swfdec_rtmp_handshake_free (conn->handshake); - conn->handshake = NULL; - swfdec_rtmp_socket_send (conn->socket); - } else { - if (!SWFDEC_AS_VALUE_IS_NULL (val[0])) { - SWFDEC_FIXME ("first argument in reply is not null?"); - } - reply_to = g_hash_table_lookup (SWFDEC_RTMP_RPC_CHANNEL (channel)->pending, - GUINT_TO_POINTER (id)); - if (reply_to == NULL) { - SWFDEC_ERROR ("no object to send a reply to"); - return; - } - g_hash_table_steal (SWFDEC_RTMP_RPC_CHANNEL (channel)->pending, GUINT_TO_POINTER (id)); - swfdec_as_object_call (reply_to, SWFDEC_AS_STR_onResult, 1, &val[1], NULL); - } -} - -static void -swfdec_rtmp_rpc_channel_receive_call (SwfdecRtmpChannel *channel, - SwfdecAmfContext *cx, SwfdecAsValue val, SwfdecBits *bits) -{ - SwfdecAsContext *context = swfdec_gc_object_get_context (channel->conn); - SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (channel); - const char *name; - guint id, i; - SwfdecAsValue *args; - - name = swfdec_as_value_to_string (context, val); - if (!swfdec_amf_decode (cx, bits, &val)) { - SWFDEC_ERROR ("could not decode reply id"); - return; - } - id = swfdec_as_value_to_integer (context, val); - - args = NULL; - for (i = 0; swfdec_bits_left (bits); i++) { - if ((i % 4) == 0) - args = g_realloc (args, sizeof (SwfdecAsValue) * (i + 4)); - - if (!swfdec_amf_decode (cx, bits, &args[i])) { - SWFDEC_ERROR ("could not decode argument %u", i); - return; - } - } - swfdec_as_object_call (rpc->target, name, i, args, &val); - g_free (args); - - /* send reply */ - if (id) { - swfdec_rtmp_rpc_channel_do_send (rpc, - SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR__result), id, val, 0, NULL); - } -} - -static void -swfdec_rtmp_rpc_channel_receive (SwfdecRtmpChannel *channel, - const SwfdecRtmpHeader *header, SwfdecBuffer *buffer) -{ - SwfdecAsContext *context; - SwfdecAmfContext *cx; - SwfdecAsValue val; - SwfdecBits bits; - - context = swfdec_gc_object_get_context (channel->conn); - cx = swfdec_amf_context_new (context); - swfdec_sandbox_use (channel->conn->sandbox); - switch ((guint) header->type) { - case SWFDEC_RTMP_PACKET_INVOKE: - swfdec_bits_init (&bits, buffer); - if (!swfdec_amf_decode (cx, &bits, &val)) { - SWFDEC_ERROR ("could not decode call name"); - break; - } - if (SWFDEC_AS_VALUE_IS_STRING (val) && - SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR__result) { - swfdec_rtmp_rpc_channel_receive_reply (channel, cx, &bits); - } else { - swfdec_rtmp_rpc_channel_receive_call (channel, cx, val, &bits); - } - break; - default: - SWFDEC_FIXME ("channel %u: what to do with header type %u?", - channel->channel_id, header->type); - break; - } - swfdec_sandbox_unuse (channel->conn->sandbox); - swfdec_amf_context_free (cx); -} - -static SwfdecRtmpPacket * -swfdec_rtmp_rpc_channel_send_vfunc (SwfdecRtmpChannel *channel) -{ - return g_queue_pop_head (SWFDEC_RTMP_RPC_CHANNEL (channel)->packets); -} - -static void -swfdec_rtmp_rpc_channel_mark (SwfdecRtmpChannel *channel) -{ - SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (channel); - GHashTableIter iter; - gpointer value; - - for (g_hash_table_iter_init (&iter, rpc->pending); - g_hash_table_iter_next (&iter, NULL, &value);) { - swfdec_as_object_mark (value); - } - - swfdec_as_object_mark (rpc->target); -} - -static void -swfdec_rtmp_rpc_channel_dispose (GObject *object) -{ - SwfdecRtmpRpcChannel *rpc = SWFDEC_RTMP_RPC_CHANNEL (object); - - if (rpc->pending) { - g_hash_table_destroy (rpc->pending); - rpc->pending = NULL; - } - if (rpc->packets) { - g_queue_foreach (rpc->packets, (GFunc) swfdec_rtmp_packet_free, NULL); - g_queue_free (rpc->packets); - rpc->packets = NULL; - } - - - G_OBJECT_CLASS (swfdec_rtmp_rpc_channel_parent_class)->dispose (object); -} - -static void -swfdec_rtmp_rpc_channel_class_init (SwfdecRtmpRpcChannelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass); - - object_class->dispose = swfdec_rtmp_rpc_channel_dispose; - - channel_class->mark = swfdec_rtmp_rpc_channel_mark; - channel_class->receive = swfdec_rtmp_rpc_channel_receive; - channel_class->send = swfdec_rtmp_rpc_channel_send_vfunc; -} - -static void -swfdec_rtmp_rpc_channel_init (SwfdecRtmpRpcChannel *rpc) -{ - rpc->pending = g_hash_table_new (g_direct_hash, g_direct_equal); - rpc->packets = g_queue_new (); -} - -void -swfdec_rtmp_rpc_channel_send_connect (SwfdecRtmpRpcChannel *rpc, - SwfdecAsValue connect) -{ - swfdec_rtmp_rpc_channel_do_send (rpc, SWFDEC_AS_VALUE_FROM_STRING (SWFDEC_AS_STR_connect), - ++rpc->id, connect, 0, NULL); -} - -void -swfdec_rtmp_rpc_channel_send (SwfdecRtmpRpcChannel *rpc, - SwfdecAsValue name, SwfdecAsObject *reply_to, - guint argc, const SwfdecAsValue *argv) -{ - guint id; - - g_return_if_fail (SWFDEC_IS_RTMP_RPC_CHANNEL (rpc)); - g_return_if_fail (argc == 0 || argv != NULL); - - if (reply_to) { - id = ++rpc->id; - g_hash_table_insert (rpc->pending, GUINT_TO_POINTER (id), reply_to); - } else { - id = 0; - } - swfdec_rtmp_rpc_channel_do_send (rpc, name, id, SWFDEC_AS_VALUE_NULL, argc, argv); -} - -SwfdecRtmpChannel * -swfdec_rtmp_rpc_channel_new (SwfdecRtmpConnection *conn) -{ - SwfdecRtmpRpcChannel *rpc; - g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL); - - rpc = g_object_new (SWFDEC_TYPE_RTMP_RPC_CHANNEL, "connection", conn, NULL); - rpc->target = swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (conn)); - - return SWFDEC_RTMP_CHANNEL (rpc); -} - -void -swfdec_rtmp_rpc_channel_set_target (SwfdecRtmpRpcChannel *rpc, SwfdecAsObject *object) -{ - g_return_if_fail (SWFDEC_IS_RTMP_RPC_CHANNEL (rpc)); - g_return_if_fail (object != NULL); - - rpc->target = object; -} - diff --git a/swfdec/swfdec_rtmp_rpc_channel.h b/swfdec/swfdec_rtmp_rpc_channel.h deleted file mode 100644 index b4b69b1e..00000000 --- a/swfdec/swfdec_rtmp_rpc_channel.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifndef _SWFDEC_RTMP_RPC_CHANNEL_H_ -#define _SWFDEC_RTMP_RPC_CHANNEL_H_ - -#include <swfdec/swfdec_ringbuffer.h> -#include <swfdec/swfdec_rtmp_channel.h> - -G_BEGIN_DECLS - - -typedef struct _SwfdecRtmpRpcChannel SwfdecRtmpRpcChannel; -typedef struct _SwfdecRtmpRpcChannelClass SwfdecRtmpRpcChannelClass; - -#define SWFDEC_TYPE_RTMP_RPC_CHANNEL (swfdec_rtmp_rpc_channel_get_type()) -#define SWFDEC_IS_RTMP_RPC_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL)) -#define SWFDEC_IS_RTMP_RPC_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_RPC_CHANNEL)) -#define SWFDEC_RTMP_RPC_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannel)) -#define SWFDEC_RTMP_RPC_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannelClass)) -#define SWFDEC_RTMP_RPC_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_RPC_CHANNEL, SwfdecRtmpRpcChannelClass)) - -struct _SwfdecRtmpRpcChannel { - SwfdecRtmpChannel channel; - - SwfdecAsObject * target; /* object to call received calls on */ - guint id; /* last id used for RPC call */ - GHashTable * pending; /* int => SwfdecAsObject mapping of calls having pending replies */ - GQueue * packets; /* outstanding packets */ - GTimeVal last_send; /* time the last call was sent */ -}; - -struct _SwfdecRtmpRpcChannelClass { - SwfdecRtmpChannelClass channel_class; -}; - -GType swfdec_rtmp_rpc_channel_get_type (void); - -SwfdecRtmpChannel * swfdec_rtmp_rpc_channel_new (SwfdecRtmpConnection * conn); - -void swfdec_rtmp_rpc_channel_send_connect (SwfdecRtmpRpcChannel * rpc, - SwfdecAsValue connect); -void swfdec_rtmp_rpc_channel_send (SwfdecRtmpRpcChannel * rpc, - SwfdecAsValue name, - SwfdecAsObject * reply_to, - guint argc, - const SwfdecAsValue * argv); - -void swfdec_rtmp_rpc_channel_set_target (SwfdecRtmpRpcChannel * rpc, - SwfdecAsObject * object); - - -G_END_DECLS -#endif diff --git a/swfdec/swfdec_rtmp_socket.c b/swfdec/swfdec_rtmp_socket.c index 11dfbca2..7bacb34b 100644 --- a/swfdec/swfdec_rtmp_socket.c +++ b/swfdec/swfdec_rtmp_socket.c @@ -27,7 +27,6 @@ #include "swfdec_debug.h" #include "swfdec_player_internal.h" -#include "swfdec_rtmp_channel.h" #include "swfdec_rtmp_handshake.h" #include "swfdec_rtmp_stream.h" /* socket implementations for swfdec_rtmp_socket_new() */ @@ -121,9 +120,8 @@ SwfdecBuffer * swfdec_rtmp_socket_next_buffer (SwfdecRtmpSocket *socket) { SwfdecRtmpConnection *conn; - SwfdecRtmpChannel *channel; - SwfdecBuffer *buffer; - GList *walk; + SwfdecRtmpPacket *packet; + SwfdecBots *bots; g_return_val_if_fail (SWFDEC_IS_RTMP_SOCKET (socket), NULL); @@ -132,18 +130,42 @@ swfdec_rtmp_socket_next_buffer (SwfdecRtmpSocket *socket) if (G_UNLIKELY (conn->handshake)) return swfdec_rtmp_handshake_next_buffer (conn->handshake); - walk = conn->last_send; - g_assert (walk); - do { - walk = walk->next ? walk->next : conn->channels; - channel = walk->data; - buffer = swfdec_rtmp_channel_next_buffer (channel); - if (buffer != NULL) { - conn->last_send = walk; - return buffer; + bots = swfdec_bots_new (); +next_packet: + packet = g_queue_pop_head (conn->packets); + if (packet == NULL) + return NULL; + if (packet->header.size == packet->buffer->length) { + SwfdecRtmpStream *stream; + SwfdecRtmpPacket *next; + + stream = g_hash_table_lookup (conn->streams, GUINT_TO_POINTER (packet->header.stream)); + if (stream == NULL) { + swfdec_rtmp_packet_free (packet); + goto next_packet; + } + next = swfdec_rtmp_stream_sent (stream, packet); + if (next == NULL) { + swfdec_rtmp_packet_free (packet); + goto next_packet; } - } while (walk != conn->last_send); - return NULL; + swfdec_rtmp_header_write (&next->header, bots, + swfdec_rtmp_header_diff (&next->header, &packet->header)); + swfdec_rtmp_packet_free (packet); + packet = next; + packet->buffer->length = 0; + } else if (packet->buffer->length == 0) { + swfdec_rtmp_header_write (&packet->header, bots, SWFDEC_RTMP_HEADER_12_BYTES); + } else { + swfdec_rtmp_header_write (&packet->header, bots, SWFDEC_RTMP_HEADER_1_BYTE); + } + swfdec_bots_put_data (bots, packet->buffer->data + packet->buffer->length, + MIN (conn->write_size, packet->header.size - packet->buffer->length)); + packet->buffer->length += conn->write_size; + packet->buffer->length = MIN (packet->buffer->length, packet->header.size); + + g_queue_push_tail (conn->packets, packet); + return swfdec_bots_close (bots); } void diff --git a/swfdec/swfdec_rtmp_video_channel.c b/swfdec/swfdec_rtmp_video_channel.c deleted file mode 100644 index 1f8697f8..00000000 --- a/swfdec/swfdec_rtmp_video_channel.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "swfdec_rtmp_video_channel.h" - -#include "swfdec_debug.h" -#include "swfdec_rtmp_socket.h" -#include "swfdec_video_provider.h" - -/*** VIDEO PROVIDER INTERFACE ***/ - -static cairo_surface_t * -swfdec_rtmp_video_channel_get_image (SwfdecVideoProvider *prov, - SwfdecRenderer *renderer, guint *width, guint *height) -{ - return NULL; -} - -static void -swfdec_rtmp_video_channel_get_size (SwfdecVideoProvider *prov, guint *width, guint *height) -{ -} - -static void -swfdec_rtmp_video_channel_video_provider_init (SwfdecVideoProviderInterface *iface) -{ - iface->get_image = swfdec_rtmp_video_channel_get_image; - iface->get_size = swfdec_rtmp_video_channel_get_size; -} - -/*** SwfdecRtmpVideoChannel ***/ - -G_DEFINE_TYPE_WITH_CODE (SwfdecRtmpVideoChannel, swfdec_rtmp_video_channel, SWFDEC_TYPE_RTMP_CHANNEL, - G_IMPLEMENT_INTERFACE (SWFDEC_TYPE_VIDEO_PROVIDER, swfdec_rtmp_video_channel_video_provider_init)) - -static void -swfdec_rtmp_video_channel_receive (SwfdecRtmpChannel *channel, - const SwfdecRtmpHeader *header, SwfdecBuffer *buffer) -{ -} - -static SwfdecRtmpPacket * -swfdec_rtmp_video_channel_send (SwfdecRtmpChannel *channel) -{ - return NULL; -} - -static void -swfdec_rtmp_video_channel_dispose (GObject *object) -{ - //SwfdecRtmpVideoChannel *conn = SWFDEC_RTMP_VIDEO_CHANNEL (object); - - G_OBJECT_CLASS (swfdec_rtmp_video_channel_parent_class)->dispose (object); -} - -static void -swfdec_rtmp_video_channel_class_init (SwfdecRtmpVideoChannelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - SwfdecRtmpChannelClass *channel_class = SWFDEC_RTMP_CHANNEL_CLASS (klass); - - object_class->dispose = swfdec_rtmp_video_channel_dispose; - - channel_class->receive = swfdec_rtmp_video_channel_receive; - channel_class->send = swfdec_rtmp_video_channel_send; -} - -static void -swfdec_rtmp_video_channel_init (SwfdecRtmpVideoChannel *command) -{ -} - -SwfdecRtmpChannel * -swfdec_rtmp_video_channel_new (SwfdecRtmpConnection *conn) -{ - g_return_val_if_fail (SWFDEC_IS_RTMP_CONNECTION (conn), NULL); - - return g_object_new (SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, "connection", conn, NULL); -} diff --git a/swfdec/swfdec_rtmp_video_channel.h b/swfdec/swfdec_rtmp_video_channel.h deleted file mode 100644 index 49f0b15a..00000000 --- a/swfdec/swfdec_rtmp_video_channel.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Swfdec - * Copyright (C) 2008 Benjamin Otte <otte@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#ifndef _SWFDEC_RTMP_VIDEO_CHANNEL_H_ -#define _SWFDEC_RTMP_VIDEO_CHANNEL_H_ - -#include <swfdec/swfdec_rtmp_channel.h> - -G_BEGIN_DECLS - - -typedef struct _SwfdecRtmpVideoChannel SwfdecRtmpVideoChannel; -typedef struct _SwfdecRtmpVideoChannelClass SwfdecRtmpVideoChannelClass; - -#define SWFDEC_TYPE_RTMP_VIDEO_CHANNEL (swfdec_rtmp_video_channel_get_type()) -#define SWFDEC_IS_RTMP_VIDEO_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL)) -#define SWFDEC_IS_RTMP_VIDEO_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL)) -#define SWFDEC_RTMP_VIDEO_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannel)) -#define SWFDEC_RTMP_VIDEO_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannelClass)) -#define SWFDEC_RTMP_VIDEO_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_RTMP_VIDEO_CHANNEL, SwfdecRtmpVideoChannelClass)) - -struct _SwfdecRtmpVideoChannel { - SwfdecRtmpChannel channel; -}; - -struct _SwfdecRtmpVideoChannelClass { - SwfdecRtmpChannelClass channel_class; -}; - -GType swfdec_rtmp_video_channel_get_type (void); - -SwfdecRtmpChannel * swfdec_rtmp_video_channel_new (SwfdecRtmpConnection * conn); - - -G_END_DECLS -#endif |