| OLD | NEW |
| 1 /* | 1 /* |
| 2 * MMS protocol over TCP | 2 * MMS protocol over TCP |
| 3 * Copyright (c) 2006,2007 Ryan Martell | 3 * Copyright (c) 2006,2007 Ryan Martell |
| 4 * Copyright (c) 2007 Björn Axelsson | 4 * Copyright (c) 2007 Björn Axelsson |
| 5 * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com> | 5 * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com> |
| 6 * | 6 * |
| 7 * This file is part of FFmpeg. | 7 * This file is part of FFmpeg. |
| 8 * | 8 * |
| 9 * FFmpeg is free software; you can redistribute it and/or | 9 * FFmpeg is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 */ | 22 */ |
| 23 | 23 |
| 24 /* References | 24 /* References |
| 25 * MMS protocol specification: | 25 * MMS protocol specification: |
| 26 * [1]http://msdn.microsoft.com/en-us/library/cc234711(PROT.10).aspx | 26 * [1]http://msdn.microsoft.com/en-us/library/cc234711(PROT.10).aspx |
| 27 * ASF specification. Revision 01.20.03. | 27 * ASF specification. Revision 01.20.03. |
| 28 * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx | 28 * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "avformat.h" | 31 #include "avformat.h" |
| 32 #include "mms.h" |
| 32 #include "internal.h" | 33 #include "internal.h" |
| 33 #include "libavutil/intreadwrite.h" | 34 #include "libavutil/intreadwrite.h" |
| 34 #include "libavcodec/bytestream.h" | 35 #include "libavcodec/bytestream.h" |
| 35 #include "network.h" | 36 #include "network.h" |
| 36 #include "asf.h" | 37 #include "asf.h" |
| 37 | 38 |
| 38 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip addres
s. | 39 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip addres
s. |
| 39 #define LOCAL_PORT 1037 // as above. | 40 #define LOCAL_PORT 1037 // as above. |
| 40 /** Client to server packet types. */ | 41 /** Client to server packet types. */ |
| 41 typedef enum { | 42 typedef enum { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 /*@}*/ | 78 /*@}*/ |
| 78 | 79 |
| 79 /** Data packets. */ | 80 /** Data packets. */ |
| 80 /*@{*/ | 81 /*@{*/ |
| 81 SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in ca
se of | 82 SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in ca
se of |
| 82 SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets. | 83 SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets. |
| 83 /*@}*/ | 84 /*@}*/ |
| 84 } MMSSCPacketType; | 85 } MMSSCPacketType; |
| 85 | 86 |
| 86 typedef struct { | 87 typedef struct { |
| 87 int id; | 88 MMSContext mms; |
| 88 }MMSStream; | |
| 89 | |
| 90 typedef struct { | |
| 91 int outgoing_packet_seq; ///< Outgoing packet sequence number. | 89 int outgoing_packet_seq; ///< Outgoing packet sequence number. |
| 92 char path[256]; ///< Path of the resource being asked f
or. | 90 char path[256]; ///< Path of the resource being asked f
or. |
| 93 char host[128]; ///< Host of the resources. | 91 char host[128]; ///< Host of the resources. |
| 94 | |
| 95 URLContext *mms_hd; ///< TCP connection handle | |
| 96 MMSStream streams[MAX_STREAMS]; | |
| 97 | |
| 98 /** Buffer for outgoing packets. */ | |
| 99 /*@{*/ | |
| 100 uint8_t *write_out_ptr; ///< Pointer for writting the buffer. | |
| 101 uint8_t out_buffer[512]; ///< Buffer for outgoing packet. | |
| 102 /*@}*/ | |
| 103 | |
| 104 /** Buffer for incoming packets. */ | |
| 105 /*@{*/ | |
| 106 uint8_t in_buffer[8192]; ///< Buffer for incoming packets. | |
| 107 uint8_t *read_in_ptr; ///< Pointer for reading from incoming
buffer. | |
| 108 int remaining_in_len; ///< Reading length from incoming buffe
r. | |
| 109 /*@}*/ | |
| 110 | |
| 111 int incoming_packet_seq; ///< Incoming packet sequence number. | 92 int incoming_packet_seq; ///< Incoming packet sequence number. |
| 112 int incoming_flags; ///< Incoming packet flags. | 93 int incoming_flags; ///< Incoming packet flags. |
| 113 | |
| 114 int packet_id; ///< Identifier for packets in the curr
ent stream. | 94 int packet_id; ///< Identifier for packets in the curr
ent stream. |
| 115 unsigned int header_packet_id; ///< default is 2. | 95 unsigned int header_packet_id; ///< default is 2. |
| 116 | 96 } MMSTContext; |
| 117 /** Internal handling of the ASF header */ | |
| 118 /*@{*/ | |
| 119 uint8_t *asf_header; ///< Stored ASF header. | |
| 120 int asf_header_size; ///< Size of stored ASF header. | |
| 121 int header_parsed; ///< The header has been received and p
arsed. | |
| 122 int asf_packet_len; | |
| 123 int asf_header_read_size; | |
| 124 /*@}*/ | |
| 125 | |
| 126 int stream_num; ///< stream numbers. | |
| 127 } MMSContext; | |
| 128 | 97 |
| 129 /** Create MMST command packet header */ | 98 /** Create MMST command packet header */ |
| 130 static void start_command_packet(MMSContext *mms, MMSCSPacketType packet_type) | 99 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type) |
| 131 { | 100 { |
| 101 MMSContext *mms = &mmst->mms; |
| 132 mms->write_out_ptr = mms->out_buffer; | 102 mms->write_out_ptr = mms->out_buffer; |
| 133 | 103 |
| 134 bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence | 104 bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence |
| 135 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface); | 105 bytestream_put_le32(&mms->write_out_ptr, 0xb00bface); |
| 136 bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the
protocol type bytes | 106 bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the
protocol type bytes |
| 137 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); | 107 bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' ')); |
| 138 bytestream_put_le32(&mms->write_out_ptr, 0); | 108 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 139 bytestream_put_le32(&mms->write_out_ptr, mms->outgoing_packet_seq++); | 109 bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++); |
| 140 bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp | 110 bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp |
| 141 bytestream_put_le32(&mms->write_out_ptr, 0); | 111 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 142 bytestream_put_le16(&mms->write_out_ptr, packet_type); | 112 bytestream_put_le16(&mms->write_out_ptr, packet_type); |
| 143 bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server | 113 bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server |
| 144 } | 114 } |
| 145 | 115 |
| 146 /** Add prefixes to MMST command packet. */ | 116 /** Add prefixes to MMST command packet. */ |
| 147 static void insert_command_prefixes(MMSContext *mms, | 117 static void insert_command_prefixes(MMSContext *mms, |
| 148 uint32_t prefix1, uint32_t prefix2) | 118 uint32_t prefix1, uint32_t prefix2) |
| 149 { | 119 { |
| 150 bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix | 120 bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix |
| 151 bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix | 121 bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix |
| 152 } | 122 } |
| 153 | 123 |
| 154 /** Send a prepared MMST command packet. */ | 124 /** Send a prepared MMST command packet. */ |
| 155 static int send_command_packet(MMSContext *mms) | 125 static int send_command_packet(MMSTContext *mmst) |
| 156 { | 126 { |
| 127 MMSContext *mms = &mmst->mms; |
| 157 int len= mms->write_out_ptr - mms->out_buffer; | 128 int len= mms->write_out_ptr - mms->out_buffer; |
| 158 int exact_length = (len + 7) & ~7; | 129 int exact_length = FFALIGN(len, 8); |
| 159 int first_length= exact_length - 16; | 130 int first_length= exact_length - 16; |
| 160 int len8= first_length/8; | 131 int len8= first_length/8; |
| 161 int write_result; | 132 int write_result; |
| 162 | 133 |
| 163 // update packet length fields. | 134 // update packet length fields. |
| 164 AV_WL32(mms->out_buffer + 8, first_length); | 135 AV_WL32(mms->out_buffer + 8, first_length); |
| 165 AV_WL32(mms->out_buffer + 16, len8); | 136 AV_WL32(mms->out_buffer + 16, len8); |
| 166 AV_WL32(mms->out_buffer + 32, len8-2); | 137 AV_WL32(mms->out_buffer + 32, len8-2); |
| 167 memset(mms->write_out_ptr, 0, exact_length - len); | 138 memset(mms->write_out_ptr, 0, exact_length - len); |
| 168 | 139 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 185 ByteIOContext bic; | 156 ByteIOContext bic; |
| 186 int size = mms->write_out_ptr - mms->out_buffer; | 157 int size = mms->write_out_ptr - mms->out_buffer; |
| 187 int len; | 158 int len; |
| 188 init_put_byte(&bic, mms->write_out_ptr, | 159 init_put_byte(&bic, mms->write_out_ptr, |
| 189 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL); | 160 sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL); |
| 190 | 161 |
| 191 len = ff_put_str16_nolen(&bic, src); | 162 len = ff_put_str16_nolen(&bic, src); |
| 192 mms->write_out_ptr += len; | 163 mms->write_out_ptr += len; |
| 193 } | 164 } |
| 194 | 165 |
| 195 static int send_time_test_data(MMSContext *mms) | 166 static int send_time_test_data(MMSTContext *mmst) |
| 196 { | 167 { |
| 197 start_command_packet(mms, CS_PKT_TIMING_DATA_REQUEST); | 168 start_command_packet(mmst, CS_PKT_TIMING_DATA_REQUEST); |
| 198 insert_command_prefixes(mms, 0xf0f0f0f1, 0x0004000b); | 169 insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b); |
| 199 return send_command_packet(mms); | 170 return send_command_packet(mmst); |
| 200 } | 171 } |
| 201 | 172 |
| 202 static int send_protocol_select(MMSContext *mms) | 173 static int send_protocol_select(MMSTContext *mmst) |
| 203 { | 174 { |
| 204 char data_string[256]; | 175 char data_string[256]; |
| 176 MMSContext *mms = &mmst->mms; |
| 205 | 177 |
| 206 start_command_packet(mms, CS_PKT_PROTOCOL_SELECT); | 178 start_command_packet(mmst, CS_PKT_PROTOCOL_SELECT); |
| 207 insert_command_prefixes(mms, 0, 0xffffffff); | 179 insert_command_prefixes(mms, 0, 0xffffffff); |
| 208 bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes | 180 bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes |
| 209 bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate | 181 bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate |
| 210 bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode | 182 bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode |
| 211 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d", | 183 snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d", |
| 212 (LOCAL_ADDRESS>>24)&0xff, | 184 (LOCAL_ADDRESS>>24)&0xff, |
| 213 (LOCAL_ADDRESS>>16)&0xff, | 185 (LOCAL_ADDRESS>>16)&0xff, |
| 214 (LOCAL_ADDRESS>>8)&0xff, | 186 (LOCAL_ADDRESS>>8)&0xff, |
| 215 LOCAL_ADDRESS&0xff, | 187 LOCAL_ADDRESS&0xff, |
| 216 "TCP", // or UDP | 188 "TCP", // or UDP |
| 217 LOCAL_PORT); | 189 LOCAL_PORT); |
| 218 | 190 |
| 219 mms_put_utf16(mms, data_string); | 191 mms_put_utf16(mms, data_string); |
| 220 return send_command_packet(mms); | 192 return send_command_packet(mmst); |
| 221 } | 193 } |
| 222 | 194 |
| 223 static int send_media_file_request(MMSContext *mms) | 195 static int send_media_file_request(MMSTContext *mmst) |
| 224 { | 196 { |
| 225 start_command_packet(mms, CS_PKT_MEDIA_FILE_REQUEST); | 197 MMSContext *mms = &mmst->mms; |
| 198 start_command_packet(mmst, CS_PKT_MEDIA_FILE_REQUEST); |
| 226 insert_command_prefixes(mms, 1, 0xffffffff); | 199 insert_command_prefixes(mms, 1, 0xffffffff); |
| 227 bytestream_put_le32(&mms->write_out_ptr, 0); | 200 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 228 bytestream_put_le32(&mms->write_out_ptr, 0); | 201 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 229 mms_put_utf16(mms, mms->path + 1); // +1 for skip "/" | 202 mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/" |
| 230 | 203 |
| 231 return send_command_packet(mms); | 204 return send_command_packet(mmst); |
| 232 } | 205 } |
| 233 | 206 |
| 234 static void handle_packet_stream_changing_type(MMSContext *mms) | 207 static void handle_packet_stream_changing_type(MMSTContext *mmst) |
| 235 { | 208 { |
| 209 MMSContext *mms = &mmst->mms; |
| 236 dprintf(NULL, "Stream changing!\n"); | 210 dprintf(NULL, "Stream changing!\n"); |
| 237 | 211 |
| 238 // 40 is the packet header size, 7 is the prefix size. | 212 // 40 is the packet header size, 7 is the prefix size. |
| 239 mms->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); | 213 mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7); |
| 240 dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id); | 214 dprintf(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id); |
| 241 } | 215 } |
| 242 | 216 |
| 243 static int send_keepalive_packet(MMSContext *mms) | 217 static int send_keepalive_packet(MMSTContext *mmst) |
| 244 { | 218 { |
| 245 // respond to a keepalive with a keepalive... | 219 // respond to a keepalive with a keepalive... |
| 246 start_command_packet(mms, CS_PKT_KEEPALIVE); | 220 start_command_packet(mmst, CS_PKT_KEEPALIVE); |
| 247 insert_command_prefixes(mms, 1, 0x100FFFF); | 221 insert_command_prefixes(&mmst->mms, 1, 0x100FFFF); |
| 248 return send_command_packet(mms); | 222 return send_command_packet(mmst); |
| 249 } | 223 } |
| 250 | 224 |
| 251 /** Pad media packets smaller than max_packet_size and/or adjust read position | 225 /** Pad media packets smaller than max_packet_size and/or adjust read position |
| 252 * after a seek. */ | 226 * after a seek. */ |
| 253 static void pad_media_packet(MMSContext *mms) | 227 static void pad_media_packet(MMSContext *mms) |
| 254 { | 228 { |
| 255 if(mms->remaining_in_len<mms->asf_packet_len) { | 229 if(mms->remaining_in_len<mms->asf_packet_len) { |
| 256 int padding_size = mms->asf_packet_len - mms->remaining_in_len; | 230 int padding_size = mms->asf_packet_len - mms->remaining_in_len; |
| 257 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size); | 231 memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size); |
| 258 mms->remaining_in_len += padding_size; | 232 mms->remaining_in_len += padding_size; |
| 259 } | 233 } |
| 260 } | 234 } |
| 261 | 235 |
| 262 /** Read incoming MMST media, header or command packet. */ | 236 /** Read incoming MMST media, header or command packet. */ |
| 263 static MMSSCPacketType get_tcp_server_response(MMSContext *mms) | 237 static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) |
| 264 { | 238 { |
| 265 int read_result; | 239 int read_result; |
| 266 MMSSCPacketType packet_type= -1; | 240 MMSSCPacketType packet_type= -1; |
| 267 | 241 MMSContext *mms = &mmst->mms; |
| 268 for(;;) { | 242 for(;;) { |
| 269 read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); | 243 read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); |
| 270 if (read_result != 8) { | 244 if (read_result != 8) { |
| 271 if(read_result < 0) { | 245 if(read_result < 0) { |
| 272 av_log(NULL, AV_LOG_ERROR, | 246 av_log(NULL, AV_LOG_ERROR, |
| 273 "Error reading packet header: %d (%s)\n", | 247 "Error reading packet header: %d (%s)\n", |
| 274 read_result, strerror(read_result)); | 248 read_result, strerror(read_result)); |
| 275 packet_type = SC_PKT_CANCEL; | 249 packet_type = SC_PKT_CANCEL; |
| 276 } else { | 250 } else { |
| 277 av_log(NULL, AV_LOG_ERROR, | 251 av_log(NULL, AV_LOG_ERROR, |
| 278 "The server closed the connection\n"); | 252 "The server closed the connection\n"); |
| 279 packet_type = SC_PKT_NO_DATA; | 253 packet_type = SC_PKT_NO_DATA; |
| 280 } | 254 } |
| 281 return packet_type; | 255 return packet_type; |
| 282 } | 256 } |
| 283 | 257 |
| 284 // handle command packet. | 258 // handle command packet. |
| 285 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { | 259 if(AV_RL32(mms->in_buffer + 4)==0xb00bface) { |
| 286 int length_remaining, hr; | 260 int length_remaining, hr; |
| 287 | 261 |
| 288 mms->incoming_flags= mms->in_buffer[3]; | 262 mmst->incoming_flags= mms->in_buffer[3]; |
| 289 read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); | 263 read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); |
| 290 if(read_result != 4) { | 264 if(read_result != 4) { |
| 291 av_log(NULL, AV_LOG_ERROR, | 265 av_log(NULL, AV_LOG_ERROR, |
| 292 "Reading command packet length failed: %d (%s)\n", | 266 "Reading command packet length failed: %d (%s)\n", |
| 293 read_result, | 267 read_result, |
| 294 read_result < 0 ? strerror(read_result) : | 268 read_result < 0 ? strerror(read_result) : |
| 295 "The server closed the connection"); | 269 "The server closed the connection"); |
| 296 return read_result < 0 ? read_result : AVERROR_IO; | 270 return read_result < 0 ? read_result : AVERROR_IO; |
| 297 } | 271 } |
| 298 | 272 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 325 } | 299 } |
| 326 } else { | 300 } else { |
| 327 int length_remaining; | 301 int length_remaining; |
| 328 int packet_id_type; | 302 int packet_id_type; |
| 329 int tmp; | 303 int tmp; |
| 330 | 304 |
| 331 // note we cache the first 8 bytes, | 305 // note we cache the first 8 bytes, |
| 332 // then fill up the buffer with the others | 306 // then fill up the buffer with the others |
| 333 tmp = AV_RL16(mms->in_buffer + 6); | 307 tmp = AV_RL16(mms->in_buffer + 6); |
| 334 length_remaining = (tmp - 8) & 0xffff; | 308 length_remaining = (tmp - 8) & 0xffff; |
| 335 mms->incoming_packet_seq = AV_RL32(mms->in_buffer); | 309 mmst->incoming_packet_seq = AV_RL32(mms->in_buffer); |
| 336 packet_id_type = mms->in_buffer[4]; | 310 packet_id_type = mms->in_buffer[4]; |
| 337 mms->incoming_flags = mms->in_buffer[5]; | 311 mmst->incoming_flags = mms->in_buffer[5]; |
| 338 | 312 |
| 339 if (length_remaining < 0 | 313 if (length_remaining < 0 |
| 340 || length_remaining > sizeof(mms->in_buffer) - 8) { | 314 || length_remaining > sizeof(mms->in_buffer) - 8) { |
| 341 av_log(NULL, AV_LOG_ERROR, | 315 av_log(NULL, AV_LOG_ERROR, |
| 342 "Data length %d is invalid or too large (max=%zu)\n", | 316 "Data length %d is invalid or too large (max=%zu)\n", |
| 343 length_remaining, sizeof(mms->in_buffer)); | 317 length_remaining, sizeof(mms->in_buffer)); |
| 344 return AVERROR_INVALIDDATA; | 318 return AVERROR_INVALIDDATA; |
| 345 } | 319 } |
| 346 mms->remaining_in_len = length_remaining; | 320 mms->remaining_in_len = length_remaining; |
| 347 mms->read_in_ptr = mms->in_buffer; | 321 mms->read_in_ptr = mms->in_buffer; |
| 348 read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_r
emaining); | 322 read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_r
emaining); |
| 349 if(read_result != length_remaining) { | 323 if(read_result != length_remaining) { |
| 350 av_log(NULL, AV_LOG_ERROR, | 324 av_log(NULL, AV_LOG_ERROR, |
| 351 "Failed to read packet data of size %d: %d (%s)\n", | 325 "Failed to read packet data of size %d: %d (%s)\n", |
| 352 length_remaining, read_result, | 326 length_remaining, read_result, |
| 353 read_result < 0 ? strerror(read_result) : | 327 read_result < 0 ? strerror(read_result) : |
| 354 "The server closed the connection"); | 328 "The server closed the connection"); |
| 355 return read_result < 0 ? read_result : AVERROR_IO; | 329 return read_result < 0 ? read_result : AVERROR_IO; |
| 356 } | 330 } |
| 357 | 331 |
| 358 // if we successfully read everything. | 332 // if we successfully read everything. |
| 359 if(packet_id_type == mms->header_packet_id) { | 333 if(packet_id_type == mmst->header_packet_id) { |
| 360 packet_type = SC_PKT_ASF_HEADER; | 334 packet_type = SC_PKT_ASF_HEADER; |
| 361 // Store the asf header | 335 // Store the asf header |
| 362 if(!mms->header_parsed) { | 336 if(!mms->header_parsed) { |
| 363 void *p = av_realloc(mms->asf_header, | 337 void *p = av_realloc(mms->asf_header, |
| 364 mms->asf_header_size + mms->remaining_in_len); | 338 mms->asf_header_size + mms->remaining_in_len); |
| 365 if (!p) { | 339 if (!p) { |
| 366 av_freep(&mms->asf_header); | 340 av_freep(&mms->asf_header); |
| 367 return AVERROR(ENOMEM); | 341 return AVERROR(ENOMEM); |
| 368 } | 342 } |
| 369 mms->asf_header = p; | 343 mms->asf_header = p; |
| 370 memcpy(mms->asf_header + mms->asf_header_size, | 344 memcpy(mms->asf_header + mms->asf_header_size, |
| 371 mms->read_in_ptr, mms->remaining_in_len); | 345 mms->read_in_ptr, mms->remaining_in_len); |
| 372 mms->asf_header_size += mms->remaining_in_len; | 346 mms->asf_header_size += mms->remaining_in_len; |
| 373 } | 347 } |
| 374 // 0x04 means asf header is sent in multiple packets. | 348 // 0x04 means asf header is sent in multiple packets. |
| 375 if (mms->incoming_flags == 0x04) | 349 if (mmst->incoming_flags == 0x04) |
| 376 continue; | 350 continue; |
| 377 } else if(packet_id_type == mms->packet_id) { | 351 } else if(packet_id_type == mmst->packet_id) { |
| 378 packet_type = SC_PKT_ASF_MEDIA; | 352 packet_type = SC_PKT_ASF_MEDIA; |
| 379 } else { | 353 } else { |
| 380 dprintf(NULL, "packet id type %d is old.", packet_id_type); | 354 dprintf(NULL, "packet id type %d is old.", packet_id_type); |
| 381 continue; | 355 continue; |
| 382 } | 356 } |
| 383 } | 357 } |
| 384 | 358 |
| 385 // preprocess some packet type | 359 // preprocess some packet type |
| 386 if(packet_type == SC_PKT_KEEPALIVE) { | 360 if(packet_type == SC_PKT_KEEPALIVE) { |
| 387 send_keepalive_packet(mms); | 361 send_keepalive_packet(mmst); |
| 388 continue; | 362 continue; |
| 389 } else if(packet_type == SC_PKT_STREAM_CHANGING) { | 363 } else if(packet_type == SC_PKT_STREAM_CHANGING) { |
| 390 handle_packet_stream_changing_type(mms); | 364 handle_packet_stream_changing_type(mmst); |
| 391 } else if(packet_type == SC_PKT_ASF_MEDIA) { | 365 } else if(packet_type == SC_PKT_ASF_MEDIA) { |
| 392 pad_media_packet(mms); | 366 pad_media_packet(mms); |
| 393 } | 367 } |
| 394 return packet_type; | 368 return packet_type; |
| 395 } | 369 } |
| 396 } | 370 } |
| 397 | 371 |
| 398 static int mms_safe_send_recv(MMSContext *mms, | 372 static int mms_safe_send_recv(MMSTContext *mmst, |
| 399 int (*send_fun)(MMSContext *mms), | 373 int (*send_fun)(MMSTContext *mmst), |
| 400 const MMSSCPacketType expect_type) | 374 const MMSSCPacketType expect_type) |
| 401 { | 375 { |
| 402 MMSSCPacketType type; | 376 MMSSCPacketType type; |
| 403 if(send_fun) { | 377 if(send_fun) { |
| 404 int ret = send_fun(mms); | 378 int ret = send_fun(mmst); |
| 405 if (ret < 0) { | 379 if (ret < 0) { |
| 406 dprintf(NULL, "Send Packet error before expecting recv packet %d\n",
expect_type); | 380 dprintf(NULL, "Send Packet error before expecting recv packet %d\n",
expect_type); |
| 407 return ret; | 381 return ret; |
| 408 } | 382 } |
| 409 } | 383 } |
| 410 | 384 |
| 411 if ((type = get_tcp_server_response(mms)) != expect_type) { | 385 if ((type = get_tcp_server_response(mmst)) != expect_type) { |
| 412 av_log(NULL, AV_LOG_ERROR, | 386 av_log(NULL, AV_LOG_ERROR, |
| 413 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", | 387 "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n", |
| 414 type, expect_type); | 388 type, expect_type); |
| 415 return AVERROR_INVALIDDATA; | 389 return AVERROR_INVALIDDATA; |
| 416 } else { | 390 } else { |
| 417 return 0; | 391 return 0; |
| 418 } | 392 } |
| 419 } | 393 } |
| 420 | 394 |
| 421 static int send_media_header_request(MMSContext *mms) | 395 static int send_media_header_request(MMSTContext *mmst) |
| 422 { | 396 { |
| 423 start_command_packet(mms, CS_PKT_MEDIA_HEADER_REQUEST); | 397 MMSContext *mms = &mmst->mms; |
| 398 start_command_packet(mmst, CS_PKT_MEDIA_HEADER_REQUEST); |
| 424 insert_command_prefixes(mms, 1, 0); | 399 insert_command_prefixes(mms, 1, 0); |
| 425 bytestream_put_le32(&mms->write_out_ptr, 0); | 400 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 426 bytestream_put_le32(&mms->write_out_ptr, 0x00800000); | 401 bytestream_put_le32(&mms->write_out_ptr, 0x00800000); |
| 427 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); | 402 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); |
| 428 bytestream_put_le32(&mms->write_out_ptr, 0); | 403 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 429 bytestream_put_le32(&mms->write_out_ptr, 0); | 404 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 430 bytestream_put_le32(&mms->write_out_ptr, 0); | 405 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 431 | 406 |
| 432 // the media preroll value in milliseconds? | 407 // the media preroll value in milliseconds? |
| 433 bytestream_put_le32(&mms->write_out_ptr, 0); | 408 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 434 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000); | 409 bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000); |
| 435 bytestream_put_le32(&mms->write_out_ptr, 2); | 410 bytestream_put_le32(&mms->write_out_ptr, 2); |
| 436 bytestream_put_le32(&mms->write_out_ptr, 0); | 411 bytestream_put_le32(&mms->write_out_ptr, 0); |
| 437 | 412 |
| 438 return send_command_packet(mms); | 413 return send_command_packet(mmst); |
| 439 } | 414 } |
| 440 | 415 |
| 441 /** Send the initial handshake. */ | 416 /** Send the initial handshake. */ |
| 442 static int send_startup_packet(MMSContext *mms) | 417 static int send_startup_packet(MMSTContext *mmst) |
| 443 { | 418 { |
| 444 char data_string[256]; | 419 char data_string[256]; |
| 420 MMSContext *mms = &mmst->mms; |
| 445 // SubscriberName is defined in MS specification linked below. | 421 // SubscriberName is defined in MS specification linked below. |
| 446 // The guid value can be any valid value. | 422 // The guid value can be any valid value. |
| 447 // http://download.microsoft.com/ | 423 // http://download.microsoft.com/ |
| 448 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf | 424 // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf |
| 449 snprintf(data_string, sizeof(data_string), | 425 snprintf(data_string, sizeof(data_string), |
| 450 "NSPlayer/7.0.0.1956; {%s}; Host: %s", | 426 "NSPlayer/7.0.0.1956; {%s}; Host: %s", |
| 451 "7E667F5D-A661-495E-A512-F55686DDA178", mms->host); | 427 "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host); |
| 452 | 428 |
| 453 start_command_packet(mms, CS_PKT_INITIAL); | 429 start_command_packet(mmst, CS_PKT_INITIAL); |
| 454 insert_command_prefixes(mms, 0, 0x0004000b); | 430 insert_command_prefixes(mms, 0, 0x0004000b); |
| 455 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); | 431 bytestream_put_le32(&mms->write_out_ptr, 0x0003001c); |
| 456 mms_put_utf16(mms, data_string); | 432 mms_put_utf16(mms, data_string); |
| 457 return send_command_packet(mms); | 433 return send_command_packet(mmst); |
| 458 } | |
| 459 | |
| 460 static int asf_header_parser(MMSContext *mms) | |
| 461 { | |
| 462 uint8_t *p = mms->asf_header; | |
| 463 uint8_t *end; | |
| 464 int flags, stream_id; | |
| 465 mms->stream_num = 0; | |
| 466 | |
| 467 if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 || | |
| 468 memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) { | |
| 469 av_log(NULL, AV_LOG_ERROR, | |
| 470 "Corrupt stream (invalid ASF header, size=%d)\n", | |
| 471 mms->asf_header_size); | |
| 472 return AVERROR_INVALIDDATA; | |
| 473 } | |
| 474 | |
| 475 end = mms->asf_header + mms->asf_header_size; | |
| 476 | |
| 477 p += sizeof(ff_asf_guid) + 14; | |
| 478 while(end - p >= sizeof(ff_asf_guid) + 8) { | |
| 479 uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid)); | |
| 480 if (!chunksize || chunksize > end - p) { | |
| 481 av_log(NULL, AV_LOG_ERROR, | |
| 482 "Corrupt stream (header chunksize %"PRId64" is invalid)\n", | |
| 483 chunksize); | |
| 484 return AVERROR_INVALIDDATA; | |
| 485 } | |
| 486 if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) { | |
| 487 /* read packet size */ | |
| 488 if (end - p > sizeof(ff_asf_guid) * 2 + 68) { | |
| 489 mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64); | |
| 490 if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms
->in_buffer)) { | |
| 491 av_log(NULL, AV_LOG_ERROR, | |
| 492 "Corrupt stream (too large pkt_len %d)\n", | |
| 493 mms->asf_packet_len); | |
| 494 return AVERROR_INVALIDDATA; | |
| 495 } | |
| 496 } | |
| 497 } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) { | |
| 498 flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24); | |
| 499 stream_id = flags & 0x7F; | |
| 500 //The second condition is for checking CS_PKT_STREAM_ID_REQUEST pack
et size, | |
| 501 //we can calcuate the packet size by stream_num. | |
| 502 //Please see function send_stream_selection_request(). | |
| 503 if (mms->stream_num < MAX_STREAMS && | |
| 504 46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) { | |
| 505 mms->streams[mms->stream_num].id = stream_id; | |
| 506 mms->stream_num++; | |
| 507 } else { | |
| 508 av_log(NULL, AV_LOG_ERROR, | |
| 509 "Corrupt stream (too many A/V streams)\n"); | |
| 510 return AVERROR_INVALIDDATA; | |
| 511 } | |
| 512 } else if (!memcmp(p, ff_asf_head1_guid, sizeof(ff_asf_guid))) { | |
| 513 chunksize = 46; // see references [2] section 3.4. This should be se
t 46. | |
| 514 } | |
| 515 p += chunksize; | |
| 516 } | |
| 517 | |
| 518 return 0; | |
| 519 } | 434 } |
| 520 | 435 |
| 521 /** Send MMST stream selection command based on the AVStream->discard values. */ | 436 /** Send MMST stream selection command based on the AVStream->discard values. */ |
| 522 static int send_stream_selection_request(MMSContext *mms) | 437 static int send_stream_selection_request(MMSTContext *mmst) |
| 523 { | 438 { |
| 524 int i; | 439 int i; |
| 525 | 440 MMSContext *mms = &mmst->mms; |
| 526 // send the streams we want back... | 441 // send the streams we want back... |
| 527 start_command_packet(mms, CS_PKT_STREAM_ID_REQUEST); | 442 start_command_packet(mmst, CS_PKT_STREAM_ID_REQUEST); |
| 528 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream
nums | 443 bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream
nums |
| 529 for(i= 0; i<mms->stream_num; i++) { | 444 for(i= 0; i<mms->stream_num; i++) { |
| 530 bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags | 445 bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags |
| 531 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream
id | 446 bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream
id |
| 532 bytestream_put_le16(&mms->write_out_ptr, 0); // select
ion | 447 bytestream_put_le16(&mms->write_out_ptr, 0); // select
ion |
| 533 } | 448 } |
| 534 return send_command_packet(mms); | 449 return send_command_packet(mmst); |
| 535 } | 450 } |
| 536 | 451 |
| 537 static int read_data(MMSContext *mms, uint8_t *buf, const int buf_size) | 452 static int send_close_packet(MMSTContext *mmst) |
| 538 { | 453 { |
| 539 int read_size; | 454 start_command_packet(mmst, CS_PKT_STREAM_CLOSE); |
| 540 read_size = FFMIN(buf_size, mms->remaining_in_len); | 455 insert_command_prefixes(&mmst->mms, 1, 1); |
| 541 memcpy(buf, mms->read_in_ptr, read_size); | |
| 542 mms->remaining_in_len -= read_size; | |
| 543 mms->read_in_ptr += read_size; | |
| 544 return read_size; | |
| 545 } | |
| 546 | 456 |
| 547 static int send_close_packet(MMSContext *mms) | 457 return send_command_packet(mmst); |
| 548 { | |
| 549 start_command_packet(mms, CS_PKT_STREAM_CLOSE); | |
| 550 insert_command_prefixes(mms, 1, 1); | |
| 551 | |
| 552 return send_command_packet(mms); | |
| 553 } | 458 } |
| 554 | 459 |
| 555 /** Close the MMSH/MMST connection */ | 460 /** Close the MMSH/MMST connection */ |
| 556 static int mms_close(URLContext *h) | 461 static int mms_close(URLContext *h) |
| 557 { | 462 { |
| 558 MMSContext *mms = (MMSContext *)h->priv_data; | 463 MMSTContext *mmst = (MMSTContext *)h->priv_data; |
| 559 | 464 MMSContext *mms = &mmst->mms; |
| 560 if(mms->mms_hd) { | 465 if(mms->mms_hd) { |
| 561 send_close_packet(mms); | 466 send_close_packet(mmst); |
| 562 url_close(mms->mms_hd); | 467 url_close(mms->mms_hd); |
| 563 } | 468 } |
| 564 | 469 |
| 565 /* free all separately allocated pointers in mms */ | 470 /* free all separately allocated pointers in mms */ |
| 471 av_free(mms->streams); |
| 566 av_free(mms->asf_header); | 472 av_free(mms->asf_header); |
| 567 av_freep(&h->priv_data); | 473 av_freep(&h->priv_data); |
| 568 | 474 |
| 569 return 0; | 475 return 0; |
| 570 } | 476 } |
| 571 | 477 |
| 572 static int send_media_packet_request(MMSContext *mms) | 478 static int send_media_packet_request(MMSTContext *mmst) |
| 573 { | 479 { |
| 574 start_command_packet(mms, CS_PKT_START_FROM_PKT_ID); | 480 MMSContext *mms = &mmst->mms; |
| 481 start_command_packet(mmst, CS_PKT_START_FROM_PKT_ID); |
| 575 insert_command_prefixes(mms, 1, 0x0001FFFF); | 482 insert_command_prefixes(mms, 1, 0x0001FFFF); |
| 576 bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp | 483 bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp |
| 577 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown | 484 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown |
| 578 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset | 485 bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset |
| 579 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it | 486 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it |
| 580 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it | 487 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it |
| 581 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it | 488 bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time lim
it |
| 582 bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit f
lag | 489 bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit f
lag |
| 583 | 490 |
| 584 mms->packet_id++; // new packet_id | 491 mmst->packet_id++; // new packet_id |
| 585 bytestream_put_le32(&mms->write_out_ptr, mms->packet_id); | 492 bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id); |
| 586 return send_command_packet(mms); | 493 return send_command_packet(mmst); |
| 587 } | 494 } |
| 588 | 495 |
| 589 | 496 |
| 590 static void clear_stream_buffers(MMSContext *mms) | 497 static void clear_stream_buffers(MMSContext *mms) |
| 591 { | 498 { |
| 592 mms->remaining_in_len = 0; | 499 mms->remaining_in_len = 0; |
| 593 mms->read_in_ptr = mms->in_buffer; | 500 mms->read_in_ptr = mms->in_buffer; |
| 594 } | 501 } |
| 595 | 502 |
| 596 static int mms_open(URLContext *h, const char *uri, int flags) | 503 static int mms_open(URLContext *h, const char *uri, int flags) |
| 597 { | 504 { |
| 505 MMSTContext *mmst; |
| 598 MMSContext *mms; | 506 MMSContext *mms; |
| 599 int port, err; | 507 int port, err; |
| 600 char tcpname[256]; | 508 char tcpname[256]; |
| 601 | 509 |
| 602 h->is_streamed = 1; | 510 h->is_streamed = 1; |
| 603 mms = h->priv_data = av_mallocz(sizeof(MMSContext)); | 511 mmst = h->priv_data = av_mallocz(sizeof(MMSTContext)); |
| 604 if (!h->priv_data) | 512 if (!h->priv_data) |
| 605 return AVERROR(ENOMEM); | 513 return AVERROR(ENOMEM); |
| 514 mms = &mmst->mms; |
| 606 | 515 |
| 607 // only for MMS over TCP, so set proto = NULL | 516 // only for MMS over TCP, so set proto = NULL |
| 608 av_url_split(NULL, 0, NULL, 0, | 517 av_url_split(NULL, 0, NULL, 0, |
| 609 mms->host, sizeof(mms->host), &port, mms->path, | 518 mmst->host, sizeof(mmst->host), &port, mmst->path, |
| 610 sizeof(mms->path), uri); | 519 sizeof(mmst->path), uri); |
| 611 | 520 |
| 612 if(port<0) | 521 if(port<0) |
| 613 port = 1755; // defaut mms protocol port | 522 port = 1755; // defaut mms protocol port |
| 614 | 523 |
| 615 // establish tcp connection. | 524 // establish tcp connection. |
| 616 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mms->host, port, NULL); | 525 ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); |
| 617 err = url_open(&mms->mms_hd, tcpname, URL_RDWR); | 526 err = url_open(&mms->mms_hd, tcpname, URL_RDWR); |
| 618 if (err) | 527 if (err) |
| 619 goto fail; | 528 goto fail; |
| 620 | 529 |
| 621 mms->packet_id = 3; // default, initial value. | 530 mmst->packet_id = 3; // default, initial value. |
| 622 mms->header_packet_id = 2; // default, initial value. | 531 mmst->header_packet_id = 2; // default, initial value. |
| 623 err = mms_safe_send_recv(mms, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); | 532 err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); |
| 624 if (err) | 533 if (err) |
| 625 goto fail; | 534 goto fail; |
| 626 err = mms_safe_send_recv(mms, send_time_test_data, SC_PKT_TIMING_TEST_REPLY)
; | 535 err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY
); |
| 627 if (err) | 536 if (err) |
| 628 goto fail; | 537 goto fail; |
| 629 err = mms_safe_send_recv(mms, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED
); | 538 err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTE
D); |
| 630 if (err) | 539 if (err) |
| 631 goto fail; | 540 goto fail; |
| 632 err = mms_safe_send_recv(mms, send_media_file_request, SC_PKT_MEDIA_FILE_DET
AILS); | 541 err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DE
TAILS); |
| 633 if (err) | 542 if (err) |
| 634 goto fail; | 543 goto fail; |
| 635 err = mms_safe_send_recv(mms, send_media_header_request, SC_PKT_HEADER_REQUE
ST_ACCEPTED); | 544 err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQU
EST_ACCEPTED); |
| 636 if (err) | 545 if (err) |
| 637 goto fail; | 546 goto fail; |
| 638 err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_HEADER); | 547 err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER); |
| 639 if (err) | 548 if (err) |
| 640 goto fail; | 549 goto fail; |
| 641 if((mms->incoming_flags != 0X08) && (mms->incoming_flags != 0X0C)) | 550 if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) |
| 642 goto fail; | 551 goto fail; |
| 643 err = asf_header_parser(mms); | 552 err = ff_mms_asf_header_parser(mms); |
| 644 if (err) { | 553 if (err) { |
| 645 dprintf(NULL, "asf header parsed failed!\n"); | 554 dprintf(NULL, "asf header parsed failed!\n"); |
| 646 goto fail; | 555 goto fail; |
| 647 } | 556 } |
| 648 mms->header_parsed = 1; | 557 mms->header_parsed = 1; |
| 649 | 558 |
| 650 if (!mms->asf_packet_len || !mms->stream_num) | 559 if (!mms->asf_packet_len || !mms->stream_num) |
| 651 goto fail; | 560 goto fail; |
| 652 | 561 |
| 653 clear_stream_buffers(mms); | 562 clear_stream_buffers(mms); |
| 654 err = mms_safe_send_recv(mms, send_stream_selection_request, SC_PKT_STREAM_I
D_ACCEPTED); | 563 err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_
ID_ACCEPTED); |
| 655 if (err) | 564 if (err) |
| 656 goto fail; | 565 goto fail; |
| 657 // send media packet request | 566 // send media packet request |
| 658 err = mms_safe_send_recv(mms, send_media_packet_request, SC_PKT_MEDIA_PKT_FO
LLOWS); | 567 err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_F
OLLOWS); |
| 659 if (err) { | 568 if (err) { |
| 660 goto fail; | 569 goto fail; |
| 661 } | 570 } |
| 662 dprintf(NULL, "Leaving open (success)\n"); | 571 dprintf(NULL, "Leaving open (success)\n"); |
| 663 return 0; | 572 return 0; |
| 664 fail: | 573 fail: |
| 665 mms_close(h); | 574 mms_close(h); |
| 666 dprintf(NULL, "Leaving open (failure: %d)\n", err); | 575 dprintf(NULL, "Leaving open (failure: %d)\n", err); |
| 667 return err; | 576 return err; |
| 668 } | 577 } |
| 669 | 578 |
| 670 /** Read ASF data through the protocol. */ | 579 /** Read ASF data through the protocol. */ |
| 671 static int mms_read(URLContext *h, uint8_t *buf, int size) | 580 static int mms_read(URLContext *h, uint8_t *buf, int size) |
| 672 { | 581 { |
| 673 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ | 582 /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */ |
| 674 MMSContext *mms = h->priv_data; | 583 MMSTContext *mmst = h->priv_data; |
| 584 MMSContext *mms = &mmst->mms; |
| 675 int result = 0; | 585 int result = 0; |
| 676 int size_to_copy; | |
| 677 | 586 |
| 678 do { | 587 do { |
| 679 if(mms->asf_header_read_size < mms->asf_header_size) { | 588 if(mms->asf_header_read_size < mms->asf_header_size) { |
| 680 /* Read from ASF header buffer */ | 589 /* Read from ASF header buffer */ |
| 681 size_to_copy= FFMIN(size, | 590 result = ff_mms_read_header(mms, buf, size); |
| 682 mms->asf_header_size - mms->asf_header_read_size
); | |
| 683 memcpy(buf, mms->asf_header + mms->asf_header_read_size, size_to_cop
y); | |
| 684 mms->asf_header_read_size += size_to_copy; | |
| 685 result += size_to_copy; | |
| 686 dprintf(NULL, "Copied %d bytes from stored header. left: %d\n", | |
| 687 size_to_copy, mms->asf_header_size - mms->asf_header_read_siz
e); | |
| 688 if (mms->asf_header_size == mms->asf_header_read_size) { | |
| 689 av_freep(&mms->asf_header); | |
| 690 } | |
| 691 } else if(mms->remaining_in_len) { | 591 } else if(mms->remaining_in_len) { |
| 692 /* Read remaining packet data to buffer. | 592 /* Read remaining packet data to buffer. |
| 693 * the result can not be zero because remaining_in_len is positive.*
/ | 593 * the result can not be zero because remaining_in_len is positive.*
/ |
| 694 result = read_data(mms, buf, size); | 594 result = ff_mms_read_data(mms, buf, size); |
| 695 } else { | 595 } else { |
| 696 /* Read from network */ | 596 /* Read from network */ |
| 697 int err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_MEDIA); | 597 int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA); |
| 698 if (err == 0) { | 598 if (err == 0) { |
| 699 if(mms->remaining_in_len>mms->asf_packet_len) { | 599 if(mms->remaining_in_len>mms->asf_packet_len) { |
| 700 av_log(NULL, AV_LOG_ERROR, | 600 av_log(NULL, AV_LOG_ERROR, |
| 701 "Incoming pktlen %d is larger than ASF pktsize %d\n", | 601 "Incoming pktlen %d is larger than ASF pktsize %d\n", |
| 702 mms->remaining_in_len, mms->asf_packet_len); | 602 mms->remaining_in_len, mms->asf_packet_len); |
| 703 result= AVERROR_IO; | 603 result= AVERROR_IO; |
| 704 } else { | 604 } else { |
| 705 // copy the data to the packet buffer. | 605 // copy the data to the packet buffer. |
| 706 result = read_data(mms, buf, size); | 606 result = ff_mms_read_data(mms, buf, size); |
| 707 if (result == 0) { | 607 if (result == 0) { |
| 708 dprintf(NULL, "read asf media paket size is zero!\n"); | 608 dprintf(NULL, "read asf media paket size is zero!\n"); |
| 709 break; | 609 break; |
| 710 } | 610 } |
| 711 } | 611 } |
| 712 } else { | 612 } else { |
| 713 dprintf(NULL, "read packet error!\n"); | 613 dprintf(NULL, "read packet error!\n"); |
| 714 break; | 614 break; |
| 715 } | 615 } |
| 716 } | 616 } |
| 717 } while(!result); // only return one packet. | 617 } while(!result); // only return one packet. |
| 718 return result; | 618 return result; |
| 719 } | 619 } |
| 720 | 620 |
| 721 URLProtocol mmst_protocol = { | 621 URLProtocol mmst_protocol = { |
| 722 "mmst", | 622 "mmst", |
| 723 mms_open, | 623 mms_open, |
| 724 mms_read, | 624 mms_read, |
| 725 NULL, // write | 625 NULL, // write |
| 726 NULL, // seek | 626 NULL, // seek |
| 727 mms_close, | 627 mms_close, |
| 728 }; | 628 }; |
| OLD | NEW |