You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

691 lines
25KB

  1. /*
  2. * MMS protocol over TCP
  3. * Copyright (c) 2006,2007 Ryan Martell
  4. * Copyright (c) 2007 Björn Axelsson
  5. * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
  6. *
  7. * This file is part of FFmpeg.
  8. *
  9. * FFmpeg is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * FFmpeg is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with FFmpeg; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include "avformat.h"
  24. #include "internal.h"
  25. #include "libavutil/intreadwrite.h"
  26. #include "libavcodec/bytestream.h"
  27. #include "network.h"
  28. #include "asf.h"
  29. #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
  30. #define LOCAL_PORT 1037 // as above.
  31. /** Client to server packet types. */
  32. typedef enum {
  33. CS_PKT_INITIAL = 0x01,
  34. CS_PKT_PROTOCOL_SELECT = 0x02,
  35. CS_PKT_MEDIA_FILE_REQUEST = 0x05,
  36. CS_PKT_START_FROM_PKT_ID = 0x07,
  37. CS_PKT_STREAM_PAUSE = 0x09,
  38. CS_PKT_STREAM_CLOSE = 0x0d,
  39. CS_PKT_MEDIA_HEADER_REQUEST = 0x15,
  40. CS_PKT_TIMING_DATA_REQUEST = 0x18,
  41. CS_PKT_USER_PASSWORD = 0x1a,
  42. CS_PKT_KEEPALIVE = 0x1b,
  43. CS_PKT_STREAM_ID_REQUEST = 0x33,
  44. } MMSCSPacketType;
  45. /** Server to client packet types. */
  46. typedef enum {
  47. /** Control packets. */
  48. /*@{*/
  49. SC_PKT_CLIENT_ACCEPTED = 0x01,
  50. SC_PKT_PROTOCOL_ACCEPTED = 0x02,
  51. SC_PKT_PROTOCOL_FAILED = 0x03,
  52. SC_PKT_MEDIA_PKT_FOLLOWS = 0x05,
  53. SC_PKT_MEDIA_FILE_DETAILS = 0x06,
  54. SC_PKT_HEADER_REQUEST_ACCEPTED = 0x11,
  55. SC_PKT_TIMING_TEST_REPLY = 0x15,
  56. SC_PKT_PASSWORD_REQUIRED = 0x1a,
  57. SC_PKT_KEEPALIVE = 0x1b,
  58. SC_PKT_STREAM_STOPPED = 0x1e,
  59. SC_PKT_STREAM_CHANGING = 0x20,
  60. SC_PKT_STREAM_ID_ACCEPTED = 0x21,
  61. /*@}*/
  62. /** Pseudo packets. */
  63. /*@{*/
  64. SC_PKT_CANCEL = -1,
  65. SC_PKT_NO_DATA = -2,
  66. /*@}*/
  67. /** Data packets. */
  68. /*@{*/
  69. SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in case of
  70. SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets.
  71. /*@}*/
  72. } MMSSCPacketType;
  73. typedef struct {
  74. int id;
  75. }MMSStream;
  76. typedef struct {
  77. int outgoing_packet_seq; ///< Outgoing packet sequence number.
  78. char path[256]; ///< Path of the resource being asked for.
  79. char host[128]; ///< Host of the resources.
  80. URLContext *mms_hd; ///< TCP connection handle
  81. MMSStream streams[MAX_STREAMS];
  82. /** Buffer for outgoing packets. */
  83. /*@{*/
  84. uint8_t *write_out_ptr; ///< Pointer for writting the buffer.
  85. uint8_t out_buffer[512]; ///< Buffer for outgoing packet.
  86. /*@}*/
  87. /** Buffer for incoming packets. */
  88. /*@{*/
  89. uint8_t in_buffer[8192]; ///< Buffer for incoming packets.
  90. uint8_t *read_in_ptr; ///< Pointer for reading from incoming buffer.
  91. int remaining_in_len; ///< Reading length from incoming buffer.
  92. /*@}*/
  93. int incoming_packet_seq; ///< Incoming packet sequence number.
  94. int incoming_flags; ///< Incoming packet flags.
  95. int packet_id; ///< Identifier for packets in the current stream.
  96. unsigned int header_packet_id; ///< default is 2.
  97. /** Internal handling of the ASF header */
  98. /*@{*/
  99. uint8_t *asf_header; ///< Stored ASF header.
  100. int asf_header_size; ///< Size of stored ASF header.
  101. int header_parsed; ///< The header has been received and parsed.
  102. int asf_packet_len;
  103. /*@}*/
  104. int stream_num; ///< stream numbers.
  105. int is_playing;
  106. } MMSContext;
  107. /** Create MMST command packet header */
  108. static void start_command_packet(MMSContext *mms, MMSCSPacketType packet_type)
  109. {
  110. mms->write_out_ptr = mms->out_buffer;
  111. bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence
  112. bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
  113. bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes
  114. bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
  115. bytestream_put_le32(&mms->write_out_ptr, 0);
  116. bytestream_put_le32(&mms->write_out_ptr, mms->outgoing_packet_seq++);
  117. bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp
  118. bytestream_put_le32(&mms->write_out_ptr, 0);
  119. bytestream_put_le16(&mms->write_out_ptr, packet_type);
  120. bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server
  121. }
  122. /** Add prefixes to MMST command packet. */
  123. static void insert_command_prefixes(MMSContext *mms,
  124. uint32_t prefix1, uint32_t prefix2)
  125. {
  126. bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix
  127. bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix
  128. }
  129. /** Send a prepared MMST command packet. */
  130. static int send_command_packet(MMSContext *mms)
  131. {
  132. int exact_length= mms->write_out_ptr - mms->out_buffer;
  133. int first_length= exact_length - 16;
  134. int len8= first_length/8;
  135. int write_result;
  136. // update packet length fields.
  137. AV_WL32(mms->out_buffer + 8, first_length);
  138. AV_WL32(mms->out_buffer + 16, len8);
  139. AV_WL32(mms->out_buffer + 32, len8-2);
  140. // write it out.
  141. write_result= url_write(mms->mms_hd, mms->out_buffer, exact_length);
  142. if(write_result != exact_length) {
  143. dprintf(NULL, "url_write returned: %d != %d\n",
  144. write_result, exact_length);
  145. return AVERROR_IO;
  146. }
  147. return 0;
  148. }
  149. static void mms_put_utf16(MMSContext *mms, uint8_t *src)
  150. {
  151. ByteIOContext bic;
  152. int size = mms->write_out_ptr - mms->out_buffer;
  153. int len;
  154. init_put_byte(&bic, mms->write_out_ptr,
  155. sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
  156. len = ff_put_str16_nolen(&bic, src);
  157. mms->write_out_ptr += len;
  158. }
  159. static int send_protocol_select(MMSContext *mms)
  160. {
  161. char data_string[256];
  162. start_command_packet(mms, CS_PKT_PROTOCOL_SELECT);
  163. insert_command_prefixes(mms, 0, 0xffffffff);
  164. bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes
  165. bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate
  166. bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode
  167. snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
  168. (LOCAL_ADDRESS>>24)&0xff,
  169. (LOCAL_ADDRESS>>16)&0xff,
  170. (LOCAL_ADDRESS>>8)&0xff,
  171. LOCAL_ADDRESS&0xff,
  172. "TCP", // or UDP
  173. LOCAL_PORT);
  174. mms_put_utf16(mms, data_string);
  175. return send_command_packet(mms);
  176. }
  177. static int send_media_file_request(MMSContext *mms)
  178. {
  179. start_command_packet(mms, CS_PKT_MEDIA_FILE_REQUEST);
  180. insert_command_prefixes(mms, 1, 0xffffffff);
  181. bytestream_put_le32(&mms->write_out_ptr, 0);
  182. bytestream_put_le32(&mms->write_out_ptr, 0);
  183. mms_put_utf16(mms, mms->path + 1); // +1 for skip "/"
  184. return send_command_packet(mms);
  185. }
  186. static void handle_packet_stream_changing_type(MMSContext *mms)
  187. {
  188. dprintf(NULL, "Stream changing!\n");
  189. // 40 is the packet header size, 7 is the prefix size.
  190. mms->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
  191. dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id);
  192. }
  193. static int send_keepalive_packet(MMSContext *mms)
  194. {
  195. // respond to a keepalive with a keepalive...
  196. start_command_packet(mms, CS_PKT_KEEPALIVE);
  197. insert_command_prefixes(mms, 1, 0x100FFFF);
  198. return send_command_packet(mms);
  199. }
  200. /** Pad media packets smaller than max_packet_size and/or adjust read position
  201. * after a seek. */
  202. static void pad_media_packet(MMSContext *mms)
  203. {
  204. if(mms->remaining_in_len<mms->asf_packet_len) {
  205. int padding_size = mms->asf_packet_len - mms->remaining_in_len;
  206. memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
  207. mms->remaining_in_len += padding_size;
  208. }
  209. }
  210. /** Read incoming MMST media, header or command packet. */
  211. static MMSSCPacketType get_tcp_server_response(MMSContext *mms)
  212. {
  213. int read_result;
  214. MMSSCPacketType packet_type= -1;
  215. for(;;) {
  216. if((read_result= url_read_complete(mms->mms_hd, mms->in_buffer, 8))==8) {
  217. // handle command packet.
  218. if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
  219. mms->incoming_flags= mms->in_buffer[3];
  220. read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
  221. if(read_result == 4) {
  222. int length_remaining= AV_RL32(mms->in_buffer+8) + 4;
  223. dprintf(NULL, "Length remaining is %d\n", length_remaining);
  224. // read the rest of the packet.
  225. if (length_remaining < 0
  226. || length_remaining > sizeof(mms->in_buffer) - 12) {
  227. dprintf(NULL, "Incoming message len %d exceeds buffer len %d\n",
  228. length_remaining, sizeof(mms->in_buffer) - 12);
  229. return -1;
  230. }
  231. read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12,
  232. length_remaining) ;
  233. if (read_result == length_remaining) {
  234. packet_type= AV_RL16(mms->in_buffer+36);
  235. } else {
  236. dprintf(NULL, "read for packet type failed%d!\n", read_result);
  237. return -1;
  238. }
  239. } else {
  240. dprintf(NULL, "read for length remaining failed%d!\n", read_result);
  241. return -1;
  242. }
  243. } else {
  244. int length_remaining;
  245. int packet_id_type;
  246. int tmp;
  247. assert(mms->remaining_in_len==0);
  248. // note we cache the first 8 bytes,
  249. // then fill up the buffer with the others
  250. tmp = AV_RL16(mms->in_buffer + 6);
  251. length_remaining = (tmp - 8) & 0xffff;
  252. mms->incoming_packet_seq = AV_RL32(mms->in_buffer);
  253. packet_id_type = mms->in_buffer[4];
  254. mms->incoming_flags = mms->in_buffer[5];
  255. if (length_remaining < 0
  256. || length_remaining > sizeof(mms->in_buffer) - 8) {
  257. dprintf(NULL, "Incoming data len %d exceeds buffer len %d\n",
  258. length_remaining, sizeof(mms->in_buffer));
  259. return -1;
  260. }
  261. mms->remaining_in_len = length_remaining;
  262. mms->read_in_ptr = mms->in_buffer;
  263. read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
  264. if(read_result != length_remaining) {
  265. dprintf(NULL, "read_bytes result: %d asking for %d\n",
  266. read_result, length_remaining);
  267. return -1;
  268. } else {
  269. // if we successfully read everything.
  270. if(packet_id_type == mms->header_packet_id) {
  271. packet_type = SC_PKT_ASF_HEADER;
  272. // Store the asf header
  273. if(!mms->header_parsed) {
  274. void *p = av_realloc(mms->asf_header,
  275. mms->asf_header_size
  276. + mms->remaining_in_len);
  277. if (!p) {
  278. av_freep(&mms->asf_header);
  279. return AVERROR(ENOMEM);
  280. }
  281. mms->asf_header = p;
  282. memcpy(mms->asf_header + mms->asf_header_size,
  283. mms->read_in_ptr,
  284. mms->remaining_in_len);
  285. mms->asf_header_size += mms->remaining_in_len;
  286. }
  287. } else if(packet_id_type == mms->packet_id) {
  288. packet_type = SC_PKT_ASF_MEDIA;
  289. } else {
  290. dprintf(NULL, "packet id type %d is old.", packet_id_type);
  291. continue;
  292. }
  293. }
  294. }
  295. // preprocess some packet type
  296. if(packet_type == SC_PKT_KEEPALIVE) {
  297. send_keepalive_packet(mms);
  298. continue;
  299. } else if(packet_type == SC_PKT_STREAM_CHANGING) {
  300. handle_packet_stream_changing_type(mms);
  301. } else if(packet_type == SC_PKT_ASF_MEDIA) {
  302. pad_media_packet(mms);
  303. }
  304. return packet_type;
  305. } else {
  306. if(read_result<0) {
  307. dprintf(NULL, "Read error (or cancelled) returned %d!\n", read_result);
  308. packet_type = SC_PKT_CANCEL;
  309. } else {
  310. dprintf(NULL, "Read result of zero?!\n");
  311. packet_type = SC_PKT_NO_DATA;
  312. }
  313. return packet_type;
  314. }
  315. }
  316. }
  317. static int mms_safe_send_recv(MMSContext *mms,
  318. int (*send_fun)(MMSContext *mms),
  319. const MMSSCPacketType expect_type)
  320. {
  321. MMSSCPacketType type;
  322. if(send_fun) {
  323. int ret = send_fun(mms);
  324. if (ret < 0) {
  325. dprintf(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
  326. return ret;
  327. }
  328. }
  329. if ((type = get_tcp_server_response(mms)) != expect_type) {
  330. dprintf(NULL,"Unexpected packet type %d with type %d\n", type, expect_type);
  331. return -1;
  332. } else {
  333. return 0;
  334. }
  335. }
  336. static int send_media_header_request(MMSContext *mms)
  337. {
  338. start_command_packet(mms, CS_PKT_MEDIA_HEADER_REQUEST);
  339. insert_command_prefixes(mms, 1, 0);
  340. bytestream_put_le32(&mms->write_out_ptr, 0);
  341. bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
  342. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
  343. bytestream_put_le32(&mms->write_out_ptr, 0);
  344. bytestream_put_le32(&mms->write_out_ptr, 0);
  345. bytestream_put_le32(&mms->write_out_ptr, 0);
  346. // the media preroll value in milliseconds?
  347. bytestream_put_le32(&mms->write_out_ptr, 0);
  348. bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
  349. bytestream_put_le32(&mms->write_out_ptr, 2);
  350. bytestream_put_le32(&mms->write_out_ptr, 0);
  351. return send_command_packet(mms);
  352. }
  353. /** Send the initial handshake. */
  354. static int send_startup_packet(MMSContext *mms)
  355. {
  356. char data_string[256];
  357. // SubscriberName is defined in MS specification linked below.
  358. // The guid value can be any valid value.
  359. // http://download.microsoft.com/
  360. // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
  361. snprintf(data_string, sizeof(data_string),
  362. "NSPlayer/7.0.0.1956; {%s}; Host: %s",
  363. "7E667F5D-A661-495E-A512-F55686DDA178", mms->host);
  364. start_command_packet(mms, CS_PKT_INITIAL);
  365. insert_command_prefixes(mms, 0, 0x0004000b);
  366. bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
  367. mms_put_utf16(mms, data_string);
  368. return send_command_packet(mms);
  369. }
  370. static int asf_header_parser(MMSContext *mms)
  371. {
  372. uint8_t *p = mms->asf_header;
  373. uint8_t *end;
  374. int flags, stream_id, real_header_size;
  375. mms->stream_num = 0;
  376. if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
  377. memcmp(p, ff_asf_header, sizeof(ff_asf_guid)))
  378. return -1;
  379. real_header_size = AV_RL64(p + sizeof(ff_asf_guid));
  380. end = mms->asf_header + real_header_size;
  381. p += sizeof(ff_asf_guid) + 14;
  382. while(end - p >= sizeof(ff_asf_guid) + 8) {
  383. uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
  384. if (!chunksize || chunksize > end - p) {
  385. dprintf(NULL, "chunksize is exceptional value:%d!\n", chunksize);
  386. return -1;
  387. }
  388. if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
  389. /* read packet size */
  390. if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
  391. mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
  392. if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
  393. dprintf(NULL,"Too large packet len:%d"
  394. " may overwrite in_buffer when padding", mms->asf_packet_len);
  395. return -1;
  396. }
  397. }
  398. } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
  399. flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
  400. stream_id = flags & 0x7F;
  401. //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
  402. //we can calcuate the packet size by stream_num.
  403. //Please see function send_stream_selection_request().
  404. if (mms->stream_num < MAX_STREAMS &&
  405. 46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
  406. mms->streams[mms->stream_num].id = stream_id;
  407. mms->stream_num++;
  408. } else {
  409. dprintf(NULL, "Too many streams.\n");
  410. return -1;
  411. }
  412. }
  413. p += chunksize;
  414. }
  415. return 0;
  416. }
  417. /** Send MMST stream selection command based on the AVStream->discard values. */
  418. static int send_stream_selection_request(MMSContext *mms)
  419. {
  420. int i;
  421. // send the streams we want back...
  422. start_command_packet(mms, CS_PKT_STREAM_ID_REQUEST);
  423. bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums
  424. for(i= 0; i<mms->stream_num; i++) {
  425. bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags
  426. bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id
  427. bytestream_put_le16(&mms->write_out_ptr, 0); // selection
  428. }
  429. bytestream_put_le16(&mms->write_out_ptr, 0);
  430. return send_command_packet(mms);
  431. }
  432. static int read_data(MMSContext *mms, uint8_t *buf, const int buf_size)
  433. {
  434. int read_size;
  435. read_size = FFMIN(buf_size, mms->remaining_in_len);
  436. memcpy(buf, mms->read_in_ptr, read_size);
  437. mms->remaining_in_len -= read_size;
  438. mms->read_in_ptr += read_size;
  439. return read_size;
  440. }
  441. /** Read at most one media packet (or a whole header). */
  442. static int read_mms_packet(MMSContext *mms, uint8_t *buf, int buf_size)
  443. {
  444. int result = 0, read_header_size = 0;
  445. int size_to_copy;
  446. do {
  447. if(read_header_size < mms->asf_header_size && !mms->is_playing) {
  448. /* Read from ASF header buffer */
  449. size_to_copy= FFMIN(buf_size,
  450. mms->asf_header_size - read_header_size);
  451. memcpy(buf, mms->asf_header + read_header_size, size_to_copy);
  452. read_header_size += size_to_copy;
  453. result += size_to_copy;
  454. dprintf(NULL, "Copied %d bytes from stored header. left: %d\n",
  455. size_to_copy, mms->asf_header_size - read_header_size);
  456. if (mms->asf_header_size == read_header_size) {
  457. av_freep(&mms->asf_header);
  458. mms->is_playing = 1;
  459. }
  460. } else if(mms->remaining_in_len) {
  461. /* Read remaining packet data to buffer.
  462. * the result can not be zero because remaining_in_len is positive.*/
  463. result = read_data(mms, buf, buf_size);
  464. } else {
  465. /* Read from network */
  466. int err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_MEDIA);
  467. if (err == 0) {
  468. if(mms->remaining_in_len>mms->asf_packet_len) {
  469. dprintf(NULL, "Incoming packet"
  470. "larger than the asf packet size stated (%d>%d)\n",
  471. mms->remaining_in_len, mms->asf_packet_len);
  472. result= AVERROR_IO;
  473. } else {
  474. // copy the data to the packet buffer.
  475. result = read_data(mms, buf, buf_size);
  476. if (result == 0) {
  477. dprintf(NULL, "read asf media paket size is zero!\n");
  478. break;
  479. }
  480. }
  481. } else {
  482. dprintf(NULL, "read packet error!\n");
  483. break;
  484. }
  485. }
  486. } while(!result); // only return one packet.
  487. return result;
  488. }
  489. static int send_close_packet(MMSContext *mms)
  490. {
  491. start_command_packet(mms, CS_PKT_STREAM_CLOSE);
  492. insert_command_prefixes(mms, 1, 1);
  493. return send_command_packet(mms);
  494. }
  495. /** Close the MMSH/MMST connection */
  496. static int mms_close(URLContext *h)
  497. {
  498. MMSContext *mms = (MMSContext *)h->priv_data;
  499. if(mms->mms_hd) {
  500. send_close_packet(mms);
  501. url_close(mms->mms_hd);
  502. }
  503. /* free all separately allocated pointers in mms */
  504. av_free(mms->asf_header);
  505. av_freep(&h->priv_data);
  506. return 0;
  507. }
  508. static int mms_open(URLContext *h, const char *uri, int flags)
  509. {
  510. MMSContext *mms;
  511. int port, err;
  512. char tcpname[256];
  513. h->is_streamed = 1;
  514. mms = h->priv_data = av_mallocz(sizeof(MMSContext));
  515. if (!h->priv_data)
  516. return AVERROR(ENOMEM);
  517. // only for MMS over TCP, so set proto = NULL
  518. av_url_split(NULL, 0, NULL, 0,
  519. mms->host, sizeof(mms->host), &port, mms->path,
  520. sizeof(mms->path), uri);
  521. if(port<0)
  522. port = 1755; // defaut mms protocol port
  523. // establish tcp connection.
  524. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mms->host, port, NULL);
  525. err = url_open(&mms->mms_hd, tcpname, URL_RDWR);
  526. if (err)
  527. goto fail;
  528. mms->packet_id = 3; // default, initial value.
  529. mms->header_packet_id = 2; // default, initial value.
  530. err = mms_safe_send_recv(mms, send_startup_packet, SC_PKT_CLIENT_ACCEPTED);
  531. if (err)
  532. goto fail;
  533. err = mms_safe_send_recv(mms, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED);
  534. if (err)
  535. goto fail;
  536. err = mms_safe_send_recv(mms, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS);
  537. if (err)
  538. goto fail;
  539. err = mms_safe_send_recv(mms, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED);
  540. if (err)
  541. goto fail;
  542. err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_HEADER);
  543. if (err)
  544. goto fail;
  545. if((mms->incoming_flags != 0X08) && (mms->incoming_flags != 0X0C))
  546. goto fail;
  547. err = asf_header_parser(mms);
  548. if (err) {
  549. dprintf(NULL, "asf header parsed failed!\n");
  550. goto fail;
  551. }
  552. mms->header_parsed = 1;
  553. if (!mms->asf_packet_len || !mms->stream_num)
  554. goto fail;
  555. dprintf(NULL, "Leaving open (success)\n");
  556. return 0;
  557. fail:
  558. mms_close(h);
  559. dprintf(NULL, "Leaving open (failure: %d)\n", err);
  560. return err;
  561. }
  562. static int send_media_packet_request(MMSContext *mms)
  563. {
  564. start_command_packet(mms, CS_PKT_START_FROM_PKT_ID);
  565. insert_command_prefixes(mms, 1, 0x0001FFFF);
  566. bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp
  567. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown
  568. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset
  569. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  570. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  571. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  572. bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag
  573. mms->packet_id++; // new packet_id
  574. bytestream_put_le32(&mms->write_out_ptr, mms->packet_id);
  575. return send_command_packet(mms);
  576. }
  577. static void clear_stream_buffers(MMSContext *mms)
  578. {
  579. mms->remaining_in_len = 0;
  580. mms->read_in_ptr = mms->in_buffer;
  581. }
  582. /** Read ASF data through the protocol. */
  583. static int mms_read(URLContext *h, uint8_t *buf, int size)
  584. {
  585. /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
  586. MMSContext *mms = h->priv_data;
  587. int result = 0;
  588. /* Since we read the header at open(), this shouldn't be possible */
  589. assert(mms->header_parsed);
  590. if (!mms->is_playing) {
  591. dprintf(NULL, "mms_read() before play().\n");
  592. clear_stream_buffers(mms);
  593. result = mms_safe_send_recv(mms, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED);
  594. if (result)
  595. return result;
  596. // send media packet request
  597. result = mms_safe_send_recv(mms, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
  598. if (result) {
  599. return result;
  600. }
  601. }
  602. return read_mms_packet(mms, buf, size);
  603. }
  604. URLProtocol mmst_protocol = {
  605. "mmst",
  606. mms_open,
  607. mms_read,
  608. NULL, // write
  609. NULL, // seek
  610. mms_close,
  611. };