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.

706 lines
26KB

  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 len= mms->write_out_ptr - mms->out_buffer;
  133. int exact_length = (len + 7) & ~7;
  134. int first_length= exact_length - 16;
  135. int len8= first_length/8;
  136. int write_result;
  137. // update packet length fields.
  138. AV_WL32(mms->out_buffer + 8, first_length);
  139. AV_WL32(mms->out_buffer + 16, len8);
  140. AV_WL32(mms->out_buffer + 32, len8-2);
  141. memset(mms->write_out_ptr, 0, exact_length - len);
  142. // write it out.
  143. write_result= url_write(mms->mms_hd, mms->out_buffer, exact_length);
  144. if(write_result != exact_length) {
  145. dprintf(NULL, "url_write returned: %d != %d\n",
  146. write_result, exact_length);
  147. return AVERROR_IO;
  148. }
  149. return 0;
  150. }
  151. static void mms_put_utf16(MMSContext *mms, uint8_t *src)
  152. {
  153. ByteIOContext bic;
  154. int size = mms->write_out_ptr - mms->out_buffer;
  155. int len;
  156. init_put_byte(&bic, mms->write_out_ptr,
  157. sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
  158. len = ff_put_str16_nolen(&bic, src);
  159. mms->write_out_ptr += len;
  160. }
  161. static int send_time_test_data(MMSContext *mms)
  162. {
  163. start_command_packet(mms, CS_PKT_TIMING_DATA_REQUEST);
  164. insert_command_prefixes(mms, 0xf0f0f0f1, 0x0004000b);
  165. return send_command_packet(mms);
  166. }
  167. static int send_protocol_select(MMSContext *mms)
  168. {
  169. char data_string[256];
  170. start_command_packet(mms, CS_PKT_PROTOCOL_SELECT);
  171. insert_command_prefixes(mms, 0, 0xffffffff);
  172. bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes
  173. bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate
  174. bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode
  175. snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
  176. (LOCAL_ADDRESS>>24)&0xff,
  177. (LOCAL_ADDRESS>>16)&0xff,
  178. (LOCAL_ADDRESS>>8)&0xff,
  179. LOCAL_ADDRESS&0xff,
  180. "TCP", // or UDP
  181. LOCAL_PORT);
  182. mms_put_utf16(mms, data_string);
  183. return send_command_packet(mms);
  184. }
  185. static int send_media_file_request(MMSContext *mms)
  186. {
  187. start_command_packet(mms, CS_PKT_MEDIA_FILE_REQUEST);
  188. insert_command_prefixes(mms, 1, 0xffffffff);
  189. bytestream_put_le32(&mms->write_out_ptr, 0);
  190. bytestream_put_le32(&mms->write_out_ptr, 0);
  191. mms_put_utf16(mms, mms->path + 1); // +1 for skip "/"
  192. return send_command_packet(mms);
  193. }
  194. static void handle_packet_stream_changing_type(MMSContext *mms)
  195. {
  196. dprintf(NULL, "Stream changing!\n");
  197. // 40 is the packet header size, 7 is the prefix size.
  198. mms->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
  199. dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id);
  200. }
  201. static int send_keepalive_packet(MMSContext *mms)
  202. {
  203. // respond to a keepalive with a keepalive...
  204. start_command_packet(mms, CS_PKT_KEEPALIVE);
  205. insert_command_prefixes(mms, 1, 0x100FFFF);
  206. return send_command_packet(mms);
  207. }
  208. /** Pad media packets smaller than max_packet_size and/or adjust read position
  209. * after a seek. */
  210. static void pad_media_packet(MMSContext *mms)
  211. {
  212. if(mms->remaining_in_len<mms->asf_packet_len) {
  213. int padding_size = mms->asf_packet_len - mms->remaining_in_len;
  214. memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
  215. mms->remaining_in_len += padding_size;
  216. }
  217. }
  218. /** Read incoming MMST media, header or command packet. */
  219. static MMSSCPacketType get_tcp_server_response(MMSContext *mms)
  220. {
  221. int read_result;
  222. MMSSCPacketType packet_type= -1;
  223. for(;;) {
  224. if((read_result= url_read_complete(mms->mms_hd, mms->in_buffer, 8))==8) {
  225. // handle command packet.
  226. if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
  227. mms->incoming_flags= mms->in_buffer[3];
  228. read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
  229. if(read_result == 4) {
  230. int length_remaining= AV_RL32(mms->in_buffer+8) + 4;
  231. int hr;
  232. dprintf(NULL, "Length remaining is %d\n", length_remaining);
  233. // read the rest of the packet.
  234. if (length_remaining < 0
  235. || length_remaining > sizeof(mms->in_buffer) - 12) {
  236. dprintf(NULL, "Incoming message len %d exceeds buffer len %d\n",
  237. length_remaining, sizeof(mms->in_buffer) - 12);
  238. return -1;
  239. }
  240. read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12,
  241. length_remaining) ;
  242. if (read_result == length_remaining) {
  243. packet_type= AV_RL16(mms->in_buffer+36);
  244. } else {
  245. dprintf(NULL, "read for packet type failed%d!\n", read_result);
  246. return -1;
  247. }
  248. hr = AV_RL32(mms->in_buffer + 40);
  249. if (hr) {
  250. dprintf(NULL, "The server side send back error code:0x%x\n", hr);
  251. return -1;
  252. }
  253. } else {
  254. dprintf(NULL, "read for length remaining failed%d!\n", read_result);
  255. return -1;
  256. }
  257. } else {
  258. int length_remaining;
  259. int packet_id_type;
  260. int tmp;
  261. assert(mms->remaining_in_len==0);
  262. // note we cache the first 8 bytes,
  263. // then fill up the buffer with the others
  264. tmp = AV_RL16(mms->in_buffer + 6);
  265. length_remaining = (tmp - 8) & 0xffff;
  266. mms->incoming_packet_seq = AV_RL32(mms->in_buffer);
  267. packet_id_type = mms->in_buffer[4];
  268. mms->incoming_flags = mms->in_buffer[5];
  269. if (length_remaining < 0
  270. || length_remaining > sizeof(mms->in_buffer) - 8) {
  271. dprintf(NULL, "Incoming data len %d exceeds buffer len %d\n",
  272. length_remaining, sizeof(mms->in_buffer));
  273. return -1;
  274. }
  275. mms->remaining_in_len = length_remaining;
  276. mms->read_in_ptr = mms->in_buffer;
  277. read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
  278. if(read_result != length_remaining) {
  279. dprintf(NULL, "read_bytes result: %d asking for %d\n",
  280. read_result, length_remaining);
  281. return -1;
  282. } else {
  283. // if we successfully read everything.
  284. if(packet_id_type == mms->header_packet_id) {
  285. packet_type = SC_PKT_ASF_HEADER;
  286. // Store the asf header
  287. if(!mms->header_parsed) {
  288. void *p = av_realloc(mms->asf_header,
  289. mms->asf_header_size
  290. + mms->remaining_in_len);
  291. if (!p) {
  292. av_freep(&mms->asf_header);
  293. return AVERROR(ENOMEM);
  294. }
  295. mms->asf_header = p;
  296. memcpy(mms->asf_header + mms->asf_header_size,
  297. mms->read_in_ptr,
  298. mms->remaining_in_len);
  299. mms->asf_header_size += mms->remaining_in_len;
  300. }
  301. } else if(packet_id_type == mms->packet_id) {
  302. packet_type = SC_PKT_ASF_MEDIA;
  303. } else {
  304. dprintf(NULL, "packet id type %d is old.", packet_id_type);
  305. continue;
  306. }
  307. }
  308. }
  309. // preprocess some packet type
  310. if(packet_type == SC_PKT_KEEPALIVE) {
  311. send_keepalive_packet(mms);
  312. continue;
  313. } else if(packet_type == SC_PKT_STREAM_CHANGING) {
  314. handle_packet_stream_changing_type(mms);
  315. } else if(packet_type == SC_PKT_ASF_MEDIA) {
  316. pad_media_packet(mms);
  317. }
  318. return packet_type;
  319. } else {
  320. if(read_result<0) {
  321. dprintf(NULL, "Read error (or cancelled) returned %d!\n", read_result);
  322. packet_type = SC_PKT_CANCEL;
  323. } else {
  324. dprintf(NULL, "Read result of zero?!\n");
  325. packet_type = SC_PKT_NO_DATA;
  326. }
  327. return packet_type;
  328. }
  329. }
  330. }
  331. static int mms_safe_send_recv(MMSContext *mms,
  332. int (*send_fun)(MMSContext *mms),
  333. const MMSSCPacketType expect_type)
  334. {
  335. MMSSCPacketType type;
  336. if(send_fun) {
  337. int ret = send_fun(mms);
  338. if (ret < 0) {
  339. dprintf(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
  340. return ret;
  341. }
  342. }
  343. if ((type = get_tcp_server_response(mms)) != expect_type) {
  344. dprintf(NULL,"Unexpected packet type %d with type %d\n", type, expect_type);
  345. return -1;
  346. } else {
  347. return 0;
  348. }
  349. }
  350. static int send_media_header_request(MMSContext *mms)
  351. {
  352. start_command_packet(mms, CS_PKT_MEDIA_HEADER_REQUEST);
  353. insert_command_prefixes(mms, 1, 0);
  354. bytestream_put_le32(&mms->write_out_ptr, 0);
  355. bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
  356. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
  357. bytestream_put_le32(&mms->write_out_ptr, 0);
  358. bytestream_put_le32(&mms->write_out_ptr, 0);
  359. bytestream_put_le32(&mms->write_out_ptr, 0);
  360. // the media preroll value in milliseconds?
  361. bytestream_put_le32(&mms->write_out_ptr, 0);
  362. bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
  363. bytestream_put_le32(&mms->write_out_ptr, 2);
  364. bytestream_put_le32(&mms->write_out_ptr, 0);
  365. return send_command_packet(mms);
  366. }
  367. /** Send the initial handshake. */
  368. static int send_startup_packet(MMSContext *mms)
  369. {
  370. char data_string[256];
  371. // SubscriberName is defined in MS specification linked below.
  372. // The guid value can be any valid value.
  373. // http://download.microsoft.com/
  374. // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
  375. snprintf(data_string, sizeof(data_string),
  376. "NSPlayer/7.0.0.1956; {%s}; Host: %s",
  377. "7E667F5D-A661-495E-A512-F55686DDA178", mms->host);
  378. start_command_packet(mms, CS_PKT_INITIAL);
  379. insert_command_prefixes(mms, 0, 0x0004000b);
  380. bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
  381. mms_put_utf16(mms, data_string);
  382. return send_command_packet(mms);
  383. }
  384. static int asf_header_parser(MMSContext *mms)
  385. {
  386. uint8_t *p = mms->asf_header;
  387. uint8_t *end;
  388. int flags, stream_id, real_header_size;
  389. mms->stream_num = 0;
  390. if (mms->asf_header_size < sizeof(ff_asf_guid) * 2 + 22 ||
  391. memcmp(p, ff_asf_header, sizeof(ff_asf_guid)))
  392. return -1;
  393. real_header_size = AV_RL64(p + sizeof(ff_asf_guid));
  394. end = mms->asf_header + real_header_size;
  395. p += sizeof(ff_asf_guid) + 14;
  396. while(end - p >= sizeof(ff_asf_guid) + 8) {
  397. uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
  398. if (!chunksize || chunksize > end - p) {
  399. dprintf(NULL, "chunksize is exceptional value:%"PRId64"!\n", chunksize);
  400. return -1;
  401. }
  402. if (!memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
  403. /* read packet size */
  404. if (end - p > sizeof(ff_asf_guid) * 2 + 68) {
  405. mms->asf_packet_len = AV_RL32(p + sizeof(ff_asf_guid) * 2 + 64);
  406. if (mms->asf_packet_len <= 0 || mms->asf_packet_len > sizeof(mms->in_buffer)) {
  407. dprintf(NULL,"Too large packet len:%d"
  408. " may overwrite in_buffer when padding", mms->asf_packet_len);
  409. return -1;
  410. }
  411. }
  412. } else if (!memcmp(p, ff_asf_stream_header, sizeof(ff_asf_guid))) {
  413. flags = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
  414. stream_id = flags & 0x7F;
  415. //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
  416. //we can calcuate the packet size by stream_num.
  417. //Please see function send_stream_selection_request().
  418. if (mms->stream_num < MAX_STREAMS &&
  419. 46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
  420. mms->streams[mms->stream_num].id = stream_id;
  421. mms->stream_num++;
  422. } else {
  423. dprintf(NULL, "Too many streams.\n");
  424. return -1;
  425. }
  426. }
  427. p += chunksize;
  428. }
  429. return 0;
  430. }
  431. /** Send MMST stream selection command based on the AVStream->discard values. */
  432. static int send_stream_selection_request(MMSContext *mms)
  433. {
  434. int i;
  435. // send the streams we want back...
  436. start_command_packet(mms, CS_PKT_STREAM_ID_REQUEST);
  437. bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums
  438. for(i= 0; i<mms->stream_num; i++) {
  439. bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags
  440. bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id
  441. bytestream_put_le16(&mms->write_out_ptr, 0); // selection
  442. }
  443. return send_command_packet(mms);
  444. }
  445. static int read_data(MMSContext *mms, uint8_t *buf, const int buf_size)
  446. {
  447. int read_size;
  448. read_size = FFMIN(buf_size, mms->remaining_in_len);
  449. memcpy(buf, mms->read_in_ptr, read_size);
  450. mms->remaining_in_len -= read_size;
  451. mms->read_in_ptr += read_size;
  452. return read_size;
  453. }
  454. /** Read at most one media packet (or a whole header). */
  455. static int read_mms_packet(MMSContext *mms, uint8_t *buf, int buf_size)
  456. {
  457. int result = 0, read_header_size = 0;
  458. int size_to_copy;
  459. do {
  460. if(read_header_size < mms->asf_header_size && !mms->is_playing) {
  461. /* Read from ASF header buffer */
  462. size_to_copy= FFMIN(buf_size,
  463. mms->asf_header_size - read_header_size);
  464. memcpy(buf, mms->asf_header + read_header_size, size_to_copy);
  465. read_header_size += size_to_copy;
  466. result += size_to_copy;
  467. dprintf(NULL, "Copied %d bytes from stored header. left: %d\n",
  468. size_to_copy, mms->asf_header_size - read_header_size);
  469. if (mms->asf_header_size == read_header_size) {
  470. av_freep(&mms->asf_header);
  471. mms->is_playing = 1;
  472. }
  473. } else if(mms->remaining_in_len) {
  474. /* Read remaining packet data to buffer.
  475. * the result can not be zero because remaining_in_len is positive.*/
  476. result = read_data(mms, buf, buf_size);
  477. } else {
  478. /* Read from network */
  479. int err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_MEDIA);
  480. if (err == 0) {
  481. if(mms->remaining_in_len>mms->asf_packet_len) {
  482. dprintf(NULL, "Incoming packet"
  483. "larger than the asf packet size stated (%d>%d)\n",
  484. mms->remaining_in_len, mms->asf_packet_len);
  485. result= AVERROR_IO;
  486. } else {
  487. // copy the data to the packet buffer.
  488. result = read_data(mms, buf, buf_size);
  489. if (result == 0) {
  490. dprintf(NULL, "read asf media paket size is zero!\n");
  491. break;
  492. }
  493. }
  494. } else {
  495. dprintf(NULL, "read packet error!\n");
  496. break;
  497. }
  498. }
  499. } while(!result); // only return one packet.
  500. return result;
  501. }
  502. static int send_close_packet(MMSContext *mms)
  503. {
  504. start_command_packet(mms, CS_PKT_STREAM_CLOSE);
  505. insert_command_prefixes(mms, 1, 1);
  506. return send_command_packet(mms);
  507. }
  508. /** Close the MMSH/MMST connection */
  509. static int mms_close(URLContext *h)
  510. {
  511. MMSContext *mms = (MMSContext *)h->priv_data;
  512. if(mms->mms_hd) {
  513. send_close_packet(mms);
  514. url_close(mms->mms_hd);
  515. }
  516. /* free all separately allocated pointers in mms */
  517. av_free(mms->asf_header);
  518. av_freep(&h->priv_data);
  519. return 0;
  520. }
  521. static int mms_open(URLContext *h, const char *uri, int flags)
  522. {
  523. MMSContext *mms;
  524. int port, err;
  525. char tcpname[256];
  526. h->is_streamed = 1;
  527. mms = h->priv_data = av_mallocz(sizeof(MMSContext));
  528. if (!h->priv_data)
  529. return AVERROR(ENOMEM);
  530. // only for MMS over TCP, so set proto = NULL
  531. av_url_split(NULL, 0, NULL, 0,
  532. mms->host, sizeof(mms->host), &port, mms->path,
  533. sizeof(mms->path), uri);
  534. if(port<0)
  535. port = 1755; // defaut mms protocol port
  536. // establish tcp connection.
  537. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mms->host, port, NULL);
  538. err = url_open(&mms->mms_hd, tcpname, URL_RDWR);
  539. if (err)
  540. goto fail;
  541. mms->packet_id = 3; // default, initial value.
  542. mms->header_packet_id = 2; // default, initial value.
  543. err = mms_safe_send_recv(mms, send_startup_packet, SC_PKT_CLIENT_ACCEPTED);
  544. if (err)
  545. goto fail;
  546. err = mms_safe_send_recv(mms, send_time_test_data, SC_PKT_TIMING_TEST_REPLY);
  547. if (err)
  548. goto fail;
  549. err = mms_safe_send_recv(mms, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED);
  550. if (err)
  551. goto fail;
  552. err = mms_safe_send_recv(mms, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS);
  553. if (err)
  554. goto fail;
  555. err = mms_safe_send_recv(mms, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED);
  556. if (err)
  557. goto fail;
  558. err = mms_safe_send_recv(mms, NULL, SC_PKT_ASF_HEADER);
  559. if (err)
  560. goto fail;
  561. if((mms->incoming_flags != 0X08) && (mms->incoming_flags != 0X0C))
  562. goto fail;
  563. err = asf_header_parser(mms);
  564. if (err) {
  565. dprintf(NULL, "asf header parsed failed!\n");
  566. goto fail;
  567. }
  568. mms->header_parsed = 1;
  569. if (!mms->asf_packet_len || !mms->stream_num)
  570. goto fail;
  571. dprintf(NULL, "Leaving open (success)\n");
  572. return 0;
  573. fail:
  574. mms_close(h);
  575. dprintf(NULL, "Leaving open (failure: %d)\n", err);
  576. return err;
  577. }
  578. static int send_media_packet_request(MMSContext *mms)
  579. {
  580. start_command_packet(mms, CS_PKT_START_FROM_PKT_ID);
  581. insert_command_prefixes(mms, 1, 0x0001FFFF);
  582. bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp
  583. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown
  584. bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset
  585. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  586. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  587. bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
  588. bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag
  589. mms->packet_id++; // new packet_id
  590. bytestream_put_le32(&mms->write_out_ptr, mms->packet_id);
  591. return send_command_packet(mms);
  592. }
  593. static void clear_stream_buffers(MMSContext *mms)
  594. {
  595. mms->remaining_in_len = 0;
  596. mms->read_in_ptr = mms->in_buffer;
  597. }
  598. /** Read ASF data through the protocol. */
  599. static int mms_read(URLContext *h, uint8_t *buf, int size)
  600. {
  601. /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
  602. MMSContext *mms = h->priv_data;
  603. int result = 0;
  604. /* Since we read the header at open(), this shouldn't be possible */
  605. assert(mms->header_parsed);
  606. if (!mms->is_playing) {
  607. dprintf(NULL, "mms_read() before play().\n");
  608. clear_stream_buffers(mms);
  609. result = mms_safe_send_recv(mms, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED);
  610. if (result)
  611. return result;
  612. // send media packet request
  613. result = mms_safe_send_recv(mms, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS);
  614. if (result) {
  615. return result;
  616. }
  617. }
  618. return read_mms_packet(mms, buf, size);
  619. }
  620. URLProtocol mmst_protocol = {
  621. "mmst",
  622. mms_open,
  623. mms_read,
  624. NULL, // write
  625. NULL, // seek
  626. mms_close,
  627. };