]> git.sesse.net Git - vlc/blob - modules/access/rtmp/rtmp_amf_flv.c
playlist: Handle vlc_InputItemErrorWhenReadingChanged events.
[vlc] / modules / access / rtmp / rtmp_amf_flv.c
1 /*****************************************************************************
2  * rtmp_amf_flv.c: RTMP, AMF and FLV over RTMP implementation.
3  *****************************************************************************
4  * Copyright (C) URJC - LADyR - Luis Lopez Fernandez
5  *
6  * Author: Miguel Angel Cabrera Moya
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * RTMP header:
25  ******************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <vlc_common.h>
31 #include <vlc_access.h>
32
33 #include <vlc_network.h> /* DOWN: #include <network.h> */
34 #include <vlc_url.h>
35 #include <vlc_block.h>
36
37 #include <stdlib.h>
38 #include <stdint.h>
39 #include <string.h>
40
41 #include "rtmp_amf_flv.h"
42
43 /* header length (including itself) */
44 const uint8_t RTMP_HEADER_SIZE_MASK = 0xC0;
45 const uint8_t RTMP_HEADER_SIZE_12 = 0x00; 
46 const uint8_t RTMP_HEADER_SIZE_8 = 0x40;
47 const uint8_t RTMP_HEADER_SIZE_4 = 0x80;
48 const uint8_t RTMP_HEADER_SIZE_1 = 0xC0;
49
50 /* streams */
51 const uint8_t RTMP_HEADER_STREAM_MAX = 64;
52 const uint8_t RTMP_HEADER_STREAM_INDEX_MASK = 0x3F;
53
54 /* handshake */
55 const uint8_t RTMP_HANDSHAKE = 0x03;
56 const uint16_t RTMP_HANDSHAKE_BODY_SIZE = 1536;
57
58 /* content types */
59 const uint8_t RTMP_CONTENT_TYPE_CHUNK_SIZE = 0x01;
60 const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_02 = 0x02;
61 const uint8_t RTMP_CONTENT_TYPE_BYTES_READ = 0x03;
62 const uint8_t RTMP_CONTENT_TYPE_PING = 0x04;
63 const uint8_t RTMP_CONTENT_TYPE_SERVER_BW = 0x05;
64 const uint8_t RTMP_CONTENT_TYPE_CLIENT_BW = 0x06;
65 const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_07 = 0x07;
66 const uint8_t RTMP_CONTENT_TYPE_AUDIO_DATA = 0x08;
67 const uint8_t RTMP_CONTENT_TYPE_VIDEO_DATA = 0x09;
68 const uint8_t RTMP_CONTENT_TYPE_UNKNOWN_0A_0E = 0x0A;
69 const uint8_t RTMP_CONTENT_TYPE_FLEX_STREAM = 0x0F;
70 const uint8_t RTMP_CONTENT_TYPE_FLEX_SHARED_OBJECT = 0x10;
71 const uint8_t RTMP_CONTENT_TYPE_MESSAGE = 0x11;
72 const uint8_t RTMP_CONTENT_TYPE_NOTIFY = 0x12;
73 const uint8_t RTMP_CONTENT_TYPE_SHARED_OBJECT = 0x13;
74 const uint8_t RTMP_CONTENT_TYPE_INVOKE = 0x14;
75
76 /* shared object datatypes */
77 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_CONNECT = 0x01;
78 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DISCONNECT = 0x02;
79 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_SET_ATTRIBUTE = 0x03;
80 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_UPDATE_DATA = 0x04;
81 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_UPDATE_ATTRIBUTE = 0x05;
82 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_SEND_MESSAGE = 0x06;
83 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_STATUS = 0x07;
84 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_CLEAR_DATA = 0x08;
85 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DELETE_DATA = 0x09;
86 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_DELETE_ATTRIBUTE = 0x0A;
87 const uint8_t RTMP_SHARED_OBJECT_DATATYPE_INITIAL_DATA = 0x0B;
88
89 /* pings */
90 const uint16_t RTMP_PING_CLEAR_STREAM = 0x0000;
91 const uint16_t RTMP_PING_CLEAR_PLAYING_BUFFER = 0x0001;
92 const uint16_t RTMP_PING_BUFFER_TIME_CLIENT = 0x0003;
93 const uint16_t RTMP_PING_RESET_STREAM = 0x0004;
94 const uint16_t RTMP_PING_CLIENT_FROM_SERVER = 0x0006;
95 const uint16_t RTMP_PING_PONG_FROM_CLIENT = 0x0007;
96
97 /* pings sizes */
98 const uint8_t RTMP_PING_SIZE_CLEAR_STREAM = 6;
99 const uint8_t RTMP_PING_SIZE_CLEAR_PLAYING_BUFFER = 6;
100 const uint8_t RTMP_PING_SIZE_BUFFER_TIME_CLIENT = 10;
101 const uint8_t RTMP_PING_SIZE_RESET_STREAM = 6;
102 /*const uint8_t RTMP_PING_SIZE_CLIENT_FROM_SERVER = 0x0006; TODO
103 const uint8_t RTMP_PING_SIZE_PONG_FROM_CLIENT = 0x0007;
104 */
105
106 /* default values */
107 const uint8_t RTMP_DEFAULT_STREAM_INDEX_CONTROL = 0x02;
108 const uint8_t RTMP_DEFAULT_STREAM_INDEX_INVOKE = 0x03;
109 const uint8_t RTMP_DEFAULT_STREAM_INDEX_NOTIFY = 0x04;
110 const uint8_t RTMP_DEFAULT_STREAM_INDEX_VIDEO_DATA = 0x05;
111 const uint8_t RTMP_DEFAULT_STREAM_INDEX_AUDIO_DATA = 0x06;
112 const uint32_t RTMP_DEFAULT_CHUNK_SIZE = 128;
113 const double RTMP_DEFAULT_STREAM_CLIENT_ID = 1.0;
114 const double RTMP_DEFAULT_STREAM_SERVER_ID = 1.0;
115
116 /* misc */
117 const uint16_t MAX_EMPTY_BLOCKS = 200; /* empty blocks in fifo for media*/
118 const uint16_t RTMP_BODY_SIZE_ALLOC = 1024;
119 const uint32_t RTMP_TIME_CLIENT_BUFFER = 2000; /* miliseconds */
120 const uint32_t RTMP_SERVER_BW = 0x00000200;
121 const uint32_t RTMP_SRC_DST_CONNECT_OBJECT = 0x00000000;
122 const uint32_t RTMP_SRC_DST_CONNECT_OBJECT2 = 0x00000001;
123 const uint32_t RTMP_SRC_DST_DEFAULT = 0x01000000;
124 const uint64_t RTMP_AUDIOCODECS = 0x4083380000000000;
125 const uint64_t RTMP_VIDEOCODECS = 0x405f000000000000;
126 const uint64_t RTMP_VIDEOFUNCTION = 0x3ff0000000000000;
127 /*****************************************************************************
128  * AMF header:
129  ******************************************************************************/
130
131 /* boolean constants */
132 const uint8_t AMF_BOOLEAN_FALSE = 0x00;
133 const uint8_t AMF_BOOLEAN_TRUE = 0x01;
134
135 /* datatypes */
136 const uint8_t AMF_DATATYPE_NUMBER = 0x00;
137 const uint8_t AMF_DATATYPE_BOOLEAN = 0x01;
138 const uint8_t AMF_DATATYPE_STRING = 0x02;
139 const uint8_t AMF_DATATYPE_OBJECT = 0x03;
140 const uint8_t AMF_DATATYPE_MOVIE_CLIP = 0x04;
141 const uint8_t AMF_DATATYPE_NULL = 0x05;
142 const uint8_t AMF_DATATYPE_UNDEFINED = 0x06;
143 const uint8_t AMF_DATATYPE_REFERENCE = 0x07;
144 const uint8_t AMF_DATATYPE_MIXED_ARRAY = 0x08;
145 const uint8_t AMF_DATATYPE_END_OF_OBJECT = 0x09;
146 const uint8_t AMF_DATATYPE_ARRAY = 0x0A;
147 const uint8_t AMF_DATATYPE_DATE = 0x0B;
148 const uint8_t AMF_DATATYPE_LONG_STRING = 0x0C;
149 const uint8_t AMF_DATATYPE_UNSUPPORTED = 0x0D;
150 const uint8_t AMF_DATATYPE_RECORDSET = 0x0E;
151 const uint8_t AMF_DATATYPE_XML = 0x0F;
152 const uint8_t AMF_DATATYPE_TYPED_OBJECT = 0x10;
153 const uint8_t AMF_DATATYPE_AMF3_DATA = 0x11;
154
155 /* datatypes sizes */
156 const uint8_t AMF_DATATYPE_SIZE_NUMBER = 9;
157 const uint8_t AMF_DATATYPE_SIZE_BOOLEAN = 2;
158 const uint8_t AMF_DATATYPE_SIZE_STRING = 3;
159 const uint8_t AMF_DATATYPE_SIZE_OBJECT = 1;
160 const uint8_t AMF_DATATYPE_SIZE_NULL = 1;
161 const uint8_t AMF_DATATYPE_SIZE_OBJECT_VARIABLE = 2;
162 const uint8_t AMF_DATATYPE_SIZE_MIXED_ARRAY = 5;
163 const uint8_t AMF_DATATYPE_SIZE_END_OF_OBJECT = 3;
164
165 /* amf remote calls */
166 const uint64_t AMF_CALL_NETCONNECTION_CONNECT = 0x3FF0000000000000;
167 const uint64_t AMF_CALL_NETCONNECTION_CONNECT_AUDIOCODECS = 0x4083380000000000;
168 const uint64_t AMF_CALL_NETCONNECTION_CONNECT_VIDEOCODECS = 0x405F000000000000;
169 const uint64_t AMF_CALL_NETCONNECTION_CONNECT_VIDEOFUNCTION = 0x3FF0000000000000;
170 const uint64_t AMF_CALL_NETCONNECTION_CONNECT_OBJECTENCODING = 0x0;
171 const double AMF_CALL_STREAM_CLIENT_NUMBER = 3.0;
172 const double AMF_CALL_ONBWDONE = 2.0; 
173 const uint64_t AMF_CALL_NETSTREAM_PLAY = 0x0;
174
175 /*****************************************************************************
176  * FLV header:
177  ******************************************************************************/
178 const uint8_t FLV_HEADER_SIGNATURE[3] = { 0x46, 0x4C, 0x56 }; /* always "FLV" */
179 const uint8_t FLV_HEADER_VERSION = 0x01;
180 const uint8_t FLV_HEADER_AUDIO = 0x04;
181 const uint8_t FLV_HEADER_VIDEO = 0x01;
182 const uint32_t FLV_HEADER_SIZE = 0x00000009; /* always 9 for known FLV files */
183
184 const uint32_t FLV_TAG_FIRST_PREVIOUS_TAG_SIZE = 0x00000000;
185 const uint8_t FLV_TAG_PREVIOUS_TAG_SIZE = 4;
186 const uint8_t FLV_TAG_SIZE = 11;
187
188 /* audio stereo types */
189 const uint8_t FLV_AUDIO_STEREO_MASK = 0x01;
190 const uint8_t FLV_AUDIO_STEREO_MONO = 0x00;
191 const uint8_t FLV_AUDIO_STEREO_STEREO = 0x01;
192
193 /* audio size */
194 const uint8_t FLV_AUDIO_SIZE_MASK = 0x02;
195 const uint8_t FLV_AUDIO_SIZE_8_BIT = 0x00;
196 const uint8_t FLV_AUDIO_SIZE_16_BIT = 0x02;
197
198 /* audio rate */
199 const uint8_t FLV_AUDIO_RATE_MASK = 0x0C;
200 const uint8_t FLV_AUDIO_RATE_5_5_KHZ = 0x00;
201 const uint8_t FLV_AUDIO_RATE_11_KHZ = 0x04;
202 const uint8_t FLV_AUDIO_RATE_22_KHZ = 0x08;
203 const uint8_t FLV_AUDIO_RATE_44_KHZ = 0x0C;
204
205 /* audio codec types */
206 const uint8_t FLV_AUDIO_CODEC_ID_MASK = 0xF0;
207 const uint8_t FLV_AUDIO_CODEC_ID_UNCOMPRESSED = 0x00;
208 const uint8_t FLV_AUDIO_CODEC_ID_ADPCM = 0x10;
209 const uint8_t FLV_AUDIO_CODEC_ID_MP3 = 0x20;
210 const uint8_t FLV_AUDIO_CODEC_ID_NELLYMOSER_8KHZ_MONO = 0x50;
211 const uint8_t FLV_AUDIO_CODEC_ID_NELLYMOSER = 0x60;
212
213 /* video codec types */
214 const uint8_t FLV_VIDEO_CODEC_ID_MASK = 0x0F;
215 const uint8_t FLV_VIDEO_CODEC_ID_SORENSEN_H263 = 0x02;
216 const uint8_t FLV_VIDEO_CODEC_ID_SCREEN_VIDEO = 0x03;
217 const uint8_t FLV_VIDEO_CODEC_ID_ON2_VP6 = 0x04;
218 const uint8_t FLV_VIDEO_CODEC_ID_ON2_VP6_ALPHA = 0x05;
219 const uint8_t FLV_VIDEO_CODEC_ID_SCREEN_VIDEO_2 = 0x06;
220
221 /* video frame types */
222 const uint8_t FLV_VIDEO_FRAME_TYPE_MASK = 0xF0;
223 const uint8_t FLV_VIDEO_FRAME_TYPE_KEYFRAME = 0x10;
224 const uint8_t FLV_VIDEO_FRAME_TYPE_INTER_FRAME = 0x20;
225 const uint8_t FLV_VIDEO_FRAME_TYPE_DISPOSABLE_INTER_FRAME = 0x30;
226
227 /*****************************************************************************
228  * static RTMP functions:
229  ******************************************************************************/
230 static void rtmp_handler_null       ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
231 static void rtmp_handler_chunk_size ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
232 static void rtmp_handler_invoke     ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
233 static void rtmp_handler_audio_data ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
234 static void rtmp_handler_video_data ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
235 static void rtmp_handler_notify     ( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
236
237 static rtmp_packet_t *rtmp_new_packet( rtmp_control_thread_t *p_thread, uint8_t stream_index, uint32_t timestamp, uint8_t content_type, uint32_t src_dst, rtmp_body_t *body );
238 static block_t *rtmp_new_block( rtmp_control_thread_t *p_thread, uint8_t *buffer, int32_t length_buffer );
239
240 static rtmp_packet_t *rtmp_encode_onBWDone( rtmp_control_thread_t *p_thread, double number );
241 static rtmp_packet_t *rtmp_encode_server_bw( rtmp_control_thread_t *p_thread, uint32_t number );
242 static rtmp_packet_t *rtmp_encode_NetConnection_connect_result( rtmp_control_thread_t *p_thread, double number );
243 static rtmp_packet_t *rtmp_encode_createStream_result( rtmp_control_thread_t *p_thread, double stream_client, double stream_server );
244 static rtmp_packet_t *rtmp_encode_ping_reset_stream( rtmp_control_thread_t *p_thread );
245 static rtmp_packet_t *rtmp_encode_ping_clear_stream( rtmp_control_thread_t *p_thread, uint32_t src_dst );
246 static rtmp_packet_t *rtmp_encode_NetStream_play_reset_onStatus( rtmp_control_thread_t *p_thread, char *psz_media );
247 static rtmp_packet_t *rtmp_encode_NetStream_play_start_onStatus( rtmp_control_thread_t *p_thread, char *psz_media );
248 static uint8_t rtmp_encode_header_size( vlc_object_t *p_this, uint8_t header_size );
249 static uint8_t rtmp_decode_header_size( vlc_object_t *p_this, uint8_t header_size );
250 static uint8_t rtmp_get_stream_index( uint8_t content_type );
251
252 static void rtmp_body_append( rtmp_body_t *rtmp_body, uint8_t *buffer, uint32_t length );
253
254 static uint8_t *rtmp_encode_ping( uint16_t type, uint32_t src_dst, uint32_t third_arg, uint32_t fourth_arg );
255
256 /*****************************************************************************
257  * static AMF functions:
258  ******************************************************************************/
259 static uint8_t *amf_encode_element( uint8_t element, const void *value );
260 static uint8_t *amf_encode_object_variable( const char *key, uint8_t element, const void *value );
261 static double amf_decode_number( uint8_t **buffer );
262 static int amf_decode_boolean( uint8_t **buffer );
263 static char *amf_decode_string( uint8_t **buffer );
264 static char *amf_decode_object( uint8_t **buffer );
265
266 /*****************************************************************************
267  * static FLV functions:
268  ******************************************************************************/
269 static void flv_rebuild( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet );
270 static void flv_get_metadata_audio( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_audio, uint8_t *stereo, uint8_t *audiosamplesize, uint32_t *audiosamplerate, uint8_t *audiocodecid );
271 static void flv_get_metadata_video( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_video, uint8_t *videocodecid, uint8_t *frametype );
272 static rtmp_packet_t *flv_build_onMetaData( access_t *p_access, uint64_t duration, uint8_t stereo, uint8_t audiosamplesize, uint32_t audiosamplerate, uint8_t audiocodecid, uint8_t videocodecid );
273
274 /*****************************************************************************
275  * RTMP implementation:
276  ******************************************************************************/
277 int
278 rtmp_handshake_passive( vlc_object_t *p_this, int fd )
279 {
280     uint8_t p_read[RTMP_HANDSHAKE_BODY_SIZE + 1];
281     uint8_t p_write[RTMP_HANDSHAKE_BODY_SIZE * 2 + 1];
282     ssize_t i_ret;
283     int i;
284
285     /* Receive handshake */
286     i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE + 1, true );
287     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE + 1 )
288     {
289         msg_Err( p_this, "failed to receive handshake" );
290         return -1;
291     }
292
293     /* Check handshake */
294     if ( p_read[0] != RTMP_HANDSHAKE )
295     {
296         msg_Err( p_this, "first byte in handshake corrupt" );
297         return -1;
298     }
299
300     /* Answer handshake */
301     p_write[0] = RTMP_HANDSHAKE;
302     memset( p_write + 1, 0, RTMP_HANDSHAKE_BODY_SIZE );
303     memcpy( p_write + 1 + RTMP_HANDSHAKE_BODY_SIZE, p_read + 1, RTMP_HANDSHAKE_BODY_SIZE );
304
305     /* Send handshake*/
306     i_ret = net_Write( p_this, fd, NULL, p_write, RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 );
307     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 )
308     {
309         msg_Err( p_this, "failed to send handshake" );
310         return -1;
311     }
312
313     /* Receive acknowledge */
314     i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE, true );
315     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE )
316     {
317         msg_Err( p_this, "failed to receive acknowledge" );
318         return -1;
319     }
320
321     /* Check acknowledge */
322     for(i = 8; i < RTMP_HANDSHAKE_BODY_SIZE; i++ )
323         if( p_write[i + 1] != p_read[i] )
324         {
325             msg_Err( p_this, "body acknowledge received corrupt" );
326             return -1;
327         }
328
329     return 0;
330 }
331
332 int
333 rtmp_handshake_active( vlc_object_t *p_this, int fd )
334 {
335     uint8_t p_read[RTMP_HANDSHAKE_BODY_SIZE * 2 + 1];
336     uint8_t p_write[RTMP_HANDSHAKE_BODY_SIZE + 1];
337     ssize_t i_ret;
338     int i;
339
340     p_write[0] = RTMP_HANDSHAKE;
341     for( i = 0; i < RTMP_HANDSHAKE_BODY_SIZE; i++ )
342         p_write[i + 1] = i & 0xFF;
343
344     /* Send handshake*/
345     i_ret = net_Write( p_this, fd, NULL, p_write, RTMP_HANDSHAKE_BODY_SIZE + 1 );
346     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE + 1 )
347     {
348         msg_Err( p_this, "failed to send handshake" );
349         return -1;
350     }
351
352     /* Receive handshake */
353     i_ret = net_Read( p_this, fd, NULL, p_read, RTMP_HANDSHAKE_BODY_SIZE * 2 + 1, true );
354     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE * 2 + 1 )
355     {
356         msg_Err( p_this, "failed to receive handshake" );
357         return -1;
358     }
359
360     /* Check handshake */
361     if( p_read[0] != RTMP_HANDSHAKE )
362     {
363         msg_Err( p_this, "first byte in handshake received corrupt" );
364         return -1;
365     }
366
367     for(i = 8; i < RTMP_HANDSHAKE_BODY_SIZE; i++ )
368         if( p_write[i + 1] != p_read[i + 1 + RTMP_HANDSHAKE_BODY_SIZE] )
369         {
370             msg_Err( p_this, "body handshake received corrupt" );
371             return -1;
372         }
373
374     /* Acknowledge handshake */
375     i_ret = net_Write( p_this, fd, NULL, p_read + 1, RTMP_HANDSHAKE_BODY_SIZE );
376     if( i_ret != RTMP_HANDSHAKE_BODY_SIZE )
377     {
378         msg_Err( p_this, "failed to acknowledge handshake" );
379         return -1;
380     }
381
382     return 0;
383 }
384
385 int
386 rtmp_connect_active( rtmp_control_thread_t *p_thread )
387 {
388     rtmp_packet_t *rtmp_packet;
389     rtmp_body_t *rtmp_body;
390     uint8_t *tmp_buffer;
391     char *tmp_url;
392     ssize_t i_ret;
393
394     /* Build NetConnection.connect call */
395     rtmp_body = rtmp_body_new( -1 );
396
397     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "connect" );
398     rtmp_body_append( rtmp_body, tmp_buffer, 
399         AMF_DATATYPE_SIZE_STRING + strlen( "connect" ) );
400     free( tmp_buffer );
401
402     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
403         &AMF_CALL_NETCONNECTION_CONNECT );
404     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
405     free( tmp_buffer );
406
407     tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL );
408     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT );
409     free( tmp_buffer );
410
411     tmp_buffer = amf_encode_object_variable( "app",
412         AMF_DATATYPE_STRING, p_thread->psz_application );
413     rtmp_body_append( rtmp_body, tmp_buffer,
414         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "app" ) + 
415         AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_application ) );
416     free( tmp_buffer );
417
418     tmp_buffer = amf_encode_object_variable( "flashVer",
419         AMF_DATATYPE_STRING, "LNX 9,0,48,0" );
420     rtmp_body_append( rtmp_body, tmp_buffer,
421         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "flashVer" ) +
422         AMF_DATATYPE_SIZE_STRING + strlen( "LNX 9,0,48,0" ) );
423     free( tmp_buffer );
424
425     tmp_buffer = amf_encode_object_variable( "swfUrl",
426          AMF_DATATYPE_STRING, "file:///mac.flv" );
427     rtmp_body_append( rtmp_body, tmp_buffer,
428         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "swfUrl" ) +
429         AMF_DATATYPE_SIZE_STRING + strlen( "file:///mac.flv" ) );
430     free( tmp_buffer );
431
432     tmp_url = (char *) malloc( strlen( "rtmp://") + strlen( p_thread->url.psz_buffer ) + 1 );
433     if( !tmp_url )
434     {
435         free( rtmp_body->body );
436         free( rtmp_body );
437         return -1;
438     }
439     sprintf( tmp_url, "rtmp://%s", p_thread->url.psz_buffer );
440     tmp_buffer = amf_encode_object_variable( "tcUrl",
441         AMF_DATATYPE_STRING, tmp_url );
442     rtmp_body_append( rtmp_body, tmp_buffer,
443         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "tcUrl" ) +
444         AMF_DATATYPE_SIZE_STRING + strlen( tmp_url ) );
445     free( tmp_url );
446     free( tmp_buffer );
447
448     tmp_buffer = amf_encode_object_variable( "fpad",
449         AMF_DATATYPE_BOOLEAN, &AMF_BOOLEAN_FALSE );
450     rtmp_body_append( rtmp_body, tmp_buffer,
451         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "fpad" ) +
452         AMF_DATATYPE_SIZE_BOOLEAN );
453     free( tmp_buffer );
454
455     tmp_buffer = amf_encode_object_variable( "audioCodecs",
456         AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_AUDIOCODECS );
457     rtmp_body_append( rtmp_body, tmp_buffer,
458         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "audioCodecs" ) +
459         AMF_DATATYPE_SIZE_NUMBER );
460     free( tmp_buffer );
461
462     tmp_buffer = amf_encode_object_variable( "videoCodecs",
463         AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_VIDEOCODECS );
464     rtmp_body_append( rtmp_body, tmp_buffer,
465         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "videoCodecs" ) +
466         AMF_DATATYPE_SIZE_NUMBER );
467     free( tmp_buffer );
468
469     tmp_buffer = amf_encode_object_variable( "videoFunction",
470         AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_VIDEOFUNCTION );
471     rtmp_body_append( rtmp_body, tmp_buffer,
472         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "videoFunction" ) +
473         AMF_DATATYPE_SIZE_NUMBER );
474     free( tmp_buffer );
475
476     tmp_buffer = amf_encode_object_variable( "pageUrl",
477         AMF_DATATYPE_STRING, "file:///mac.html" );
478     rtmp_body_append( rtmp_body, tmp_buffer,
479         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "pageUrl" ) +
480         AMF_DATATYPE_SIZE_STRING + strlen( "file:///mac.html" ) );
481     free( tmp_buffer );
482
483     tmp_buffer = amf_encode_object_variable( "objectEncoding",
484         AMF_DATATYPE_NUMBER, &AMF_CALL_NETCONNECTION_CONNECT_OBJECTENCODING );
485     rtmp_body_append( rtmp_body, tmp_buffer,
486         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "objectEncoding" ) +
487         AMF_DATATYPE_SIZE_NUMBER );
488     free( tmp_buffer );
489
490     tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL );
491     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
492     free( tmp_buffer );
493
494     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
495         0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body );
496     free( rtmp_body->body );
497     free( rtmp_body );
498
499     tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet );
500
501     /* Call NetConnection.connect */
502     i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
503     if( i_ret != rtmp_packet->length_encoded )
504     {
505         free( rtmp_packet->body->body );
506         free( rtmp_packet->body );
507         free( rtmp_packet );
508         free( tmp_buffer );
509         msg_Err( p_thread, "failed send call NetConnection.connect" );
510         return -1;
511     }
512     free( rtmp_packet->body->body );
513     free( rtmp_packet->body );
514     free( rtmp_packet );
515     free( tmp_buffer );
516
517     /* Wait for NetConnection.connect result */
518     vlc_mutex_lock( &p_thread->lock );
519     vlc_cond_wait( &p_thread->wait, &p_thread->lock );
520     vlc_mutex_unlock( &p_thread->lock );
521
522     if( p_thread->result_connect )
523     {
524         msg_Err( p_thread, "failed call NetConnection.connect" );
525         return -1;
526     }
527
528     /* Force control thread to stop if receive NetStream.play call and wait is not ready */
529     vlc_mutex_lock( &p_thread->lock );
530
531     /* Build NetStream.createStream call */
532     rtmp_body = rtmp_body_new( -1 );
533
534     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "createStream" );
535     rtmp_body_append( rtmp_body, tmp_buffer, 
536         AMF_DATATYPE_SIZE_STRING + strlen( "createStream" ) );
537     free( tmp_buffer );
538
539     p_thread->stream_client_id = RTMP_DEFAULT_STREAM_CLIENT_ID;
540
541     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
542         &AMF_CALL_STREAM_CLIENT_NUMBER );
543     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
544     free( tmp_buffer );
545
546     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
547     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
548     free( tmp_buffer );
549
550     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE, 
551         0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body );
552     free( rtmp_body->body );
553     free( rtmp_body );
554
555     tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet );
556
557     /* Call NetStream.createStream */
558     i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
559     if( i_ret != rtmp_packet->length_encoded )
560     {
561         free( rtmp_packet->body->body );
562         free( rtmp_packet->body );
563         free( rtmp_packet );
564         free( tmp_buffer );
565         msg_Err( p_thread, "failed send call NetStream.createStream" );
566         return -1;
567     }
568     free( rtmp_packet->body->body );
569     free( rtmp_packet->body );
570     free( rtmp_packet );
571     free( tmp_buffer );
572 /*TODO: read server stream number*/
573     /* Build ping packet */
574     rtmp_body = rtmp_body_new( -1 );
575
576     tmp_buffer = rtmp_encode_ping( RTMP_PING_BUFFER_TIME_CLIENT, RTMP_SRC_DST_CONNECT_OBJECT, RTMP_TIME_CLIENT_BUFFER, 0 );
577     rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_BUFFER_TIME_CLIENT );
578     free( tmp_buffer );
579
580     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
581         0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body );
582     free( rtmp_body->body );
583     free( rtmp_body );
584
585     tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet );
586
587     /* Send ping packet */
588     i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
589     if( i_ret != rtmp_packet->length_encoded )
590     {
591         free( rtmp_packet->body->body );
592         free( rtmp_packet->body );
593         free( rtmp_packet );
594         free( tmp_buffer );
595         msg_Err( p_thread, "failed send ping BUFFER_TIME_CLIENT" );
596         return -1;
597     }
598     free( rtmp_packet->body->body );
599     free( rtmp_packet->body );
600     free( rtmp_packet );
601     free( tmp_buffer );
602
603     /* Build NetStream.play call */
604     rtmp_body = rtmp_body_new( -1 );
605
606     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "play" );
607     rtmp_body_append( rtmp_body, tmp_buffer,
608         AMF_DATATYPE_SIZE_STRING + strlen( "play" ) );
609     free( tmp_buffer );
610
611     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
612         &AMF_CALL_NETSTREAM_PLAY );
613     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
614     free( tmp_buffer );
615
616     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
617     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
618     free( tmp_buffer );
619
620     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, p_thread->psz_media );
621     rtmp_body_append( rtmp_body, tmp_buffer,
622         AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_media ) );
623     free( tmp_buffer );
624
625     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
626         0, RTMP_CONTENT_TYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body );
627     free( rtmp_body->body );
628     free( rtmp_body );
629
630     tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet );
631
632     /* Call NetStream.play */
633     i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
634     if( i_ret != rtmp_packet->length_encoded )
635     {
636         free( rtmp_packet->body->body );
637         free( rtmp_packet->body );
638         free( rtmp_packet );
639         free( tmp_buffer );
640         msg_Err( p_thread, "failed send call NetStream.play" );
641         return -1;
642     }
643     free( rtmp_packet->body->body );
644     free( rtmp_packet->body );
645     free( rtmp_packet );
646     free( tmp_buffer );
647
648     /* Build ping packet */
649     rtmp_body = rtmp_body_new( -1 );
650
651     tmp_buffer = rtmp_encode_ping( RTMP_PING_BUFFER_TIME_CLIENT, RTMP_SRC_DST_CONNECT_OBJECT2, RTMP_TIME_CLIENT_BUFFER, 0 );
652     rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_BUFFER_TIME_CLIENT );
653     free( tmp_buffer );
654
655     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
656         0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body );
657     free( rtmp_body->body );
658     free( rtmp_body );
659
660     tmp_buffer = rtmp_encode_packet( p_thread, rtmp_packet );
661
662     /* Send ping packet */
663     i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
664     if( i_ret != rtmp_packet->length_encoded )
665     {
666         free( rtmp_packet->body->body );
667         free( rtmp_packet->body );
668         free( rtmp_packet );
669         free( tmp_buffer );
670         msg_Err( p_thread, "failed send ping BUFFER_TIME_CLIENT" );
671         return -1;
672     }
673     free( rtmp_packet->body->body );
674     free( rtmp_packet->body );
675     free( rtmp_packet );
676     free( tmp_buffer );
677
678     /* Wait for NetStream.play.start result */
679     vlc_cond_wait( &p_thread->wait, &p_thread->lock );
680     vlc_mutex_unlock( &p_thread->lock );
681
682     if( p_thread->result_play )
683     {
684         msg_Err( p_thread, "failed call NetStream.play" );
685         return -1;
686     }
687
688     /* Next packet is the beginning of flv stream */
689     msg_Dbg( p_thread, "next packet is the beginning of flv stream" );
690
691     return 0;
692 }
693
694 int
695 rtmp_connect_passive( rtmp_control_thread_t *p_thread )
696 {
697     /* Force control thread to stop if receive NetStream.play call and wait is not ready */
698     vlc_mutex_lock( &p_thread->lock );
699
700     /* Wait for NetStream.play.start result */
701     vlc_cond_wait( &p_thread->wait, &p_thread->lock );
702     vlc_mutex_unlock( &p_thread->lock );
703
704     if( p_thread->result_play )
705     {
706         msg_Err( p_thread, "failed call NetStream.play" );
707         return -1;
708     }
709
710     return 0;
711 }
712
713 /* TODO
714 int
715 rtmp_seek( access_t *p_access, int64_t i_pos )
716 {
717     access_sys_t *p_sys = p_access->p_sys;
718     rtmp_packet_t *rtmp_packet;
719     rtmp_body_t *rtmp_body;
720     uint8_t *tmp_buffer;
721     uint64_t tmp_number;
722     ssize_t i_ret;
723 msg_Warn(p_access, "i_pos %lld", i_pos);
724     // Build NetStream.seek call //
725     rtmp_body = rtmp_body_new();
726
727     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "seek" );
728     rtmp_body_append( rtmp_body, tmp_buffer,
729         AMF_DATATYPE_SIZE_STRING + strlen( "seek" ) );
730     free( tmp_buffer );
731
732     tmp_number = 0;
733     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
734         &tmp_number );
735     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
736     free( tmp_buffer );
737
738     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
739     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
740     free( tmp_buffer );
741 //TODO: convert i_pos to double and see if they are milliseconds
742     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
743         &i_pos );
744     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
745     free( tmp_buffer );
746
747     rtmp_packet = rtmp_new_packet( p_sys->p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
748         0, RTMP_DATATYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body );
749     free( rtmp_body->body );
750     free( rtmp_body );
751
752     tmp_buffer = rtmp_encode_packet( p_access, rtmp_packet ); 
753
754     // Call NetStream.seek //
755     i_ret = net_Write( p_access, p_sys->fd, NULL, tmp_buffer, rtmp_packet->length_encoded );
756     if( i_ret < rtmp_packet->length_encoded )
757     {
758         free( rtmp_packet->body->body );
759         free( rtmp_packet->body );
760         free( rtmp_packet );
761         free( tmp_buffer );
762         msg_Err( p_access, "failed call NetStream.seek" );
763         return -1;
764     }
765     free( rtmp_packet->body->body );
766     free( rtmp_packet->body );
767     free( rtmp_packet );
768     free( tmp_buffer );
769
770     // Receive TODO: see what //
771     rtmp_packet = rtmp_read_net_packet( p_access, p_sys->fd );
772     free( rtmp_packet->body->body );
773     free( rtmp_packet->body );
774     free( rtmp_packet );
775
776     return 0;
777 }
778 */
779
780 rtmp_packet_t *
781 rtmp_build_bytes_read( rtmp_control_thread_t *p_thread, uint32_t reply )
782 {
783     rtmp_packet_t *rtmp_packet;
784     rtmp_body_t *rtmp_body;
785     uint8_t *tmp_buffer;
786
787     /* Build bytes read packet */
788     rtmp_body = rtmp_body_new( -1 );
789
790     tmp_buffer = (uint8_t *) malloc( sizeof( uint32_t ) * sizeof( uint8_t ) );
791     if( !tmp_buffer ) return NULL;
792
793     reply = hton32( reply );
794     memcpy( tmp_buffer, &reply, sizeof( uint32_t ) );
795
796     rtmp_body_append( rtmp_body, tmp_buffer, sizeof( uint32_t ) );
797     free( tmp_buffer );
798
799     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
800         0, RTMP_CONTENT_TYPE_BYTES_READ, 0, rtmp_body );
801     free( rtmp_body->body );
802     free( rtmp_body );
803
804     return rtmp_packet;
805 }
806
807 rtmp_packet_t *
808 rtmp_build_publish_start( rtmp_control_thread_t *p_thread )
809 {
810     rtmp_packet_t *rtmp_packet;
811     rtmp_body_t *rtmp_body;
812     uint8_t *tmp_buffer;
813
814     /* Build publish start event */
815     rtmp_body = rtmp_body_new( -1 );
816
817     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onStatus" );
818     rtmp_body_append( rtmp_body, tmp_buffer,
819         AMF_DATATYPE_SIZE_STRING + strlen( "onStatus" ) );
820     free( tmp_buffer );
821
822     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER,
823         &p_thread->stream_server_id );
824     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
825     free( tmp_buffer );
826
827     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
828     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
829     free( tmp_buffer );
830
831     tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL );
832     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT );
833     free( tmp_buffer );
834
835     tmp_buffer = amf_encode_object_variable( "level",
836         AMF_DATATYPE_STRING, "status" );
837     rtmp_body_append( rtmp_body, tmp_buffer,
838         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "level" ) +
839         AMF_DATATYPE_SIZE_STRING + strlen( "status" ) );
840     free ( tmp_buffer );
841
842     tmp_buffer = amf_encode_object_variable( "code",
843         AMF_DATATYPE_STRING, "NetStream.Publish.Start" );
844     rtmp_body_append( rtmp_body, tmp_buffer,
845         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "code" ) +
846         AMF_DATATYPE_SIZE_STRING + strlen( "NetStream.Publish.Start" ) );
847     free ( tmp_buffer );
848
849     tmp_buffer = amf_encode_object_variable( "description",
850         AMF_DATATYPE_STRING, "" );
851     rtmp_body_append( rtmp_body, tmp_buffer,
852         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "description" ) +
853         AMF_DATATYPE_SIZE_STRING + strlen( "" ) );
854     free ( tmp_buffer );
855
856     tmp_buffer = amf_encode_object_variable( "details",
857         AMF_DATATYPE_STRING, p_thread->psz_publish );
858     rtmp_body_append( rtmp_body, tmp_buffer,
859         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "details" ) +
860         AMF_DATATYPE_SIZE_STRING + strlen( p_thread->psz_publish ) );
861     free ( tmp_buffer );
862
863     tmp_buffer = amf_encode_object_variable( "clientid",
864         AMF_DATATYPE_NUMBER, &p_thread->stream_client_id );
865     rtmp_body_append( rtmp_body, tmp_buffer,
866         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "clientid" ) +
867         AMF_DATATYPE_SIZE_NUMBER );
868     free( tmp_buffer );
869
870     tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL );
871     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
872     free( tmp_buffer );
873
874     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
875         0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body );
876     free( rtmp_body->body );
877     free( rtmp_body );
878
879     return rtmp_packet;
880 }
881
882 rtmp_packet_t *
883 rtmp_build_flv_over_rtmp( rtmp_control_thread_t *p_thread, block_t *p_buffer )
884 {
885     rtmp_packet_t *rtmp_packet;
886
887     if( p_thread->flv_length_body > 0 )
888     {
889         p_thread->flv_length_body -= p_buffer->i_buffer;
890         rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer, p_buffer->i_buffer );
891
892         if( p_thread->flv_length_body > 0 )
893             return NULL;
894
895     }
896     else
897     {
898         p_thread->flv_content_type = *p_buffer->p_buffer;
899
900         p_buffer->p_buffer[0] = 0;
901         p_thread->flv_length_body = ntoh32( *(uint32_t *) (p_buffer->p_buffer) );
902
903         p_buffer->p_buffer[3] = 0;
904         p_thread->flv_timestamp = ntoh32( *(uint32_t *) (p_buffer->p_buffer + 3) );
905     }
906
907     if( p_thread->flv_length_body > p_buffer->i_buffer - FLV_TAG_SIZE - FLV_TAG_PREVIOUS_TAG_SIZE )
908     {
909         p_thread->flv_length_body -= p_buffer->i_buffer - FLV_TAG_SIZE - FLV_TAG_PREVIOUS_TAG_SIZE;
910         rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer + FLV_TAG_SIZE, p_buffer->i_buffer - FLV_TAG_SIZE );
911
912         return NULL;
913     }
914     else
915     {
916         rtmp_body_append( p_thread->flv_body, p_buffer->p_buffer + FLV_TAG_SIZE, p_thread->flv_length_body );
917     }
918
919     rtmp_packet = rtmp_new_packet( p_thread, rtmp_get_stream_index( p_thread->flv_content_type ),
920         p_thread->flv_timestamp, p_thread->flv_content_type, RTMP_SRC_DST_DEFAULT, p_thread->flv_body );
921     p_thread->flv_length_body = 0;
922     rtmp_body_reset( p_thread->flv_body );
923
924     return rtmp_packet;
925 }
926
927 rtmp_packet_t *
928 rtmp_read_net_packet( rtmp_control_thread_t *p_thread )
929 {
930     int length_header;
931     int stream_index;
932     int bytes_left;
933     uint8_t p_read[12];
934     rtmp_packet_t *rtmp_packet;
935     ssize_t i_ret;
936
937
938     for(;;)
939     {
940         i_ret = net_Read( p_thread, p_thread->fd, NULL, p_read, 1, true );
941         if( i_ret != 1 )
942             goto error;
943
944         length_header = rtmp_decode_header_size( (vlc_object_t *) p_thread, p_read[0] & RTMP_HEADER_SIZE_MASK );
945         stream_index = p_read[0] & RTMP_HEADER_STREAM_INDEX_MASK;
946
947         i_ret = net_Read( p_thread, p_thread->fd, NULL, p_read + 1, length_header - 1, true );
948         if( i_ret != length_header - 1 )
949             goto error;
950
951         /* Update timestamp if not is an interchunk packet */
952         if( length_header == 1 && p_thread->rtmp_headers_recv[stream_index].body == NULL )
953         {
954             p_thread->rtmp_headers_recv[stream_index].timestamp +=
955                 p_thread->rtmp_headers_recv[stream_index].timestamp_relative;
956         }
957
958         /* Length 4 and 8 headers have relative timestamp */
959         if( length_header == 4 || length_header == 8 )
960         {
961             p_read[0] = 0;
962
963             p_thread->rtmp_headers_recv[stream_index].timestamp_relative = ntoh32( *(uint32_t *) p_read );
964             p_thread->rtmp_headers_recv[stream_index].timestamp +=
965                 p_thread->rtmp_headers_recv[stream_index].timestamp_relative;
966         }
967
968         if( length_header >= 8 )
969         {
970             p_read[3] = 0;
971
972             p_thread->rtmp_headers_recv[stream_index].length_body = ntoh32( *(uint32_t *) (p_read + 3) );
973             p_thread->rtmp_headers_recv[stream_index].content_type = p_read[7];
974         }
975
976         /* Length 12 headers have absolute timestamp */
977         if( length_header >= 12 )
978         {
979             p_read[0] = 0;
980
981             p_thread->rtmp_headers_recv[stream_index].timestamp = ntoh32( *(uint32_t *) p_read );
982             p_thread->rtmp_headers_recv[stream_index].src_dst = ntoh32( *(uint32_t *) (p_read + 8) );
983         }
984
985         if( p_thread->rtmp_headers_recv[stream_index].body == NULL )
986         {
987             p_thread->rtmp_headers_recv[stream_index].body =
988                 rtmp_body_new( p_thread->rtmp_headers_recv[stream_index].length_body );
989         }
990
991         bytes_left = p_thread->rtmp_headers_recv[stream_index].body->length_buffer -
992             p_thread->rtmp_headers_recv[stream_index].body->length_body;
993
994         if( bytes_left > p_thread->chunk_size_recv )
995             bytes_left = p_thread->chunk_size_recv;
996
997         i_ret = net_Read( p_thread, p_thread->fd, NULL,
998             p_thread->rtmp_headers_recv[stream_index].body->body +
999             p_thread->rtmp_headers_recv[stream_index].body->length_body,
1000             bytes_left, true );
1001         if( i_ret != bytes_left )
1002             goto error;
1003
1004         p_thread->rtmp_headers_recv[stream_index].body->length_body += bytes_left;
1005
1006         if( p_thread->rtmp_headers_recv[stream_index].length_body == p_thread->rtmp_headers_recv[stream_index].body->length_body )
1007         {
1008             rtmp_packet = (rtmp_packet_t *) malloc( sizeof( rtmp_packet_t ) );
1009             if( !rtmp_packet ) goto error;
1010
1011             rtmp_packet->stream_index = stream_index;
1012             rtmp_packet->timestamp = p_thread->rtmp_headers_recv[stream_index].timestamp;
1013             rtmp_packet->timestamp_relative = p_thread->rtmp_headers_recv[stream_index].timestamp_relative;
1014             rtmp_packet->content_type = p_thread->rtmp_headers_recv[stream_index].content_type;
1015             rtmp_packet->src_dst = p_thread->rtmp_headers_recv[stream_index].src_dst;
1016             rtmp_packet->length_body = p_thread->rtmp_headers_recv[stream_index].length_body;
1017             rtmp_packet->body = p_thread->rtmp_headers_recv[stream_index].body;
1018
1019             p_thread->rtmp_headers_recv[stream_index].body = NULL;
1020
1021             return rtmp_packet;
1022         }
1023     }
1024
1025 error:
1026     msg_Err( p_thread, "rtmp_read_net_packet: net_Read error");
1027     return NULL;
1028 }
1029
1030 void
1031 rtmp_init_handler( rtmp_handler_t *rtmp_handler )
1032 {
1033     rtmp_handler[RTMP_CONTENT_TYPE_CHUNK_SIZE] = rtmp_handler_chunk_size;
1034     rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_02] = rtmp_handler_null;
1035     rtmp_handler[RTMP_CONTENT_TYPE_BYTES_READ] = rtmp_handler_null;
1036     rtmp_handler[RTMP_CONTENT_TYPE_PING] = rtmp_handler_null;
1037     rtmp_handler[RTMP_CONTENT_TYPE_SERVER_BW] = rtmp_handler_null;
1038     rtmp_handler[RTMP_CONTENT_TYPE_CLIENT_BW] = rtmp_handler_null;
1039     rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_07] = rtmp_handler_null;
1040     rtmp_handler[RTMP_CONTENT_TYPE_AUDIO_DATA] = rtmp_handler_audio_data;
1041     rtmp_handler[RTMP_CONTENT_TYPE_VIDEO_DATA] = rtmp_handler_video_data;
1042     rtmp_handler[RTMP_CONTENT_TYPE_UNKNOWN_0A_0E] = rtmp_handler_null;
1043     rtmp_handler[RTMP_CONTENT_TYPE_FLEX_STREAM] = rtmp_handler_null;
1044     rtmp_handler[RTMP_CONTENT_TYPE_FLEX_SHARED_OBJECT] = rtmp_handler_null;
1045     rtmp_handler[RTMP_CONTENT_TYPE_MESSAGE] = rtmp_handler_null;
1046     rtmp_handler[RTMP_CONTENT_TYPE_NOTIFY] = rtmp_handler_notify;
1047     rtmp_handler[RTMP_CONTENT_TYPE_SHARED_OBJECT] = rtmp_handler_null;
1048     rtmp_handler[RTMP_CONTENT_TYPE_INVOKE] = rtmp_handler_invoke;
1049 }
1050
1051 static void
1052 rtmp_handler_null( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1053 {
1054     VLC_UNUSED(p_thread);
1055     free( rtmp_packet->body->body );
1056     free( rtmp_packet->body );
1057     free( rtmp_packet );
1058 }
1059
1060 static void
1061 rtmp_handler_chunk_size( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1062 {
1063     p_thread->chunk_size_recv = ntoh32( *(uint32_t *) (rtmp_packet->body->body) );
1064
1065     free( rtmp_packet->body->body );
1066     free( rtmp_packet->body );
1067     free( rtmp_packet );
1068 }
1069
1070 static void
1071 rtmp_handler_audio_data( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1072 {
1073     block_t *p_buffer;
1074
1075     if( !p_thread->has_audio )
1076     {
1077         p_thread->has_audio = 1;
1078
1079         flv_get_metadata_audio( p_thread, rtmp_packet,
1080             &p_thread->metadata_stereo, &p_thread->metadata_samplesize,
1081             &p_thread->metadata_samplerate, &p_thread->metadata_audiocodecid );
1082     }
1083
1084     flv_rebuild( p_thread, rtmp_packet );
1085     p_buffer = rtmp_new_block( p_thread, rtmp_packet->body->body, rtmp_packet->body->length_body );
1086     block_FifoPut( p_thread->p_fifo_input, p_buffer );
1087
1088     free( rtmp_packet->body->body );
1089     free( rtmp_packet->body );
1090     free( rtmp_packet );
1091 }
1092
1093 static void
1094 rtmp_handler_video_data( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1095 {
1096     block_t *p_buffer;
1097
1098     if( !p_thread->has_video )
1099     {
1100         p_thread->has_video = 1;
1101
1102         flv_get_metadata_video( p_thread, rtmp_packet,
1103             &p_thread->metadata_videocodecid, &p_thread->metadata_frametype );
1104     }
1105
1106     flv_rebuild( p_thread, rtmp_packet );
1107     p_buffer = rtmp_new_block( p_thread, rtmp_packet->body->body, rtmp_packet->body->length_body );
1108     block_FifoPut( p_thread->p_fifo_input, p_buffer );
1109
1110     free( rtmp_packet->body->body );
1111     free( rtmp_packet->body );
1112     free( rtmp_packet );
1113 }
1114
1115 static void
1116 rtmp_handler_notify( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1117 {
1118     block_t *p_buffer;
1119
1120     p_thread->metadata_received = 1;
1121
1122     flv_rebuild( p_thread, rtmp_packet );
1123     p_buffer = rtmp_new_block( p_thread, rtmp_packet->body->body, rtmp_packet->body->length_body );
1124     block_FifoPut( p_thread->p_fifo_input, p_buffer );
1125
1126     free( rtmp_packet->body->body );
1127     free( rtmp_packet->body );
1128     free( rtmp_packet );
1129 }
1130
1131 static void
1132 rtmp_handler_invoke( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1133 {
1134     rtmp_packet_t *tmp_rtmp_packet;
1135     uint8_t *i, *end, *tmp_buffer;
1136     double number;
1137     char *string, *string2;
1138     ssize_t i_ret;
1139
1140     i = rtmp_packet->body->body;
1141     end = rtmp_packet->body->body + rtmp_packet->body->length_body;
1142
1143     i++; /* Pass over AMF_DATATYPE_STRING */
1144     string = amf_decode_string( &i );
1145
1146     i++; /* Pass over AMF_DATATYPE_NUMBER */
1147     number = amf_decode_number( &i );
1148
1149     msg_Dbg( p_thread, "%s %.1f", string, number );
1150
1151     if( strcmp( "connect", string ) == 0 )
1152     {
1153         /* Connection bandwith */
1154         tmp_rtmp_packet = rtmp_encode_onBWDone( p_thread, AMF_CALL_ONBWDONE );
1155
1156         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1157
1158         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1159         if( i_ret != tmp_rtmp_packet->length_encoded )
1160         {
1161             msg_Err( p_thread, "failed send connection bandwith" );
1162             goto error;
1163         }
1164         free( tmp_rtmp_packet->body->body );
1165         free( tmp_rtmp_packet->body );
1166         free( tmp_rtmp_packet );
1167         free( tmp_buffer );
1168
1169         /* Server bandwith */
1170         tmp_rtmp_packet = rtmp_encode_server_bw( p_thread, RTMP_SERVER_BW );
1171
1172         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1173
1174         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1175         if( i_ret != tmp_rtmp_packet->length_encoded )
1176         {
1177             msg_Err( p_thread, "failed send server bandwith" );
1178             goto error;
1179         }
1180         free( tmp_rtmp_packet->body->body );
1181         free( tmp_rtmp_packet->body );
1182         free( tmp_rtmp_packet );
1183         free( tmp_buffer );
1184
1185         /* Clear stream */
1186         tmp_rtmp_packet = rtmp_encode_ping_clear_stream( p_thread, RTMP_SRC_DST_CONNECT_OBJECT );
1187
1188         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1189
1190         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1191         if( i_ret != tmp_rtmp_packet->length_encoded )
1192         {
1193             msg_Err( p_thread, "failed send clear stream" );
1194             goto error;
1195         }
1196         free( tmp_rtmp_packet->body->body );
1197         free( tmp_rtmp_packet->body );
1198         free( tmp_rtmp_packet );
1199         free( tmp_buffer );
1200
1201         /* Reply NetConnection.connect */
1202         tmp_rtmp_packet = rtmp_encode_NetConnection_connect_result( p_thread, number );
1203
1204         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1205
1206         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1207         if( i_ret != tmp_rtmp_packet->length_encoded )
1208         {
1209             msg_Err( p_thread, "failed send reply NetConnection.connect" );
1210             goto error;
1211         }
1212         free( tmp_rtmp_packet->body->body );
1213         free( tmp_rtmp_packet->body );
1214         free( tmp_rtmp_packet );
1215         free( tmp_buffer );
1216     }
1217     else if( strcmp( "createStream", string ) == 0 )
1218     {
1219         p_thread->stream_client_id = number;
1220         p_thread->stream_server_id = RTMP_DEFAULT_STREAM_SERVER_ID;
1221
1222         /* Reply createStream */
1223         tmp_rtmp_packet = rtmp_encode_createStream_result( p_thread, p_thread->stream_client_id, p_thread->stream_server_id );
1224
1225         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1226
1227         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1228         if( i_ret != tmp_rtmp_packet->length_encoded )
1229         {
1230             msg_Err( p_thread, "failed send reply createStream" );
1231             goto error;
1232         }
1233         free( tmp_rtmp_packet->body->body );
1234         free( tmp_rtmp_packet->body );
1235         free( tmp_rtmp_packet );
1236         free( tmp_buffer );
1237
1238         /* Reset stream */
1239         tmp_rtmp_packet = rtmp_encode_ping_reset_stream( p_thread );
1240
1241         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1242
1243         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1244         if( i_ret != tmp_rtmp_packet->length_encoded )
1245         {
1246             msg_Err( p_thread, "failed send reset stream" );
1247             goto error;
1248         }
1249         free( tmp_rtmp_packet->body->body );
1250         free( tmp_rtmp_packet->body );
1251         free( tmp_rtmp_packet );
1252         free( tmp_buffer );
1253
1254         /* Clear stream */
1255         tmp_rtmp_packet = rtmp_encode_ping_clear_stream( p_thread, RTMP_SRC_DST_CONNECT_OBJECT2 );
1256
1257         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1258     
1259         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1260         if( i_ret != tmp_rtmp_packet->length_encoded )
1261         {
1262             msg_Err( p_thread, "failed send clear stream" );
1263             goto error;
1264         }
1265         free( tmp_rtmp_packet->body->body );
1266         free( tmp_rtmp_packet->body );
1267         free( tmp_rtmp_packet );
1268         free( tmp_buffer );
1269     }
1270     else if( strcmp( "publish", string ) == 0 )
1271     {
1272         i++;
1273         msg_Dbg( p_thread, "null" );
1274
1275         i++;
1276         string2 = amf_decode_string( &i );
1277         msg_Dbg( p_thread, "string: %s", string2 );
1278
1279         p_thread->psz_publish = strdup( string2 );
1280
1281         free( string2 );
1282     }
1283     else if( strcmp( "play", string ) == 0 )
1284     {
1285         i++;
1286         msg_Dbg( p_thread, "null" );
1287
1288         i++;
1289         string2 = amf_decode_string( &i );
1290         msg_Dbg( p_thread, "string: %s", string2 );
1291
1292         /* Reply NetStream.play.reset */
1293         tmp_rtmp_packet = rtmp_encode_NetStream_play_reset_onStatus( p_thread, string2 );
1294
1295         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1296
1297         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1298         if( i_ret != tmp_rtmp_packet->length_encoded )
1299         {
1300             msg_Err( p_thread, "failed send reply NetStream.play.reset" );
1301             goto error;
1302         }
1303         free( tmp_rtmp_packet->body->body );
1304         free( tmp_rtmp_packet->body );
1305         free( tmp_rtmp_packet );
1306         free( tmp_buffer );
1307
1308         /* Reply NetStream.play.start */
1309         tmp_rtmp_packet = rtmp_encode_NetStream_play_start_onStatus( p_thread, string2 );
1310
1311         tmp_buffer = rtmp_encode_packet( p_thread, tmp_rtmp_packet );
1312
1313         i_ret = net_Write( p_thread, p_thread->fd, NULL, tmp_buffer, tmp_rtmp_packet->length_encoded );
1314         if( i_ret != tmp_rtmp_packet->length_encoded )
1315         {
1316             msg_Err( p_thread, "failed send reply NetStream.play.start" );
1317             goto error;
1318         }
1319         free( tmp_rtmp_packet->body->body );
1320         free( tmp_rtmp_packet->body );
1321         free( tmp_rtmp_packet );
1322         free( tmp_buffer );
1323
1324         free( string2 );
1325
1326         p_thread->result_play = 0;
1327
1328         vlc_mutex_lock( &p_thread->lock );
1329         vlc_cond_signal( &p_thread->wait );
1330         vlc_mutex_unlock( &p_thread->lock );
1331     }
1332
1333     free( string );
1334
1335     while( i < end )
1336     {
1337         if( *i == AMF_DATATYPE_NUMBER )
1338         {
1339             i++;
1340             msg_Dbg( p_thread, "number: %le", amf_decode_number( &i ) );
1341         }
1342         else if( *i == AMF_DATATYPE_BOOLEAN )
1343         {
1344             i++;
1345             msg_Dbg( p_thread, "boolean: %s", amf_decode_boolean( &i ) ? "true" : "false" );
1346         }
1347         else if( *i == AMF_DATATYPE_STRING )
1348         {
1349             i++;
1350             string = amf_decode_string( &i );
1351             msg_Dbg( p_thread, "string: %s", string );
1352             free( string );
1353         }
1354         else if( *i == AMF_DATATYPE_OBJECT )
1355         {
1356             i++;
1357             msg_Dbg( p_thread, "object" );
1358             while( ( string = amf_decode_object( &i ) ) != NULL )
1359             {
1360                 if( *i == AMF_DATATYPE_NUMBER )
1361                 {
1362                     i++;
1363                     msg_Dbg( p_thread, "key: %s value: %le", string, amf_decode_number( &i ) );
1364                 }
1365                 else if( *i == AMF_DATATYPE_BOOLEAN )
1366                 {
1367                     i++;
1368                     msg_Dbg( p_thread, "key: %s value: %s", string, amf_decode_boolean( &i ) ? "true" : "false" );
1369                 }
1370                 else if( *i == AMF_DATATYPE_STRING )
1371                 {
1372                     i++;
1373                     string2 = amf_decode_string( &i );
1374                     msg_Dbg( p_thread, "key: %s value: %s", string, string2 );
1375                     if( strcmp( "code", string ) == 0 )
1376                     {
1377                         if( strcmp( "NetConnection.Connect.Success", string2 ) == 0 )
1378                         {
1379                             p_thread->result_connect = 0;
1380
1381                             vlc_mutex_lock( &p_thread->lock );
1382                             vlc_cond_signal( &p_thread->wait );
1383                             vlc_mutex_unlock( &p_thread->lock );
1384                         }
1385                         else if( strcmp( "NetConnection.Connect.InvalidApp", string2 ) == 0 )
1386                         {
1387                             p_thread->b_die = 1; 
1388
1389                             vlc_mutex_lock( &p_thread->lock );
1390                             vlc_cond_signal( &p_thread->wait );
1391                             vlc_mutex_unlock( &p_thread->lock );
1392                         }
1393                         else if( strcmp( "NetStream.Play.Start", string2 ) == 0 )
1394                         {
1395                             p_thread->result_play = 0;
1396
1397                             vlc_mutex_lock( &p_thread->lock );
1398                             vlc_cond_signal( &p_thread->wait );
1399                             vlc_mutex_unlock( &p_thread->lock );
1400                         }
1401                         else if( strcmp( "NetStream.Play.Stop", string2 ) == 0 )
1402                         {
1403                             p_thread->result_stop = 1;
1404
1405                             block_FifoWake( p_thread->p_fifo_input );
1406                         }
1407                     }
1408                     free( string2 );
1409                 }
1410                 else if( *i == AMF_DATATYPE_NULL )
1411                 {
1412                     i++;
1413                     msg_Dbg( p_thread, "key: %s value: Null", string );
1414                 }
1415                 else if( *i == AMF_DATATYPE_UNDEFINED )
1416                 {
1417                     i++;
1418                     msg_Dbg( p_thread, "key: %s value: undefined (Null)", string );
1419                 }
1420                 else
1421                 {
1422                     i++;
1423                     msg_Warn( p_thread, "key: %s value: undefined AMF type", string );
1424                 }
1425                 free( string );
1426             }
1427             msg_Dbg( p_thread, "end of object" );
1428         }
1429         else if( *i == AMF_DATATYPE_NULL)
1430         {
1431             i++;
1432             msg_Dbg( p_thread, "null" );
1433         }
1434         else if( *i == AMF_DATATYPE_UNDEFINED )
1435         {
1436             i++;
1437             msg_Dbg( p_thread, "undefined (null)" );
1438         }
1439         else
1440         {
1441             i++;
1442             msg_Warn( p_thread, "undefined AMF type" );
1443         }
1444     }
1445     
1446     free( rtmp_packet->body->body );
1447     free( rtmp_packet->body );
1448     free( rtmp_packet );
1449
1450     return;
1451
1452 error:
1453     free( tmp_rtmp_packet->body->body );
1454     free( tmp_rtmp_packet->body );
1455     free( tmp_rtmp_packet );
1456     free( tmp_buffer );
1457 }
1458
1459 /* length header calculated automatically based on last packet in the same channel */
1460 /* timestamps passed are always absolute */
1461 static rtmp_packet_t *
1462 rtmp_new_packet( rtmp_control_thread_t *p_thread, uint8_t stream_index, uint32_t timestamp, uint8_t content_type, uint32_t src_dst, rtmp_body_t *body )
1463 {
1464     int interchunk_headers;
1465     rtmp_packet_t *rtmp_packet;
1466
1467     rtmp_packet = (rtmp_packet_t *) malloc( sizeof( rtmp_packet_t ) );
1468     if( !rtmp_packet ) return NULL;
1469
1470     interchunk_headers = body->length_body / p_thread->chunk_size_send;
1471     if( body->length_body % p_thread->chunk_size_send == 0 )
1472         interchunk_headers--;
1473
1474     if( src_dst != p_thread->rtmp_headers_send[stream_index].src_dst )
1475     {
1476         p_thread->rtmp_headers_send[stream_index].timestamp = timestamp;
1477         p_thread->rtmp_headers_send[stream_index].length_body = body->length_body;
1478         p_thread->rtmp_headers_send[stream_index].content_type = content_type;
1479         p_thread->rtmp_headers_send[stream_index].src_dst = src_dst;
1480         
1481         rtmp_packet->length_header = 12;
1482     }
1483     else if( content_type != p_thread->rtmp_headers_send[stream_index].content_type
1484         || body->length_body != p_thread->rtmp_headers_send[stream_index].length_body )
1485     {
1486         p_thread->rtmp_headers_send[stream_index].timestamp_relative = 
1487             timestamp - p_thread->rtmp_headers_send[stream_index].timestamp;
1488         p_thread->rtmp_headers_send[stream_index].timestamp = timestamp;
1489         p_thread->rtmp_headers_send[stream_index].length_body = body->length_body;
1490         p_thread->rtmp_headers_send[stream_index].content_type = content_type;
1491
1492         rtmp_packet->length_header = 8;
1493     }
1494     else if( timestamp != p_thread->rtmp_headers_send[stream_index].timestamp )
1495     {
1496         p_thread->rtmp_headers_send[stream_index].timestamp_relative = 
1497             timestamp - p_thread->rtmp_headers_send[stream_index].timestamp;
1498         p_thread->rtmp_headers_send[stream_index].timestamp = timestamp;
1499
1500         rtmp_packet->length_header = 4;
1501     }
1502     else
1503     {
1504         rtmp_packet->length_header = 1;
1505     }
1506 /*TODO: puede que no haga falta guardar el timestamp relative */
1507     rtmp_packet->stream_index = stream_index;
1508     if( rtmp_packet->length_header == 12 )
1509     {
1510         rtmp_packet->timestamp = timestamp;
1511         rtmp_packet->timestamp_relative = 0;
1512     }
1513     else
1514     {
1515         rtmp_packet->timestamp = timestamp;
1516         rtmp_packet->timestamp_relative = p_thread->rtmp_headers_send[stream_index].timestamp_relative;
1517     }
1518     rtmp_packet->length_encoded = rtmp_packet->length_header + body->length_body + interchunk_headers;
1519     rtmp_packet->length_body = body->length_body;
1520     rtmp_packet->content_type = content_type;
1521     rtmp_packet->src_dst = src_dst;
1522
1523     rtmp_packet->body = (rtmp_body_t *) malloc( sizeof( rtmp_body_t ) );
1524     if( !rtmp_packet->body )
1525     {
1526        free( rtmp_packet );
1527        return NULL;
1528     }
1529
1530     rtmp_packet->body->length_body = body->length_body;
1531     rtmp_packet->body->length_buffer = body->length_body;
1532     rtmp_packet->body->body = (uint8_t *) malloc( rtmp_packet->body->length_buffer * sizeof( uint8_t ) );
1533     if( !rtmp_packet->body->body )
1534     {
1535         free( rtmp_packet->body );
1536         free( rtmp_packet );
1537         return NULL;
1538     }
1539     memcpy( rtmp_packet->body->body, body->body, rtmp_packet->body->length_body );
1540
1541     return rtmp_packet;
1542 }
1543
1544 static block_t *
1545 rtmp_new_block( rtmp_control_thread_t *p_thread, uint8_t *buffer, int32_t length_buffer )
1546 {
1547     block_t *p_buffer;
1548     /* DOWN: p_thread->p_empty_blocks->i_depth */
1549     while ( block_FifoCount( p_thread->p_empty_blocks ) > MAX_EMPTY_BLOCKS )
1550     {
1551         p_buffer = block_FifoGet( p_thread->p_empty_blocks );
1552         block_Release( p_buffer );
1553     }
1554     /* DOWN: p_thread->p_empty_blocks->i_depth */
1555     if( block_FifoCount( p_thread->p_empty_blocks ) == 0 )
1556     {
1557         p_buffer = block_New( p_thread, length_buffer );
1558     }
1559     else
1560     {
1561         p_buffer = block_FifoGet( p_thread->p_empty_blocks );
1562         p_buffer = block_Realloc( p_buffer, 0, length_buffer );
1563     }
1564
1565     p_buffer->i_buffer = length_buffer;
1566
1567     memcpy( p_buffer->p_buffer, buffer, p_buffer->i_buffer );
1568
1569     return p_buffer;
1570 }
1571
1572 /* call sequence for each packet rtmp_new_packet -> rtmp_encode_packet -> send */
1573 /* no parallelism allowed because of optimization in header length */
1574 uint8_t *
1575 rtmp_encode_packet( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
1576 {
1577     uint8_t *out;
1578     int interchunk_headers;
1579     uint32_t timestamp, length_body, src_dst;
1580     int i, j;
1581
1582     out = (uint8_t *) malloc( rtmp_packet->length_encoded * sizeof( uint8_t ) );
1583     if( !out ) return NULL;
1584
1585     interchunk_headers = rtmp_packet->body->length_body / p_thread->chunk_size_send;
1586     if( rtmp_packet->body->length_body % p_thread->chunk_size_send == 0 )
1587         interchunk_headers--;
1588
1589     if( rtmp_packet->length_header == 12 )
1590     {
1591         /* Timestamp absolute */
1592         timestamp = hton32( rtmp_packet->timestamp );
1593         memcpy( out, &timestamp, sizeof( uint32_t ) );
1594
1595         src_dst = hton32( rtmp_packet->src_dst );
1596         memcpy( out + 8, &src_dst, sizeof( uint32_t ) );
1597     }
1598
1599     if( rtmp_packet->length_header >= 8 )
1600     {
1601         /* Length without inter chunk headers */
1602         length_body = hton32( rtmp_packet->body->length_body );
1603         memcpy( out + 3, &length_body, sizeof( uint32_t ) );
1604
1605         out[7] = rtmp_packet->content_type;
1606     }
1607     if( rtmp_packet->length_header >= 4 && rtmp_packet->length_header != 12 )
1608     {
1609         /* Timestamp relative */
1610         timestamp = hton32( rtmp_packet->timestamp_relative );
1611         memcpy( out, &timestamp, sizeof( uint32_t ) );
1612     }
1613
1614     out[0] = rtmp_encode_header_size( (vlc_object_t *) p_thread, rtmp_packet->length_header ) + rtmp_packet->stream_index;
1615
1616     /* Insert inter chunk headers */
1617     for(i = 0, j = 0; i < rtmp_packet->body->length_body + interchunk_headers; i++, j++)
1618     {
1619         if( j % p_thread->chunk_size_send == 0 && j != 0 )
1620             out[rtmp_packet->length_header + i++] = RTMP_HEADER_SIZE_1 + rtmp_packet->stream_index;
1621         out[rtmp_packet->length_header + i] = rtmp_packet->body->body[j];
1622     }
1623
1624     return out;
1625 }
1626
1627 static rtmp_packet_t *
1628 rtmp_encode_onBWDone( rtmp_control_thread_t *p_thread, double number )
1629 {
1630     rtmp_packet_t *rtmp_packet;
1631     rtmp_body_t *rtmp_body;
1632     uint8_t *tmp_buffer;
1633
1634     /* Build onBWDone */
1635     rtmp_body = rtmp_body_new( -1 );
1636
1637     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onBWDone" );
1638     rtmp_body_append( rtmp_body, tmp_buffer,
1639         AMF_DATATYPE_SIZE_STRING + strlen( "onBWDone" ) );
1640     free( tmp_buffer );
1641
1642     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &number );
1643     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1644     free( tmp_buffer );
1645
1646     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
1647     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
1648     free( tmp_buffer );
1649
1650     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
1651         0, RTMP_CONTENT_TYPE_INVOKE, RTMP_SRC_DST_CONNECT_OBJECT, rtmp_body );
1652     free( rtmp_body->body );
1653     free( rtmp_body );
1654
1655     return rtmp_packet;
1656 }
1657
1658 static rtmp_packet_t *
1659 rtmp_encode_server_bw( rtmp_control_thread_t *p_thread, uint32_t number )
1660 {
1661     rtmp_packet_t *rtmp_packet;
1662     rtmp_body_t *rtmp_body;
1663
1664     /* Build server bw */
1665     rtmp_body = rtmp_body_new( -1 );
1666
1667     rtmp_body_append( rtmp_body, (uint8_t *) &number, sizeof( uint32_t ) );
1668
1669     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
1670         0, RTMP_CONTENT_TYPE_SERVER_BW, RTMP_SRC_DST_CONNECT_OBJECT, rtmp_body );
1671     free( rtmp_body->body );
1672     free( rtmp_body );
1673
1674     return rtmp_packet;
1675 }
1676
1677 static rtmp_packet_t *
1678 rtmp_encode_NetConnection_connect_result( rtmp_control_thread_t *p_thread, double number )
1679 {
1680     rtmp_packet_t *rtmp_packet;
1681     rtmp_body_t *rtmp_body;
1682     uint8_t *tmp_buffer;
1683
1684     /* Build NetConnection.connect result */
1685     rtmp_body = rtmp_body_new( -1 );
1686
1687     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "_result" );
1688     rtmp_body_append( rtmp_body, tmp_buffer,
1689         AMF_DATATYPE_SIZE_STRING + strlen( "_result" ) );
1690     free( tmp_buffer );
1691
1692     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &number );
1693     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1694     free( tmp_buffer );
1695
1696     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
1697     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
1698     free( tmp_buffer );
1699
1700     tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL );
1701     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT );
1702     free( tmp_buffer );
1703
1704     tmp_buffer = amf_encode_object_variable( "level",
1705         AMF_DATATYPE_STRING, "status" );
1706     rtmp_body_append( rtmp_body, tmp_buffer,
1707         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "level" ) +
1708         AMF_DATATYPE_SIZE_STRING + strlen( "status" ) );
1709     free( tmp_buffer );
1710
1711     tmp_buffer = amf_encode_object_variable( "code",
1712         AMF_DATATYPE_STRING, "NetConnection.Connect.Success" );
1713     rtmp_body_append( rtmp_body, tmp_buffer,
1714         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "code" ) +
1715         AMF_DATATYPE_SIZE_STRING + strlen( "NetConnection.Connect.Success" ) );
1716     free( tmp_buffer );
1717
1718     tmp_buffer = amf_encode_object_variable( "description",
1719         AMF_DATATYPE_STRING, "Connection succeeded." );
1720     rtmp_body_append( rtmp_body, tmp_buffer,
1721         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "description" ) +
1722         AMF_DATATYPE_SIZE_STRING + strlen( "Connection succeeded." ) );
1723     free( tmp_buffer );
1724
1725     tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL );
1726     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
1727     free( tmp_buffer );
1728
1729     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
1730         0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body );
1731     free( rtmp_body->body );
1732     free( rtmp_body );
1733
1734     return rtmp_packet;
1735 }
1736
1737 static rtmp_packet_t *
1738 rtmp_encode_createStream_result( rtmp_control_thread_t *p_thread, double stream_client_id, double stream_server_id )
1739 {
1740     rtmp_packet_t *rtmp_packet;
1741     rtmp_body_t *rtmp_body;
1742     uint8_t *tmp_buffer;
1743
1744     /* Build createStream result */
1745     rtmp_body = rtmp_body_new( -1 );
1746
1747     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "_result" );
1748     rtmp_body_append( rtmp_body, tmp_buffer,
1749         AMF_DATATYPE_SIZE_STRING + strlen( "_result" ) );
1750     free( tmp_buffer );
1751
1752     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &stream_client_id );
1753     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1754     free( tmp_buffer );
1755
1756     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
1757     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
1758     free( tmp_buffer );
1759
1760     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &stream_server_id );
1761     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1762     free( tmp_buffer );
1763
1764     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
1765         0, RTMP_CONTENT_TYPE_INVOKE, 0, rtmp_body );
1766     free( rtmp_body->body );
1767     free( rtmp_body );
1768
1769     return rtmp_packet;
1770 }
1771
1772 static rtmp_packet_t *
1773 rtmp_encode_ping_reset_stream( rtmp_control_thread_t *p_thread )
1774 {
1775     rtmp_packet_t *rtmp_packet;
1776     rtmp_body_t *rtmp_body;
1777     uint8_t *tmp_buffer;
1778
1779     /* Build ping reset stream */
1780     rtmp_body = rtmp_body_new( -1 );
1781
1782     tmp_buffer = rtmp_encode_ping( RTMP_PING_RESET_STREAM, RTMP_SRC_DST_CONNECT_OBJECT2, 0, 0 );
1783     rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_RESET_STREAM );
1784     free( tmp_buffer );
1785
1786     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
1787         0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body );
1788     free( rtmp_body->body );
1789     free( rtmp_body );
1790
1791     return rtmp_packet;
1792 }
1793
1794 static rtmp_packet_t *
1795 rtmp_encode_ping_clear_stream( rtmp_control_thread_t *p_thread, uint32_t src_dst )
1796 {
1797     rtmp_packet_t *rtmp_packet;
1798     rtmp_body_t *rtmp_body;
1799     uint8_t *tmp_buffer;
1800
1801     /* Build ping clear stream */
1802     rtmp_body = rtmp_body_new( -1 );
1803
1804     tmp_buffer = rtmp_encode_ping( RTMP_PING_CLEAR_STREAM, src_dst, 0, 0 );
1805     rtmp_body_append( rtmp_body, tmp_buffer, RTMP_PING_SIZE_CLEAR_STREAM );
1806     free( tmp_buffer );
1807
1808     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_CONTROL,
1809         0, RTMP_CONTENT_TYPE_PING, 0, rtmp_body );
1810     free( rtmp_body->body );
1811     free( rtmp_body );
1812
1813     return rtmp_packet;
1814 }
1815
1816 static rtmp_packet_t *
1817 rtmp_encode_NetStream_play_reset_onStatus( rtmp_control_thread_t *p_thread, char *psz_media )
1818 {
1819     rtmp_packet_t *rtmp_packet;
1820     rtmp_body_t *rtmp_body;
1821     uint8_t *tmp_buffer;
1822     double number;
1823     char *description;
1824
1825     /* Build NetStream.play.reset onStatus */
1826     rtmp_body = rtmp_body_new( -1 );
1827
1828     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onStatus" );
1829     rtmp_body_append( rtmp_body, tmp_buffer,
1830         AMF_DATATYPE_SIZE_STRING + strlen( "onStatus" ) );
1831     free( tmp_buffer );
1832
1833     number = 1; /* TODO: review this number*/
1834     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &number );
1835     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1836     free( tmp_buffer );
1837
1838     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
1839     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
1840     free( tmp_buffer );
1841
1842     tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL );
1843     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT );
1844     free( tmp_buffer );
1845
1846     tmp_buffer = amf_encode_object_variable( "level",
1847         AMF_DATATYPE_STRING, "status" );
1848     rtmp_body_append( rtmp_body, tmp_buffer,
1849         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "level" ) +
1850         AMF_DATATYPE_SIZE_STRING + strlen( "status" ) );
1851     free( tmp_buffer );
1852
1853     tmp_buffer = amf_encode_object_variable( "code",
1854         AMF_DATATYPE_STRING, "NetStream.Play.Reset" );
1855     rtmp_body_append( rtmp_body, tmp_buffer,
1856         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "code" ) +
1857         AMF_DATATYPE_SIZE_STRING + strlen( "NetStream.Play.Reset" ) );
1858     free( tmp_buffer );
1859
1860     description = (char *) malloc( strlen( "Playing and resetting ") + strlen( psz_media ) + strlen( "." ) + 1 );
1861     if( !description )
1862     {
1863         free( rtmp_body->body );
1864         free( rtmp_body );
1865         return NULL;
1866     }
1867     sprintf( description, "Playing and resetting %s.", psz_media );
1868     tmp_buffer = amf_encode_object_variable( "description",
1869         AMF_DATATYPE_STRING, description );
1870     rtmp_body_append( rtmp_body, tmp_buffer,
1871         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "description" ) +
1872         AMF_DATATYPE_SIZE_STRING + strlen( description ) );
1873     free( tmp_buffer );
1874     free( description );
1875
1876     tmp_buffer = amf_encode_object_variable( "details",
1877         AMF_DATATYPE_STRING, psz_media );
1878     rtmp_body_append( rtmp_body, tmp_buffer,
1879         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "details" ) +
1880         AMF_DATATYPE_SIZE_STRING + strlen( psz_media ) );
1881     free( tmp_buffer );
1882
1883     tmp_buffer = amf_encode_object_variable( "clientid",
1884         AMF_DATATYPE_NUMBER, &p_thread->stream_client_id );
1885     rtmp_body_append( rtmp_body, tmp_buffer,
1886         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "clientid" ) +
1887         AMF_DATATYPE_SIZE_NUMBER );
1888     free( tmp_buffer );
1889
1890     tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL );
1891     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
1892     free( tmp_buffer );
1893
1894     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_NOTIFY,
1895         0, RTMP_CONTENT_TYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body );
1896     free( rtmp_body->body );
1897     free( rtmp_body );
1898
1899     return rtmp_packet;
1900 }
1901
1902 static rtmp_packet_t *
1903 rtmp_encode_NetStream_play_start_onStatus( rtmp_control_thread_t *p_thread, char *psz_media )
1904 {
1905     rtmp_packet_t *rtmp_packet;
1906     rtmp_body_t *rtmp_body;
1907     uint8_t *tmp_buffer;
1908     double number;
1909     char *description;
1910
1911     /* Build NetStream.play.start onStatus */
1912     rtmp_body = rtmp_body_new( -1 );
1913
1914     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onStatus" );
1915     rtmp_body_append( rtmp_body, tmp_buffer,
1916         AMF_DATATYPE_SIZE_STRING + strlen( "onStatus" ) );
1917     free( tmp_buffer );
1918
1919     number = 1; /* TODO: review this number*/
1920     tmp_buffer = amf_encode_element( AMF_DATATYPE_NUMBER, &number );
1921     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NUMBER );
1922     free( tmp_buffer );
1923
1924     tmp_buffer = amf_encode_element( AMF_DATATYPE_NULL, NULL );
1925     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_NULL );
1926     free( tmp_buffer );
1927
1928     tmp_buffer = amf_encode_element( AMF_DATATYPE_OBJECT, NULL );
1929     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_OBJECT );
1930     free( tmp_buffer );
1931
1932     tmp_buffer = amf_encode_object_variable( "level",
1933         AMF_DATATYPE_STRING, "status" );
1934     rtmp_body_append( rtmp_body, tmp_buffer,
1935         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "level" ) +
1936         AMF_DATATYPE_SIZE_STRING + strlen( "status" ) );
1937     free( tmp_buffer );
1938
1939     tmp_buffer = amf_encode_object_variable( "code",
1940         AMF_DATATYPE_STRING, "NetStream.Play.Start" );
1941     rtmp_body_append( rtmp_body, tmp_buffer,
1942         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "code" ) +
1943         AMF_DATATYPE_SIZE_STRING + strlen( "NetStream.Play.Start" ) );
1944     free( tmp_buffer );
1945
1946     description = (char *) malloc( strlen( "Started playing ") + strlen( psz_media ) + strlen( "." ) + 1 );
1947     if( !description )
1948     {
1949         free( rtmp_body->body );
1950         free( rtmp_body );
1951         return NULL;
1952     }
1953
1954     sprintf( description, "Started playing %s.", psz_media );
1955     tmp_buffer = amf_encode_object_variable( "description",
1956         AMF_DATATYPE_STRING, description );
1957     rtmp_body_append( rtmp_body, tmp_buffer,
1958         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "description" ) +
1959         AMF_DATATYPE_SIZE_STRING + strlen( description ) );
1960     free( tmp_buffer );
1961     free( description );
1962
1963     tmp_buffer = amf_encode_object_variable( "details",
1964         AMF_DATATYPE_STRING, psz_media );
1965     rtmp_body_append( rtmp_body, tmp_buffer,
1966         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "details" ) +
1967         AMF_DATATYPE_SIZE_STRING + strlen( psz_media ) );
1968     free( tmp_buffer );
1969
1970     tmp_buffer = amf_encode_object_variable( "clientid",
1971         AMF_DATATYPE_NUMBER, &p_thread->stream_client_id );
1972     rtmp_body_append( rtmp_body, tmp_buffer,
1973         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "clientid" ) +
1974         AMF_DATATYPE_SIZE_NUMBER );
1975     free( tmp_buffer );
1976
1977     tmp_buffer = amf_encode_element ( AMF_DATATYPE_END_OF_OBJECT, NULL );
1978     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
1979     free( tmp_buffer );
1980
1981     rtmp_packet = rtmp_new_packet( p_thread, RTMP_DEFAULT_STREAM_INDEX_NOTIFY,
1982         0, RTMP_CONTENT_TYPE_INVOKE, RTMP_SRC_DST_DEFAULT, rtmp_body );
1983     free( rtmp_body->body );
1984     free( rtmp_body );
1985
1986     return rtmp_packet;
1987 }
1988
1989 static uint8_t
1990 rtmp_encode_header_size( vlc_object_t *p_this, uint8_t header_size )
1991 {
1992     if( header_size == 1 )
1993         return RTMP_HEADER_SIZE_1;
1994     else if( header_size == 4 )
1995         return RTMP_HEADER_SIZE_4;
1996     else if( header_size == 8 )
1997         return RTMP_HEADER_SIZE_8;
1998     else if( header_size == 12 )
1999         return RTMP_HEADER_SIZE_12;
2000     else
2001     {
2002         msg_Err( p_this, "invalid header size for encoding" );
2003         return 0;
2004     }
2005 }
2006
2007 static uint8_t
2008 rtmp_decode_header_size( vlc_object_t *p_this, uint8_t header_size )
2009 {
2010     if( header_size == RTMP_HEADER_SIZE_1 )
2011         return 1;
2012     else if( header_size == RTMP_HEADER_SIZE_4 )
2013         return 4;
2014     else if( header_size == RTMP_HEADER_SIZE_8 )
2015         return 8;
2016     else if( header_size == RTMP_HEADER_SIZE_12 )
2017         return 12;
2018     else
2019     {
2020         msg_Err( p_this, "invalid RTMP_HEADER_SIZE_XX " );
2021         return 0;
2022     }
2023 }
2024
2025 static uint8_t
2026 rtmp_get_stream_index( uint8_t content_type )
2027 {
2028     if( content_type == RTMP_CONTENT_TYPE_AUDIO_DATA )
2029         return RTMP_DEFAULT_STREAM_INDEX_AUDIO_DATA;
2030     else if( content_type == RTMP_CONTENT_TYPE_VIDEO_DATA )
2031         return RTMP_DEFAULT_STREAM_INDEX_VIDEO_DATA;
2032     else if( content_type == RTMP_CONTENT_TYPE_NOTIFY )
2033         return RTMP_DEFAULT_STREAM_INDEX_NOTIFY;
2034     else
2035         return -1;
2036 }
2037
2038 /*****************************************************************************
2039  * Body handling implementation:
2040  ******************************************************************************/
2041 rtmp_body_t *
2042 rtmp_body_new( int length_buffer )
2043 {
2044     rtmp_body_t *rtmp_body;
2045
2046     rtmp_body = (rtmp_body_t *) malloc( sizeof( rtmp_body_t ) );
2047     if( !rtmp_body ) return NULL;
2048
2049     rtmp_body->length_body = 0;
2050     if( length_buffer < 0 )
2051         rtmp_body->length_buffer = RTMP_BODY_SIZE_ALLOC;
2052     else
2053         rtmp_body->length_buffer = length_buffer;
2054     rtmp_body->body = (uint8_t *) malloc( rtmp_body->length_buffer * sizeof( uint8_t ) );
2055     if( !rtmp_body->body )
2056     {
2057         free( rtmp_body );
2058         return NULL;
2059     }
2060     return rtmp_body;
2061 }
2062
2063 void
2064 rtmp_body_reset( rtmp_body_t *rtmp_body )
2065 {
2066     rtmp_body->length_body = 0;
2067 }
2068
2069 static void
2070 rtmp_body_append( rtmp_body_t *rtmp_body, uint8_t *buffer, uint32_t length )
2071 {
2072     if( rtmp_body->length_body + length > rtmp_body->length_buffer )
2073     {
2074         uint8_t *tmp;
2075         rtmp_body->length_buffer = rtmp_body->length_body + length;
2076         tmp =  realloc( rtmp_body->body,
2077                         rtmp_body->length_buffer * sizeof( uint8_t ) );
2078         if( !tmp ) return;
2079         rtmp_body->body = tmp;
2080     }
2081
2082     memcpy( rtmp_body->body + rtmp_body->length_body, buffer, length );
2083     rtmp_body->length_body += length;
2084 }
2085
2086 /*****************************************************************************
2087  * RTMP ping implementation:
2088  ******************************************************************************/
2089 static uint8_t *
2090 rtmp_encode_ping( uint16_t type, uint32_t src_dst, uint32_t third_arg, uint32_t fourth_arg )
2091 {
2092     uint8_t *out = NULL;
2093     VLC_UNUSED(fourth_arg);
2094
2095     if( type == RTMP_PING_CLEAR_STREAM )
2096         out = (uint8_t *) malloc( RTMP_PING_SIZE_CLEAR_STREAM * sizeof( uint8_t ) );
2097     else if( type == RTMP_PING_CLEAR_PLAYING_BUFFER )
2098         out = (uint8_t *) malloc( RTMP_PING_SIZE_CLEAR_PLAYING_BUFFER * sizeof( uint8_t ) );
2099     else if( type == RTMP_PING_BUFFER_TIME_CLIENT )
2100     {
2101         out = (uint8_t *) malloc( RTMP_PING_SIZE_BUFFER_TIME_CLIENT * sizeof( uint8_t ) );
2102         if( !out ) goto error;
2103         third_arg = hton32( third_arg );
2104         memcpy( out + 6, &third_arg, sizeof( uint32_t ) );
2105     }
2106     else if( type == RTMP_PING_RESET_STREAM )
2107     {
2108         out = (uint8_t *) malloc( RTMP_PING_SIZE_RESET_STREAM * sizeof( uint8_t ) );
2109     }
2110 /*    else if( type == RTMP_PING_CLIENT_FROM_SERVER ) TODO: research this
2111     {
2112     }
2113     else if( type == RTMP_PING_PONG_FROM_CLIENT )
2114     {
2115     }
2116 */    else
2117     {
2118         out = (uint8_t *) malloc( RTMP_PING_SIZE_BUFFER_TIME_CLIENT * sizeof( uint8_t ) );
2119         if( !out ) goto error;
2120         out[6] = 0x0D; out[7] = 0x0E; out[8] = 0x0A; out[9] = 0x0D;
2121     }
2122
2123     if( !out ) goto error;
2124
2125     type = hton16( type );
2126     memcpy( out, &type, sizeof( uint16_t ) );
2127
2128     src_dst = hton32( src_dst );
2129     memcpy( out + 2, &src_dst, sizeof( uint32_t ) );
2130
2131     return out;
2132
2133 error:
2134     return NULL;
2135 }
2136
2137 /*****************************************************************************
2138  * AMF implementation:
2139  ******************************************************************************/
2140 static uint8_t *
2141 amf_encode_element( uint8_t element, const void *value )
2142 {
2143     uint8_t *out;
2144
2145     if ( element == AMF_DATATYPE_NUMBER )
2146     {
2147         uint64_t number = *(uint64_t *) value;
2148
2149         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_NUMBER * sizeof( uint8_t ) );
2150         if( !out ) return NULL;
2151         
2152         number = hton64( number );
2153         out[0] = AMF_DATATYPE_NUMBER;
2154         memcpy( out + 1, &number, sizeof( uint64_t ) );
2155     } else if ( element == AMF_DATATYPE_BOOLEAN )
2156     {
2157         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_BOOLEAN * sizeof( uint8_t ) );
2158         if( !out ) return NULL;
2159
2160         out[0] = AMF_DATATYPE_BOOLEAN;
2161         out[1] = *(uint8_t *) value;
2162     } else if ( element == AMF_DATATYPE_STRING )
2163     {
2164         uint16_t length_psz, length_psz_cpy;
2165
2166         length_psz = length_psz_cpy = strlen( (char *) value );
2167         out = (uint8_t *) malloc( ( AMF_DATATYPE_SIZE_STRING + length_psz ) * sizeof( uint8_t ) );
2168         if( !out ) return NULL;
2169
2170         out[0] = AMF_DATATYPE_STRING;
2171         length_psz = hton16( length_psz );
2172         memcpy( out + 1, &length_psz, sizeof( uint16_t ) );
2173         memcpy( out + 3, value, length_psz_cpy );
2174     } else if ( element == AMF_DATATYPE_OBJECT )
2175     {
2176         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_OBJECT * sizeof( uint8_t ) );
2177         if( !out ) return NULL;
2178
2179         out[0] = AMF_DATATYPE_OBJECT;
2180     } else if ( element == AMF_DATATYPE_NULL )
2181     {
2182         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_NULL * sizeof( uint8_t ) );
2183         if( !out ) return NULL;
2184
2185         out[0] = AMF_DATATYPE_NULL;
2186     } else if ( element == AMF_DATATYPE_MIXED_ARRAY )
2187     {
2188         uint32_t highest_index = *(uint32_t *) value;
2189
2190         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_MIXED_ARRAY * sizeof( uint8_t ) );
2191         if( !out ) return NULL;
2192
2193         highest_index = hton32( highest_index );
2194         out[0] = AMF_DATATYPE_MIXED_ARRAY;
2195         memcpy( out + 1, &highest_index, sizeof( uint32_t ) );
2196     } else if ( element == AMF_DATATYPE_END_OF_OBJECT )
2197     {
2198         out = (uint8_t *) calloc( AMF_DATATYPE_SIZE_END_OF_OBJECT, sizeof( uint8_t ) );
2199
2200         out[AMF_DATATYPE_SIZE_END_OF_OBJECT - 1] = AMF_DATATYPE_END_OF_OBJECT;
2201     } else
2202     {
2203         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_NUMBER * sizeof( uint8_t ) );
2204         if( !out ) return NULL;
2205
2206         out[0] = AMF_DATATYPE_NUMBER;
2207         out[1] = 0x0D; out[2] = 0x0E; out[3] = 0x0A; out[4] = 0x0D;
2208         out[5] = 0x0B; out[6] = 0x0E; out[7] = 0x0E; out[8] = 0x0F;
2209     }
2210
2211     return out;
2212 }
2213
2214 static uint8_t *
2215 amf_encode_object_variable( const char *key, uint8_t element, const void *value )
2216 {
2217     uint8_t *out, *out_value;
2218     int length_value;
2219     uint16_t length_psz, length_psz_cpy;
2220
2221     length_psz = length_psz_cpy = strlen( key );
2222
2223     if( element == AMF_DATATYPE_NUMBER )
2224         length_value = AMF_DATATYPE_SIZE_NUMBER;
2225     else if( element == AMF_DATATYPE_BOOLEAN )
2226         length_value = AMF_DATATYPE_SIZE_BOOLEAN;
2227     else if( element == AMF_DATATYPE_STRING )
2228         length_value = AMF_DATATYPE_SIZE_STRING + strlen( (char *) value );
2229     else if( element == AMF_DATATYPE_NULL )
2230         length_value = AMF_DATATYPE_SIZE_NULL;
2231     else
2232     {
2233         out = (uint8_t *) malloc( AMF_DATATYPE_SIZE_NUMBER * sizeof( uint8_t ) );
2234         if( !out ) return NULL;
2235
2236         out[0] = AMF_DATATYPE_NUMBER;
2237         out[1] = 0xD; out[2] = 0xE; out[3] = 0xA; out[4] = 0xD;
2238         out[5] = 0xB; out[6] = 0xE; out[7] = 0xE; out[8] = 0xF;
2239
2240         return out;
2241     }
2242
2243     out = (uint8_t *) malloc( ( AMF_DATATYPE_SIZE_OBJECT_VARIABLE + length_psz + length_value ) * sizeof( uint8_t ) );
2244     if( !out ) return NULL;
2245
2246     length_psz = hton16( length_psz );
2247     memcpy( out, &length_psz, sizeof( uint16_t ) );
2248     memcpy( out + 2, key, length_psz_cpy );
2249
2250     out_value = amf_encode_element( element, value );
2251     memcpy( out + 2 + length_psz_cpy, out_value, length_value );
2252     free( out_value );
2253
2254     return out;
2255 }
2256
2257 static double
2258 amf_decode_number( uint8_t **buffer )
2259 {
2260     uint64_t number;
2261     double out;
2262
2263     number = ntoh64( *(uint64_t *) *buffer );
2264     memcpy(&out, &number, sizeof( uint64_t ) );
2265     *buffer += sizeof( uint64_t );
2266
2267     return out;
2268 }
2269
2270 static int
2271 amf_decode_boolean( uint8_t **buffer )
2272 {
2273     int out;
2274
2275     out = **buffer;
2276     *buffer += 1;
2277
2278     return out;
2279 }
2280
2281 /* return value allocated dinamically */
2282 static char *
2283 amf_decode_string( uint8_t **buffer )
2284 {
2285     char *out;
2286     int length;
2287     int i;
2288
2289     length = ntoh16( *(uint16_t *) *buffer );
2290     *buffer += sizeof( uint16_t );
2291
2292     out = (char *) malloc( length + 1 ); /* '\0' terminated */
2293     if( !out ) return NULL;
2294
2295     for(i = 0; i < length; i++)
2296         out[i] = (*buffer)[i];
2297
2298     *buffer += length;
2299
2300     out[i] = '\0';
2301
2302     return out;
2303 }
2304
2305 /* returns in each call next key, at end of object returns NULL */
2306 /* need to decode value of key after call */
2307 static char *
2308 amf_decode_object( uint8_t **buffer )
2309 {
2310     if( **buffer == 0x0 && *(*buffer + 1) == 0x00 && *(*buffer + 2) == 0x09)
2311     {
2312         *buffer += 3;
2313
2314         return NULL;
2315     }
2316     else
2317         return amf_decode_string( buffer );
2318 }
2319
2320 /*****************************************************************************
2321  * FLV rebuilding implementation:
2322  ******************************************************************************/
2323 static void
2324 flv_rebuild( rtmp_control_thread_t *p_thread, rtmp_packet_t *rtmp_packet )
2325 {
2326     uint32_t length_tag, timestamp;
2327     uint8_t *tmp;
2328
2329     tmp = (uint8_t *) realloc( rtmp_packet->body->body,
2330                                rtmp_packet->body->length_body +
2331                                FLV_TAG_PREVIOUS_TAG_SIZE + FLV_TAG_SIZE );
2332     if( !tmp ) return;
2333     rtmp_packet->body->body = tmp;
2334     memmove( rtmp_packet->body->body + FLV_TAG_PREVIOUS_TAG_SIZE + FLV_TAG_SIZE,
2335              rtmp_packet->body->body, rtmp_packet->body->length_body );
2336
2337     /* Insert tag */
2338     p_thread->flv_tag_previous_tag_size = hton32( p_thread->flv_tag_previous_tag_size );
2339     memcpy( rtmp_packet->body->body, &p_thread->flv_tag_previous_tag_size, sizeof( uint32_t ) );
2340
2341     /* Fill backwards because of overlapping*/
2342     rtmp_packet->body->body[11] = 0x00;
2343
2344     timestamp = hton32( rtmp_packet->timestamp );
2345     memcpy( rtmp_packet->body->body + 7, &timestamp, sizeof( uint32_t ) );
2346
2347     length_tag = hton32( rtmp_packet->body->length_body );
2348     memcpy( rtmp_packet->body->body + 4, &length_tag, sizeof( uint32_t ) );
2349
2350     rtmp_packet->body->body[4] = rtmp_packet->content_type;
2351
2352     rtmp_packet->body->body[12] = 0x00;
2353     rtmp_packet->body->body[13] = 0x00;
2354     rtmp_packet->body->body[14] = 0x00;
2355
2356     p_thread->flv_tag_previous_tag_size = rtmp_packet->body->length_body + FLV_TAG_SIZE;
2357
2358     /* Update size */
2359     rtmp_packet->body->length_body += FLV_TAG_PREVIOUS_TAG_SIZE + FLV_TAG_SIZE;
2360     rtmp_packet->body->length_buffer = rtmp_packet->body->length_body;
2361 }
2362
2363 static void
2364 flv_get_metadata_audio( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_audio, uint8_t *stereo, uint8_t *audiosamplesize, uint32_t *audiosamplerate, uint8_t *audiocodecid )
2365 {
2366     uint8_t data_audio;
2367
2368     data_audio = *packet_audio->body->body;
2369
2370     if( ( data_audio & FLV_AUDIO_STEREO_MASK ) == FLV_AUDIO_STEREO_MONO )
2371         *stereo = FLV_AUDIO_STEREO_MONO;
2372     else if( ( data_audio & FLV_AUDIO_STEREO_MASK ) == FLV_AUDIO_STEREO_STEREO )
2373         *stereo = FLV_AUDIO_STEREO_STEREO;
2374     else
2375         msg_Warn( p_thread, "unknown metadata audio stereo" );
2376
2377     if( ( data_audio & FLV_AUDIO_SIZE_MASK ) == FLV_AUDIO_SIZE_8_BIT )
2378         *audiosamplesize = FLV_AUDIO_SIZE_8_BIT >> 1;
2379     else if( ( data_audio & FLV_AUDIO_SIZE_MASK ) == FLV_AUDIO_SIZE_16_BIT )
2380         *audiosamplesize = FLV_AUDIO_SIZE_16_BIT >> 1;
2381     else
2382         msg_Warn( p_thread, "unknown metadata audio sample size" );
2383
2384     if( ( data_audio & FLV_AUDIO_RATE_MASK ) == FLV_AUDIO_RATE_5_5_KHZ )
2385         *audiosamplerate = 5512;
2386     else if( ( data_audio & FLV_AUDIO_RATE_MASK ) == FLV_AUDIO_RATE_11_KHZ )
2387         *audiosamplerate = 11025;
2388     else if( ( data_audio & FLV_AUDIO_RATE_MASK ) == FLV_AUDIO_RATE_22_KHZ )
2389         *audiosamplerate = 22050;
2390     else if( ( data_audio & FLV_AUDIO_RATE_MASK ) == FLV_AUDIO_RATE_44_KHZ )
2391         *audiosamplerate = 44100;
2392     else
2393         msg_Warn( p_thread, "unknown metadata audio sample rate" );
2394
2395     if( ( data_audio & FLV_AUDIO_CODEC_ID_MASK ) == FLV_AUDIO_CODEC_ID_UNCOMPRESSED )
2396         *audiocodecid = FLV_AUDIO_CODEC_ID_UNCOMPRESSED >> 4;
2397     else if( ( data_audio & FLV_AUDIO_CODEC_ID_MASK ) == FLV_AUDIO_CODEC_ID_ADPCM )
2398         *audiocodecid = FLV_AUDIO_CODEC_ID_ADPCM >> 4;
2399     else if( ( data_audio & FLV_AUDIO_CODEC_ID_MASK ) == FLV_AUDIO_CODEC_ID_MP3 )
2400         *audiocodecid = FLV_AUDIO_CODEC_ID_MP3 >> 4;
2401     else if( ( data_audio & FLV_AUDIO_CODEC_ID_MASK ) == FLV_AUDIO_CODEC_ID_NELLYMOSER_8KHZ_MONO )
2402         *audiocodecid = FLV_AUDIO_CODEC_ID_NELLYMOSER_8KHZ_MONO >> 4;
2403     else if( ( data_audio & FLV_AUDIO_CODEC_ID_MASK ) == FLV_AUDIO_CODEC_ID_NELLYMOSER )
2404         *audiocodecid = FLV_AUDIO_CODEC_ID_NELLYMOSER >> 4;
2405     else
2406         msg_Warn( p_thread, "unknown metadata audio codec id" );
2407 }
2408
2409 static void
2410 flv_get_metadata_video( rtmp_control_thread_t *p_thread, rtmp_packet_t *packet_video, uint8_t *videocodecid, uint8_t *frametype )
2411 {
2412     uint8_t data_video;
2413
2414     data_video = *packet_video->body->body;
2415
2416     if( ( data_video & FLV_VIDEO_CODEC_ID_MASK ) == FLV_VIDEO_CODEC_ID_SORENSEN_H263 )
2417         *videocodecid = FLV_VIDEO_CODEC_ID_SORENSEN_H263;
2418     else if( ( data_video & FLV_VIDEO_CODEC_ID_MASK ) == FLV_VIDEO_CODEC_ID_SCREEN_VIDEO )
2419         *videocodecid = FLV_VIDEO_CODEC_ID_SCREEN_VIDEO;
2420     else if( ( data_video & FLV_VIDEO_CODEC_ID_MASK ) == FLV_VIDEO_CODEC_ID_ON2_VP6 )
2421         *videocodecid = FLV_VIDEO_CODEC_ID_ON2_VP6;
2422     else if( ( data_video & FLV_VIDEO_CODEC_ID_MASK ) == FLV_VIDEO_CODEC_ID_ON2_VP6_ALPHA )
2423         *videocodecid = FLV_VIDEO_CODEC_ID_ON2_VP6_ALPHA;
2424     else if( ( data_video & FLV_VIDEO_CODEC_ID_MASK ) == FLV_VIDEO_CODEC_ID_SCREEN_VIDEO_2 )
2425         *videocodecid = FLV_VIDEO_CODEC_ID_SCREEN_VIDEO_2;
2426     else
2427         msg_Warn( p_thread, "unknown metadata video codec id" );
2428
2429     if( ( data_video & FLV_VIDEO_FRAME_TYPE_MASK ) == FLV_VIDEO_FRAME_TYPE_KEYFRAME )
2430         *frametype = FLV_VIDEO_FRAME_TYPE_KEYFRAME >> 4;
2431     else if( ( data_video & FLV_VIDEO_FRAME_TYPE_MASK ) == FLV_VIDEO_FRAME_TYPE_INTER_FRAME )
2432         *frametype = FLV_VIDEO_FRAME_TYPE_INTER_FRAME >> 4;
2433     else if( ( data_video & FLV_VIDEO_FRAME_TYPE_MASK ) == FLV_VIDEO_FRAME_TYPE_DISPOSABLE_INTER_FRAME )
2434         *frametype = FLV_VIDEO_FRAME_TYPE_DISPOSABLE_INTER_FRAME >> 4;
2435     else
2436         msg_Warn( p_thread, "unknown metadata video frame type" );
2437 }
2438
2439 static rtmp_packet_t *
2440 flv_build_onMetaData( access_t *p_access, uint64_t duration, uint8_t stereo, uint8_t audiosamplesize, uint32_t audiosamplerate, uint8_t audiocodecid, uint8_t videocodecid )
2441 {
2442     rtmp_packet_t *rtmp_packet;
2443     rtmp_body_t *rtmp_body;
2444     uint8_t *tmp_buffer;
2445     double number;
2446
2447     rtmp_body = rtmp_body_new( -1 );
2448
2449     tmp_buffer = amf_encode_element( AMF_DATATYPE_STRING, "onMetaData" );
2450     rtmp_body_append( rtmp_body, tmp_buffer,
2451         AMF_DATATYPE_SIZE_STRING + strlen( "onMetaData" ) );
2452     free( tmp_buffer );
2453
2454     number = 0;
2455     tmp_buffer = amf_encode_element( AMF_DATATYPE_MIXED_ARRAY, &number );
2456     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_MIXED_ARRAY );
2457     free( tmp_buffer );
2458
2459     number = duration;
2460     tmp_buffer = amf_encode_object_variable( "duration",
2461         AMF_DATATYPE_NUMBER, &number );
2462     rtmp_body_append( rtmp_body, tmp_buffer,
2463         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "duration" ) +
2464         AMF_DATATYPE_SIZE_NUMBER );
2465     free( tmp_buffer );
2466
2467     tmp_buffer = amf_encode_object_variable( "stereo",
2468         AMF_DATATYPE_BOOLEAN, &stereo );
2469     rtmp_body_append( rtmp_body, tmp_buffer,
2470         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "stereo" ) +
2471         AMF_DATATYPE_SIZE_BOOLEAN );
2472     free( tmp_buffer );
2473
2474     number = audiosamplesize;
2475     tmp_buffer = amf_encode_object_variable( "audiosamplesize",
2476         AMF_DATATYPE_NUMBER, &number );
2477     rtmp_body_append( rtmp_body, tmp_buffer,
2478         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "audiosamplesize" ) +
2479         AMF_DATATYPE_SIZE_NUMBER );
2480     free( tmp_buffer );
2481
2482     number = audiosamplerate;
2483     tmp_buffer = amf_encode_object_variable( "audiosamplerate",
2484         AMF_DATATYPE_NUMBER, &number );
2485     rtmp_body_append( rtmp_body, tmp_buffer,
2486         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "audiosamplerate" ) +
2487         AMF_DATATYPE_SIZE_NUMBER );
2488     free( tmp_buffer );
2489
2490     number = audiocodecid;
2491     tmp_buffer = amf_encode_object_variable( "audiocodecid",
2492         AMF_DATATYPE_NUMBER, &number );
2493     rtmp_body_append( rtmp_body, tmp_buffer,
2494         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "audiocodecid" ) +
2495         AMF_DATATYPE_SIZE_NUMBER );
2496     free( tmp_buffer );
2497
2498     number = videocodecid;
2499     tmp_buffer = amf_encode_object_variable( "videocodecid",
2500         AMF_DATATYPE_NUMBER, &number );
2501     rtmp_body_append( rtmp_body, tmp_buffer,
2502         AMF_DATATYPE_SIZE_OBJECT_VARIABLE + strlen( "videocodecid" ) +
2503         AMF_DATATYPE_SIZE_NUMBER );
2504     free( tmp_buffer );
2505
2506     tmp_buffer = amf_encode_element( AMF_DATATYPE_END_OF_OBJECT, NULL );
2507     rtmp_body_append( rtmp_body, tmp_buffer, AMF_DATATYPE_SIZE_END_OF_OBJECT );
2508     free( tmp_buffer );
2509
2510     rtmp_packet = rtmp_new_packet( p_access->p_sys->p_thread, RTMP_DEFAULT_STREAM_INDEX_INVOKE,
2511         0, RTMP_CONTENT_TYPE_NOTIFY, 0, rtmp_body );
2512     free( rtmp_body->body );
2513     free( rtmp_body );
2514
2515     return rtmp_packet;
2516 }
2517
2518 block_t *
2519 flv_get_metadata( access_t *p_access )
2520 {
2521     access_sys_t *p_sys = p_access->p_sys;
2522     rtmp_packet_t *flv_metadata_packet;
2523     block_t *p_buffer;
2524
2525     flv_metadata_packet = flv_build_onMetaData( p_access, 0, p_sys->p_thread->metadata_stereo,
2526         p_sys->p_thread->metadata_samplesize, p_sys->p_thread->metadata_samplerate,
2527         p_sys->p_thread->metadata_audiocodecid, p_sys->p_thread->metadata_videocodecid );
2528     flv_rebuild( p_sys->p_thread, flv_metadata_packet );
2529     p_buffer = rtmp_new_block( p_sys->p_thread, flv_metadata_packet->body->body, flv_metadata_packet->body->length_buffer );
2530
2531     free( flv_metadata_packet->body->body );
2532     free( flv_metadata_packet->body );
2533     free( flv_metadata_packet );
2534
2535     return p_buffer;
2536 }
2537
2538 block_t *
2539 flv_insert_header( access_t *p_access, block_t *first_packet )
2540 {
2541     access_sys_t *p_sys = p_access->p_sys;
2542     int old_buffer_size;
2543     uint32_t tmp_number;
2544
2545     old_buffer_size = first_packet->i_buffer;
2546
2547     first_packet = block_Realloc( first_packet, 0, first_packet->i_buffer + FLV_HEADER_SIZE );
2548
2549     memmove( first_packet->p_buffer + FLV_HEADER_SIZE,
2550         first_packet->p_buffer, old_buffer_size );
2551
2552     memcpy( first_packet->p_buffer, FLV_HEADER_SIGNATURE, sizeof( FLV_HEADER_SIGNATURE ) );
2553     first_packet->p_buffer[3] = FLV_HEADER_VERSION;
2554     if( p_sys->p_thread->has_audio && p_sys->p_thread->has_video )
2555         first_packet->p_buffer[4] = FLV_HEADER_AUDIO | FLV_HEADER_VIDEO;
2556     else if( p_sys->p_thread->has_audio )
2557         first_packet->p_buffer[4] = FLV_HEADER_AUDIO;
2558     else
2559         first_packet->p_buffer[4] = FLV_HEADER_VIDEO;
2560     tmp_number = hton32( FLV_HEADER_SIZE );
2561     memcpy( first_packet->p_buffer + 5, &tmp_number, sizeof( uint32_t ) );
2562
2563     return first_packet;
2564 }