rtmp_amf_flv.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:91k
源码类别:

midi

开发平台:

Unix_Linux

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