Libav
mmst.c
Go to the documentation of this file.
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 Libav.
8  *
9  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 /* References
25  * MMS protocol specification:
26  * [1]http://msdn.microsoft.com/en-us/library/cc234711(PROT.10).aspx
27  * ASF specification. Revision 01.20.03.
28  * [2]http://msdn.microsoft.com/en-us/library/bb643323.aspx
29  */
30 
31 #include "avformat.h"
32 #include "mms.h"
33 #include "internal.h"
34 #include "avio_internal.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavcodec/bytestream.h"
37 #include "network.h"
38 #include "url.h"
39 
40 #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address.
41 #define LOCAL_PORT 1037 // as above.
42 
43 typedef enum {
56 
58 typedef enum {
83  SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in case of
84  SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets.
87 
88 typedef struct {
91  char path[256];
92  char host[128];
95  int packet_id;
96  unsigned int header_packet_id;
97 } MMSTContext;
98 
100 static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
101 {
102  MMSContext *mms = &mmst->mms;
103  mms->write_out_ptr = mms->out_buffer;
104 
105  bytestream_put_le32(&mms->write_out_ptr, 1); // start sequence
106  bytestream_put_le32(&mms->write_out_ptr, 0xb00bface);
107  bytestream_put_le32(&mms->write_out_ptr, 0); // Length starts from after the protocol type bytes
108  bytestream_put_le32(&mms->write_out_ptr, MKTAG('M','M','S',' '));
109  bytestream_put_le32(&mms->write_out_ptr, 0);
110  bytestream_put_le32(&mms->write_out_ptr, mmst->outgoing_packet_seq++);
111  bytestream_put_le64(&mms->write_out_ptr, 0); // timestamp
112  bytestream_put_le32(&mms->write_out_ptr, 0);
113  bytestream_put_le16(&mms->write_out_ptr, packet_type);
114  bytestream_put_le16(&mms->write_out_ptr, 3); // direction to server
115 }
116 
119  uint32_t prefix1, uint32_t prefix2)
120 {
121  bytestream_put_le32(&mms->write_out_ptr, prefix1); // first prefix
122  bytestream_put_le32(&mms->write_out_ptr, prefix2); // second prefix
123 }
124 
127 {
128  MMSContext *mms = &mmst->mms;
129  int len= mms->write_out_ptr - mms->out_buffer;
130  int exact_length = FFALIGN(len, 8);
131  int first_length= exact_length - 16;
132  int len8= first_length/8;
133  int write_result;
134 
135  // update packet length fields.
136  AV_WL32(mms->out_buffer + 8, first_length);
137  AV_WL32(mms->out_buffer + 16, len8);
138  AV_WL32(mms->out_buffer + 32, len8-2);
139  memset(mms->write_out_ptr, 0, exact_length - len);
140 
141  // write it out.
142  write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length);
143  if(write_result != exact_length) {
145  "Failed to write data of length %d: %d (%s)\n",
146  exact_length, write_result,
147  write_result < 0 ? strerror(AVUNERROR(write_result)) :
148  "The server closed the connection");
149  return AVERROR(EIO);
150  }
151 
152  return 0;
153 }
154 
155 static void mms_put_utf16(MMSContext *mms, uint8_t *src)
156 {
157  AVIOContext bic;
158  int size = mms->write_out_ptr - mms->out_buffer;
159  int len;
160  ffio_init_context(&bic, mms->write_out_ptr,
161  sizeof(mms->out_buffer) - size, 1, NULL, NULL, NULL, NULL);
162 
163  len = avio_put_str16le(&bic, src);
164  mms->write_out_ptr += len;
165 }
166 
168 {
170  insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
171  return send_command_packet(mmst);
172 }
173 
175 {
176  char data_string[256];
177  MMSContext *mms = &mmst->mms;
178 
180  insert_command_prefixes(mms, 0, 0xffffffff);
181  bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes
182  bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate
183  bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode
184  snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
185  (LOCAL_ADDRESS>>24)&0xff,
186  (LOCAL_ADDRESS>>16)&0xff,
187  (LOCAL_ADDRESS>>8)&0xff,
188  LOCAL_ADDRESS&0xff,
189  "TCP", // or UDP
190  LOCAL_PORT);
191 
192  mms_put_utf16(mms, data_string);
193  return send_command_packet(mmst);
194 }
195 
197 {
198  MMSContext *mms = &mmst->mms;
200  insert_command_prefixes(mms, 1, 0xffffffff);
201  bytestream_put_le32(&mms->write_out_ptr, 0);
202  bytestream_put_le32(&mms->write_out_ptr, 0);
203  mms_put_utf16(mms, mmst->path + 1); // +1 for skip "/"
204 
205  return send_command_packet(mmst);
206 }
207 
209 {
210  MMSContext *mms = &mmst->mms;
211  av_dlog(NULL, "Stream changing!\n");
212 
213  // 40 is the packet header size, 7 is the prefix size.
214  mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
215  av_dlog(NULL, "Changed header prefix to 0x%x", mmst->header_packet_id);
216 }
217 
219 {
220  // respond to a keepalive with a keepalive...
222  insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
223  return send_command_packet(mmst);
224 }
225 
228 static void pad_media_packet(MMSContext *mms)
229 {
230  if(mms->remaining_in_len<mms->asf_packet_len) {
231  int padding_size = mms->asf_packet_len - mms->remaining_in_len;
232  memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
233  mms->remaining_in_len += padding_size;
234  }
235 }
236 
239 {
240  int read_result;
241  MMSSCPacketType packet_type= -1;
242  MMSContext *mms = &mmst->mms;
243  for(;;) {
244  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8);
245  if (read_result != 8) {
246  if(read_result < 0) {
248  "Error reading packet header: %d (%s)\n",
249  read_result, strerror(AVUNERROR(read_result)));
250  packet_type = SC_PKT_CANCEL;
251  } else {
253  "The server closed the connection\n");
254  packet_type = SC_PKT_NO_DATA;
255  }
256  return packet_type;
257  }
258 
259  // handle command packet.
260  if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
261  int length_remaining, hr;
262 
263  mmst->incoming_flags= mms->in_buffer[3];
264  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
265  if(read_result != 4) {
267  "Reading command packet length failed: %d (%s)\n",
268  read_result,
269  read_result < 0 ? strerror(AVUNERROR(read_result)) :
270  "The server closed the connection");
271  return read_result < 0 ? read_result : AVERROR(EIO);
272  }
273 
274  length_remaining= AV_RL32(mms->in_buffer+8) + 4;
275  av_dlog(NULL, "Length remaining is %d\n", length_remaining);
276  // read the rest of the packet.
277  if (length_remaining < 0
278  || length_remaining > sizeof(mms->in_buffer) - 12) {
280  "Incoming packet length %d exceeds bufsize %zu\n",
281  length_remaining, sizeof(mms->in_buffer) - 12);
282  return AVERROR_INVALIDDATA;
283  }
284  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12,
285  length_remaining) ;
286  if (read_result != length_remaining) {
288  "Reading pkt data (length=%d) failed: %d (%s)\n",
289  length_remaining, read_result,
290  read_result < 0 ? strerror(AVUNERROR(read_result)) :
291  "The server closed the connection");
292  return read_result < 0 ? read_result : AVERROR(EIO);
293  }
294  packet_type= AV_RL16(mms->in_buffer+36);
295  if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
297  "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
298  return AVERROR(EINVAL);
299  }
300  } else {
301  int length_remaining;
302  int packet_id_type;
303  int tmp;
304 
305  // note we cache the first 8 bytes,
306  // then fill up the buffer with the others
307  tmp = AV_RL16(mms->in_buffer + 6);
308  length_remaining = (tmp - 8) & 0xffff;
309  mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
310  packet_id_type = mms->in_buffer[4];
311  mmst->incoming_flags = mms->in_buffer[5];
312 
313  if (length_remaining < 0
314  || length_remaining > sizeof(mms->in_buffer) - 8) {
316  "Data length %d is invalid or too large (max=%zu)\n",
317  length_remaining, sizeof(mms->in_buffer));
318  return AVERROR_INVALIDDATA;
319  }
320  mms->remaining_in_len = length_remaining;
321  mms->read_in_ptr = mms->in_buffer;
322  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
323  if(read_result != length_remaining) {
325  "Failed to read packet data of size %d: %d (%s)\n",
326  length_remaining, read_result,
327  read_result < 0 ? strerror(AVUNERROR(read_result)) :
328  "The server closed the connection");
329  return read_result < 0 ? read_result : AVERROR(EIO);
330  }
331 
332  // if we successfully read everything.
333  if(packet_id_type == mmst->header_packet_id) {
334  int err;
335  packet_type = SC_PKT_ASF_HEADER;
336  // Store the asf header
337  if(!mms->header_parsed) {
338  if ((err = av_reallocp(&mms->asf_header,
339  mms->asf_header_size +
340  mms->remaining_in_len)) < 0) {
341  mms->asf_header_size = 0;
342  return err;
343  }
344  memcpy(mms->asf_header + mms->asf_header_size,
345  mms->read_in_ptr, mms->remaining_in_len);
346  mms->asf_header_size += mms->remaining_in_len;
347  }
348  // 0x04 means asf header is sent in multiple packets.
349  if (mmst->incoming_flags == 0x04)
350  continue;
351  } else if(packet_id_type == mmst->packet_id) {
352  packet_type = SC_PKT_ASF_MEDIA;
353  } else {
354  av_dlog(NULL, "packet id type %d is old.", packet_id_type);
355  continue;
356  }
357  }
358 
359  // preprocess some packet type
360  if(packet_type == SC_PKT_KEEPALIVE) {
361  send_keepalive_packet(mmst);
362  continue;
363  } else if(packet_type == SC_PKT_STREAM_CHANGING) {
365  } else if(packet_type == SC_PKT_ASF_MEDIA) {
366  pad_media_packet(mms);
367  }
368  return packet_type;
369  }
370 }
371 
373  int (*send_fun)(MMSTContext *mmst),
374  const MMSSCPacketType expect_type)
375 {
376  MMSSCPacketType type;
377  if(send_fun) {
378  int ret = send_fun(mmst);
379  if (ret < 0) {
380  av_dlog(NULL, "Send Packet error before expecting recv packet %d\n", expect_type);
381  return ret;
382  }
383  }
384 
385  if ((type = get_tcp_server_response(mmst)) != expect_type) {
387  "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
388  type, expect_type);
389  return AVERROR_INVALIDDATA;
390  } else {
391  return 0;
392  }
393 }
394 
396 {
397  MMSContext *mms = &mmst->mms;
399  insert_command_prefixes(mms, 1, 0);
400  bytestream_put_le32(&mms->write_out_ptr, 0);
401  bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
402  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
403  bytestream_put_le32(&mms->write_out_ptr, 0);
404  bytestream_put_le32(&mms->write_out_ptr, 0);
405  bytestream_put_le32(&mms->write_out_ptr, 0);
406 
407  // the media preroll value in milliseconds?
408  bytestream_put_le32(&mms->write_out_ptr, 0);
409  bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
410  bytestream_put_le32(&mms->write_out_ptr, 2);
411  bytestream_put_le32(&mms->write_out_ptr, 0);
412 
413  return send_command_packet(mmst);
414 }
415 
418 {
419  char data_string[256];
420  MMSContext *mms = &mmst->mms;
421  // SubscriberName is defined in MS specification linked below.
422  // The guid value can be any valid value.
423  // http://download.microsoft.com/
424  // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
425  snprintf(data_string, sizeof(data_string),
426  "NSPlayer/7.0.0.1956; {%s}; Host: %s",
427  "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
428 
430  insert_command_prefixes(mms, 0, 0x0004000b);
431  bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
432  mms_put_utf16(mms, data_string);
433  return send_command_packet(mmst);
434 }
435 
438 {
439  int i;
440  MMSContext *mms = &mmst->mms;
441  // send the streams we want back...
443  bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums
444  for(i= 0; i<mms->stream_num; i++) {
445  bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags
446  bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id
447  bytestream_put_le16(&mms->write_out_ptr, 0); // selection
448  }
449  return send_command_packet(mmst);
450 }
451 
453 {
455  insert_command_prefixes(&mmst->mms, 1, 1);
456 
457  return send_command_packet(mmst);
458 }
459 
461 static int mms_close(URLContext *h)
462 {
463  MMSTContext *mmst = (MMSTContext *)h->priv_data;
464  MMSContext *mms = &mmst->mms;
465  if(mms->mms_hd) {
466  send_close_packet(mmst);
467  ffurl_close(mms->mms_hd);
468  }
469 
470  /* free all separately allocated pointers in mms */
471  av_free(mms->streams);
472  av_free(mms->asf_header);
473 
474  return 0;
475 }
476 
478 {
479  MMSContext *mms = &mmst->mms;
481  insert_command_prefixes(mms, 1, 0x0001FFFF);
482  bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp
483  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown
484  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset
485  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
486  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
487  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
488  bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag
489 
490  mmst->packet_id++; // new packet_id
491  bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
492  return send_command_packet(mmst);
493 }
494 
495 
497 {
498  mms->remaining_in_len = 0;
499  mms->read_in_ptr = mms->in_buffer;
500 }
501 
502 static int mms_open(URLContext *h, const char *uri, int flags)
503 {
504  MMSTContext *mmst = h->priv_data;
505  MMSContext *mms;
506  int port, err;
507  char tcpname[256];
508 
509  h->is_streamed = 1;
510  mms = &mmst->mms;
511 
512  // only for MMS over TCP, so set proto = NULL
513  av_url_split(NULL, 0, NULL, 0,
514  mmst->host, sizeof(mmst->host), &port, mmst->path,
515  sizeof(mmst->path), uri);
516 
517  if(port<0)
518  port = 1755; // defaut mms protocol port
519 
520  // establish tcp connection.
521  ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
522  err = ffurl_open(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
523  &h->interrupt_callback, NULL);
524  if (err)
525  goto fail;
526 
527  mmst->packet_id = 3; // default, initial value.
528  mmst->header_packet_id = 2; // default, initial value.
530  if (err)
531  goto fail;
533  if (err)
534  goto fail;
536  if (err)
537  goto fail;
539  if (err)
540  goto fail;
542  if (err)
543  goto fail;
545  if (err)
546  goto fail;
547  if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
549  "The server does not support MMST (try MMSH or RTSP)\n");
550  err = AVERROR(EINVAL);
551  goto fail;
552  }
553  err = ff_mms_asf_header_parser(mms);
554  if (err) {
555  av_dlog(NULL, "asf header parsed failed!\n");
556  goto fail;
557  }
558  mms->header_parsed = 1;
559 
560  if (!mms->asf_packet_len || !mms->stream_num)
561  goto fail;
562 
565  if (err)
566  goto fail;
567  // send media packet request
569  if (err) {
570  goto fail;
571  }
572  av_dlog(NULL, "Leaving open (success)\n");
573  return 0;
574 fail:
575  mms_close(h);
576  av_dlog(NULL, "Leaving open (failure: %d)\n", err);
577  return err;
578 }
579 
581 static int mms_read(URLContext *h, uint8_t *buf, int size)
582 {
583  /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
584  MMSTContext *mmst = h->priv_data;
585  MMSContext *mms = &mmst->mms;
586  int result = 0;
587 
588  do {
589  if(mms->asf_header_read_size < mms->asf_header_size) {
590  /* Read from ASF header buffer */
591  result = ff_mms_read_header(mms, buf, size);
592  } else if(mms->remaining_in_len) {
593  /* Read remaining packet data to buffer.
594  * the result can not be zero because remaining_in_len is positive.*/
595  result = ff_mms_read_data(mms, buf, size);
596  } else {
597  /* Read from network */
598  int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
599  if (err == 0) {
600  if(mms->remaining_in_len>mms->asf_packet_len) {
602  "Incoming pktlen %d is larger than ASF pktsize %d\n",
603  mms->remaining_in_len, mms->asf_packet_len);
604  result= AVERROR(EIO);
605  } else {
606  // copy the data to the packet buffer.
607  result = ff_mms_read_data(mms, buf, size);
608  if (result == 0) {
609  av_dlog(NULL, "Read ASF media packet size is zero!\n");
610  break;
611  }
612  }
613  } else {
614  av_dlog(NULL, "read packet error!\n");
615  break;
616  }
617  }
618  } while(!result); // only return one packet.
619  return result;
620 }
621 
623  .name = "mmst",
624  .url_open = mms_open,
625  .url_read = mms_read,
626  .url_close = mms_close,
627  .priv_data_size = sizeof(MMSTContext),
629 };
static void pad_media_packet(MMSContext *mms)
Pad media packets smaller than max_packet_size and/or adjust read position after a seek...
Definition: mmst.c:228
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:2713
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
static void start_command_packet(MMSTContext *mmst, MMSCSPacketType packet_type)
Create MMST command packet header.
Definition: mmst.c:100
int size
URLContext * mms_hd
TCP connection handle.
Definition: mms.h:31
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:35
static int send_media_file_request(MMSTContext *mmst)
Definition: mmst.c:196
char path[256]
Path of the resource being asked for.
Definition: mmst.c:91
uint8_t * read_in_ptr
Pointer for reading from incoming buffer.
Definition: mms.h:43
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:276
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
Data packets.
Definition: mmst.c:83
AVIOInterruptCB interrupt_callback
Definition: url.h:50
Definition: mms.h:30
unsigned int header_packet_id
default is 2.
Definition: mmst.c:96
int ff_mms_read_header(MMSContext *mms, uint8_t *buf, const int size)
Definition: mms.c:29
int stream_num
stream numbers.
Definition: mms.h:56
#define AV_RL16
Definition: intreadwrite.h:42
av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (%s)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic?ac->func_descr_generic:ac->func_descr)
int header_parsed
The header has been received and parsed.
Definition: mms.h:51
#define FFALIGN(x, a)
Definition: common.h:62
uint8_t * asf_header
Internal handling of the ASF header.
Definition: mms.h:49
static int send_media_header_request(MMSTContext *mmst)
Definition: mmst.c:395
#define LOCAL_ADDRESS
Definition: mmst.c:40
uint8_t
MMSCSPacketType
Client to server packet types.
Definition: mmst.c:43
Pseudo packets.
Definition: mmst.c:77
#define AV_WL32(p, d)
Definition: intreadwrite.h:255
int ff_mms_read_data(MMSContext *mms, uint8_t *buf, const int size)
Definition: mms.c:44
int asf_packet_len
Definition: mms.h:52
int av_reallocp(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:140
static int flags
Definition: log.c:44
MMSSCPacketType
Server to client packet types.
Definition: mmst.c:58
URLProtocol ff_mmst_protocol
Definition: mmst.c:622
uint8_t in_buffer[65536]
Buffer for incoming packets.
Definition: mms.h:42
static int mms_open(URLContext *h, const char *uri, int flags)
Definition: mmst.c:502
int packet_id
Identifier for packets in the current stream.
Definition: mmst.c:95
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:186
#define AVERROR(e)
Definition: error.h:43
static void handle_packet_stream_changing_type(MMSTContext *mmst)
Definition: mmst.c:208
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:168
static int send_stream_selection_request(MMSTContext *mmst)
Send MMST stream selection command based on the AVStream->discard values.
Definition: mmst.c:437
static void clear_stream_buffers(MMSContext *mms)
Definition: mmst.c:496
uint8_t * write_out_ptr
Buffer for outgoing packets.
Definition: mms.h:36
static int send_close_packet(MMSTContext *mmst)
Definition: mmst.c:452
int asf_header_read_size
Definition: mms.h:53
static int send_keepalive_packet(MMSTContext *mmst)
Definition: mmst.c:218
static int mms_read(URLContext *h, uint8_t *buf, int size)
Read ASF data through the protocol.
Definition: mmst.c:581
static int send_command_packet(MMSTContext *mmst)
Send a prepared MMST command packet.
Definition: mmst.c:126
#define AV_RL32
Definition: intreadwrite.h:146
static void mms_put_utf16(MMSContext *mms, uint8_t *src)
Definition: mmst.c:155
#define LOCAL_PORT
Definition: mmst.c:41
int incoming_packet_seq
Incoming packet sequence number.
Definition: mmst.c:93
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
uint8_t out_buffer[512]
Buffer for outgoing packet.
Definition: mms.h:37
NULL
Definition: eval.c:55
int remaining_in_len
Reading length from incoming buffer.
Definition: mms.h:44
Definition: url.h:41
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:294
static int send_startup_packet(MMSTContext *mmst)
Send the initial handshake.
Definition: mmst.c:417
void * priv_data
Definition: url.h:44
int avio_put_str16le(AVIOContext *s, const char *str)
Convert an UTF-8 string to UTF-16LE and write it.
Definition: aviobuf.c:287
int incoming_flags
Incoming packet flags.
Definition: mmst.c:94
const char * name
Definition: url.h:54
static int send_time_test_data(MMSTContext *mmst)
Definition: mmst.c:167
int asf_header_size
Size of stored ASF header.
Definition: mms.h:50
int ffurl_close(URLContext *h)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:297
static void insert_command_prefixes(MMSContext *mms, uint32_t prefix1, uint32_t prefix2)
Add prefixes to MMST command packet.
Definition: mmst.c:118
Main libavformat public API header.
int outgoing_packet_seq
Outgoing packet sequence number.
Definition: mmst.c:90
int ffio_init_context(AVIOContext *s, unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Definition: aviobuf.c:70
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:211
Control packets.
Definition: mmst.c:61
static int send_media_packet_request(MMSTContext *mmst)
Definition: mmst.c:477
int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
Read as many bytes as possible (up to size), calling the read function multiple times if necessary...
Definition: avio.c:269
#define AVUNERROR(e)
Definition: error.h:44
static int send_protocol_select(MMSTContext *mmst)
Definition: mmst.c:174
int id
Definition: mms.h:27
int len
static int mms_safe_send_recv(MMSTContext *mmst, int(*send_fun)(MMSTContext *mmst), const MMSSCPacketType expect_type)
Definition: mmst.c:372
MMSStream * streams
Definition: mms.h:32
unbuffered private I/O API
MMSContext mms
Definition: mmst.c:89
static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst)
Read incoming MMST media, header or command packet.
Definition: mmst.c:238
char host[128]
Host of the resources.
Definition: mmst.c:92
static int mms_close(URLContext *h)
Close the MMSH/MMST connection.
Definition: mmst.c:461
#define MKTAG(a, b, c, d)
Definition: common.h:238
int ff_mms_asf_header_parser(MMSContext *mms)
Definition: mms.c:54