FFmpeg  4.0
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 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 
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 /** Client to server packet types. */
43 typedef enum {
56 
57 /** Server to client packet types. */
58 typedef enum {
59  /** Control packets. */
60  /*@{*/
73  /*@}*/
74 
75  /** Pseudo packets. */
76  /*@{*/
79  /*@}*/
80 
81  /** Data packets. */
82  /*@{*/
83  SC_PKT_ASF_HEADER = 0x010000,// make it bigger than 0xFF in case of
84  SC_PKT_ASF_MEDIA = 0x010001,// receiving false data packets.
85  /*@}*/
87 
88 typedef struct MMSTContext {
90  int outgoing_packet_seq; ///< Outgoing packet sequence number.
91  char path[256]; ///< Path of the resource being asked for.
92  char host[128]; ///< Host of the resources.
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 } MMSTContext;
98 
99 /** Create MMST command packet header */
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 
117 /** Add prefixes to MMST command packet. */
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 
125 /** Send a prepared MMST command packet. */
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 int mms_put_utf16(MMSContext *mms, const 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  if (len < 0)
165  return len;
166  mms->write_out_ptr += len;
167  return 0;
168 }
169 
171 {
173  insert_command_prefixes(&mmst->mms, 0x00f0f0f0, 0x0004000b);
174  return send_command_packet(mmst);
175 }
176 
178 {
179  int ret;
180  char data_string[256];
181  MMSContext *mms = &mmst->mms;
182 
184  insert_command_prefixes(mms, 0, 0xffffffff);
185  bytestream_put_le32(&mms->write_out_ptr, 0); // maxFunnelBytes
186  bytestream_put_le32(&mms->write_out_ptr, 0x00989680); // maxbitRate
187  bytestream_put_le32(&mms->write_out_ptr, 2); // funnelMode
188  snprintf(data_string, sizeof(data_string), "\\\\%d.%d.%d.%d\\%s\\%d",
189  (LOCAL_ADDRESS>>24)&0xff,
190  (LOCAL_ADDRESS>>16)&0xff,
191  (LOCAL_ADDRESS>>8)&0xff,
192  LOCAL_ADDRESS&0xff,
193  "TCP", // or UDP
194  LOCAL_PORT);
195 
196  if ((ret = mms_put_utf16(mms, data_string)) < 0)
197  return ret;
198  return send_command_packet(mmst);
199 }
200 
202 {
203  int ret;
204  MMSContext *mms = &mmst->mms;
206  insert_command_prefixes(mms, 1, 0xffffffff);
207  bytestream_put_le32(&mms->write_out_ptr, 0);
208  bytestream_put_le32(&mms->write_out_ptr, 0);
209  if ((ret = mms_put_utf16(mms, mmst->path + 1)) < 0) // +1 for skip "/"
210  return ret;
211 
212  return send_command_packet(mmst);
213 }
214 
216 {
217  MMSContext *mms = &mmst->mms;
218  av_log(NULL, AV_LOG_TRACE, "Stream changing!\n");
219 
220  // 40 is the packet header size, 7 is the prefix size.
221  mmst->header_packet_id= AV_RL32(mms->in_buffer + 40 + 7);
222  av_log(NULL, AV_LOG_TRACE, "Changed header prefix to 0x%x", mmst->header_packet_id);
223 }
224 
226 {
227  // respond to a keepalive with a keepalive...
229  insert_command_prefixes(&mmst->mms, 1, 0x100FFFF);
230  return send_command_packet(mmst);
231 }
232 
233 /** Pad media packets smaller than max_packet_size and/or adjust read position
234  * after a seek. */
236 {
237  if(mms->remaining_in_len<mms->asf_packet_len) {
238  int padding_size = mms->asf_packet_len - mms->remaining_in_len;
239  memset(mms->in_buffer + mms->remaining_in_len, 0, padding_size);
240  mms->remaining_in_len += padding_size;
241  }
242 }
243 
244 /** Read incoming MMST media, header or command packet. */
246 {
247  int read_result;
248  MMSSCPacketType packet_type= -1;
249  MMSContext *mms = &mmst->mms;
250  for(;;) {
251  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8);
252  if (read_result != 8) {
253  if(read_result < 0) {
255  "Error reading packet header: %d (%s)\n",
256  read_result, strerror(AVUNERROR(read_result)));
257  packet_type = SC_PKT_CANCEL;
258  } else {
260  "The server closed the connection\n");
261  packet_type = SC_PKT_NO_DATA;
262  }
263  return packet_type;
264  }
265 
266  // handle command packet.
267  if(AV_RL32(mms->in_buffer + 4)==0xb00bface) {
268  int length_remaining, hr;
269 
270  mmst->incoming_flags= mms->in_buffer[3];
271  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4);
272  if(read_result != 4) {
274  "Reading command packet length failed: %d (%s)\n",
275  read_result,
276  read_result < 0 ? strerror(AVUNERROR(read_result)) :
277  "The server closed the connection");
278  return read_result < 0 ? read_result : AVERROR(EIO);
279  }
280 
281  length_remaining= AV_RL32(mms->in_buffer+8) + 4;
282  av_log(NULL, AV_LOG_TRACE, "Length remaining is %d\n", length_remaining);
283  // read the rest of the packet.
284  if (length_remaining < 0
285  || length_remaining > sizeof(mms->in_buffer) - 12) {
287  "Incoming packet length %d exceeds bufsize %"SIZE_SPECIFIER"\n",
288  length_remaining, sizeof(mms->in_buffer) - 12);
289  return AVERROR_INVALIDDATA;
290  }
291  read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12,
292  length_remaining) ;
293  if (read_result != length_remaining) {
295  "Reading pkt data (length=%d) failed: %d (%s)\n",
296  length_remaining, read_result,
297  read_result < 0 ? strerror(AVUNERROR(read_result)) :
298  "The server closed the connection");
299  return read_result < 0 ? read_result : AVERROR(EIO);
300  }
301  packet_type= AV_RL16(mms->in_buffer+36);
302  if (read_result >= 44 && (hr = AV_RL32(mms->in_buffer + 40))) {
304  "Server sent a message with packet type 0x%x and error status code 0x%08x\n", packet_type, hr);
305  return AVERROR(EINVAL);
306  }
307  } else {
308  int length_remaining;
309  int packet_id_type;
310  int tmp;
311 
312  // note we cache the first 8 bytes,
313  // then fill up the buffer with the others
314  tmp = AV_RL16(mms->in_buffer + 6);
315  length_remaining = (tmp - 8) & 0xffff;
316  mmst->incoming_packet_seq = AV_RL32(mms->in_buffer);
317  packet_id_type = mms->in_buffer[4];
318  mmst->incoming_flags = mms->in_buffer[5];
319 
320  if (length_remaining < 0
321  || length_remaining > sizeof(mms->in_buffer) - 8) {
323  "Data length %d is invalid or too large (max=%"SIZE_SPECIFIER")\n",
324  length_remaining, sizeof(mms->in_buffer));
325  return AVERROR_INVALIDDATA;
326  }
327  mms->remaining_in_len = length_remaining;
328  mms->read_in_ptr = mms->in_buffer;
329  read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining);
330  if(read_result != length_remaining) {
332  "Failed to read packet data of size %d: %d (%s)\n",
333  length_remaining, read_result,
334  read_result < 0 ? strerror(AVUNERROR(read_result)) :
335  "The server closed the connection");
336  return read_result < 0 ? read_result : AVERROR(EIO);
337  }
338 
339  // if we successfully read everything.
340  if(packet_id_type == mmst->header_packet_id) {
341  int err;
342  packet_type = SC_PKT_ASF_HEADER;
343  // Store the asf header
344  if(!mms->header_parsed) {
345  if ((err = av_reallocp(&mms->asf_header,
346  mms->asf_header_size +
347  mms->remaining_in_len)) < 0) {
348  mms->asf_header_size = 0;
349  return err;
350  }
351  memcpy(mms->asf_header + mms->asf_header_size,
352  mms->read_in_ptr, mms->remaining_in_len);
353  mms->asf_header_size += mms->remaining_in_len;
354  }
355  // 0x04 means asf header is sent in multiple packets.
356  if (mmst->incoming_flags == 0x04)
357  continue;
358  } else if(packet_id_type == mmst->packet_id) {
359  packet_type = SC_PKT_ASF_MEDIA;
360  } else {
361  av_log(NULL, AV_LOG_TRACE, "packet id type %d is old.", packet_id_type);
362  continue;
363  }
364  }
365 
366  // preprocess some packet type
367  if(packet_type == SC_PKT_KEEPALIVE) {
368  send_keepalive_packet(mmst);
369  continue;
370  } else if(packet_type == SC_PKT_STREAM_CHANGING) {
372  } else if(packet_type == SC_PKT_ASF_MEDIA) {
373  pad_media_packet(mms);
374  }
375  return packet_type;
376  }
377 }
378 
380  int (*send_fun)(MMSTContext *mmst),
381  const MMSSCPacketType expect_type)
382 {
384  if(send_fun) {
385  int ret = send_fun(mmst);
386  if (ret < 0) {
387  av_log(NULL, AV_LOG_TRACE, "Send Packet error before expecting recv packet %d\n", expect_type);
388  return ret;
389  }
390  }
391 
392  if ((type = get_tcp_server_response(mmst)) != expect_type) {
394  "Corrupt stream (unexpected packet type 0x%x, expected 0x%x)\n",
395  type, expect_type);
396  return AVERROR_INVALIDDATA;
397  } else {
398  return 0;
399  }
400 }
401 
403 {
404  MMSContext *mms = &mmst->mms;
406  insert_command_prefixes(mms, 1, 0);
407  bytestream_put_le32(&mms->write_out_ptr, 0);
408  bytestream_put_le32(&mms->write_out_ptr, 0x00800000);
409  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff);
410  bytestream_put_le32(&mms->write_out_ptr, 0);
411  bytestream_put_le32(&mms->write_out_ptr, 0);
412  bytestream_put_le32(&mms->write_out_ptr, 0);
413 
414  // the media preroll value in milliseconds?
415  bytestream_put_le32(&mms->write_out_ptr, 0);
416  bytestream_put_le32(&mms->write_out_ptr, 0x40AC2000);
417  bytestream_put_le32(&mms->write_out_ptr, 2);
418  bytestream_put_le32(&mms->write_out_ptr, 0);
419 
420  return send_command_packet(mmst);
421 }
422 
423 /** Send the initial handshake. */
425 {
426  char data_string[256];
427  int ret;
428  MMSContext *mms = &mmst->mms;
429  // SubscriberName is defined in MS specification linked below.
430  // The GUID value can be any valid value.
431  // http://download.microsoft.com/
432  // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
433  snprintf(data_string, sizeof(data_string),
434  "NSPlayer/7.0.0.1956; {%s}; Host: %s",
435  "7E667F5D-A661-495E-A512-F55686DDA178", mmst->host);
436 
438  insert_command_prefixes(mms, 0, 0x0004000b);
439  bytestream_put_le32(&mms->write_out_ptr, 0x0003001c);
440  if ((ret = mms_put_utf16(mms, data_string)) < 0)
441  return ret;
442  return send_command_packet(mmst);
443 }
444 
445 /** Send MMST stream selection command based on the AVStream->discard values. */
447 {
448  int i;
449  MMSContext *mms = &mmst->mms;
450  // send the streams we want back...
452  bytestream_put_le32(&mms->write_out_ptr, mms->stream_num); // stream nums
453  for(i= 0; i<mms->stream_num; i++) {
454  bytestream_put_le16(&mms->write_out_ptr, 0xffff); // flags
455  bytestream_put_le16(&mms->write_out_ptr, mms->streams[i].id); // stream id
456  bytestream_put_le16(&mms->write_out_ptr, 0); // selection
457  }
458  return send_command_packet(mmst);
459 }
460 
462 {
464  insert_command_prefixes(&mmst->mms, 1, 1);
465 
466  return send_command_packet(mmst);
467 }
468 
469 /** Close the MMSH/MMST connection */
470 static int mms_close(URLContext *h)
471 {
472  MMSTContext *mmst = (MMSTContext *)h->priv_data;
473  MMSContext *mms = &mmst->mms;
474  if(mms->mms_hd) {
475  send_close_packet(mmst);
477  }
478 
479  /* free all separately allocated pointers in mms */
480  av_freep(&mms->streams);
482 
483  return 0;
484 }
485 
487 {
488  MMSContext *mms = &mmst->mms;
490  insert_command_prefixes(mms, 1, 0x0001FFFF);
491  bytestream_put_le64(&mms->write_out_ptr, 0); // seek timestamp
492  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // unknown
493  bytestream_put_le32(&mms->write_out_ptr, 0xffffffff); // packet offset
494  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
495  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
496  bytestream_put_byte(&mms->write_out_ptr, 0xff); // max stream time limit
497  bytestream_put_byte(&mms->write_out_ptr, 0x00); // stream time limit flag
498 
499  mmst->packet_id++; // new packet_id
500  bytestream_put_le32(&mms->write_out_ptr, mmst->packet_id);
501  return send_command_packet(mmst);
502 }
503 
504 
506 {
507  mms->remaining_in_len = 0;
508  mms->read_in_ptr = mms->in_buffer;
509 }
510 
511 static int mms_open(URLContext *h, const char *uri, int flags)
512 {
513  MMSTContext *mmst = h->priv_data;
514  MMSContext *mms;
515  int port, err;
516  char tcpname[256];
517 
518  h->is_streamed = 1;
519  mms = &mmst->mms;
520 
521  // only for MMS over TCP, so set proto = NULL
522  av_url_split(NULL, 0, NULL, 0,
523  mmst->host, sizeof(mmst->host), &port, mmst->path,
524  sizeof(mmst->path), uri);
525 
526  if(port<0)
527  port = 1755; // default MMS protocol port
528 
529  // establish tcp connection.
530  ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
531  err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
534  if (err)
535  goto fail;
536 
537  mmst->packet_id = 3; // default, initial value.
538  mmst->header_packet_id = 2; // default, initial value.
540  if (err)
541  goto fail;
543  if (err)
544  goto fail;
546  if (err)
547  goto fail;
549  if (err)
550  goto fail;
552  if (err)
553  goto fail;
555  if (err)
556  goto fail;
557  if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) {
559  "The server does not support MMST (try MMSH or RTSP)\n");
560  err = AVERROR(EINVAL);
561  goto fail;
562  }
563  err = ff_mms_asf_header_parser(mms);
564  if (err) {
565  av_log(NULL, AV_LOG_TRACE, "asf header parsed failed!\n");
566  goto fail;
567  }
568  mms->header_parsed = 1;
569 
570  if (!mms->asf_packet_len || !mms->stream_num)
571  goto fail;
572 
575  if (err)
576  goto fail;
577  // send media packet request
579  if (err) {
580  goto fail;
581  }
582  av_log(NULL, AV_LOG_TRACE, "Leaving open (success)\n");
583  return 0;
584 fail:
585  mms_close(h);
586  av_log(NULL, AV_LOG_TRACE, "Leaving open (failure: %d)\n", err);
587  return err;
588 }
589 
590 /** Read ASF data through the protocol. */
591 static int mms_read(URLContext *h, uint8_t *buf, int size)
592 {
593  /* TODO: see tcp.c:tcp_read() about a possible timeout scheme */
594  MMSTContext *mmst = h->priv_data;
595  MMSContext *mms = &mmst->mms;
596  int result = 0;
597 
598  do {
599  if(mms->asf_header_read_size < mms->asf_header_size) {
600  /* Read from ASF header buffer */
601  result = ff_mms_read_header(mms, buf, size);
602  } else if(mms->remaining_in_len) {
603  /* Read remaining packet data to buffer.
604  * the result can not be zero because remaining_in_len is positive.*/
605  result = ff_mms_read_data(mms, buf, size);
606  } else {
607  /* Read from network */
608  int err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_MEDIA);
609  if (err == 0) {
610  if(mms->remaining_in_len>mms->asf_packet_len) {
612  "Incoming pktlen %d is larger than ASF pktsize %d\n",
613  mms->remaining_in_len, mms->asf_packet_len);
614  result= AVERROR(EIO);
615  } else {
616  // copy the data to the packet buffer.
617  result = ff_mms_read_data(mms, buf, size);
618  if (result == 0) {
619  av_log(NULL, AV_LOG_TRACE, "Read ASF media packet size is zero!\n");
620  break;
621  }
622  }
623  } else {
624  av_log(NULL, AV_LOG_TRACE, "read packet error!\n");
625  break;
626  }
627  }
628  } while(!result); // only return one packet.
629  return result;
630 }
631 
633  .name = "mmst",
634  .url_open = mms_open,
635  .url_read = mms_read,
636  .url_close = mms_close,
637  .priv_data_size = sizeof(MMSTContext),
639 };
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:235
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:4691
#define NULL
Definition: coverity.c:32
Bytestream IO Context.
Definition: avio.h:161
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
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
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:307
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
static int send_media_file_request(MMSTContext *mmst)
Definition: mmst.c:201
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:421
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
Data packets.
Definition: mmst.c:83
AVIOInterruptCB interrupt_callback
Definition: url.h:47
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
#define src
Definition: vp8dsp.c:254
int header_parsed
The header has been received and parsed.
Definition: mms.h:51
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:402
#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_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
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
static int flags
Definition: log.c:55
MMSSCPacketType
Server to client packet types.
Definition: mmst.c:58
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
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:511
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:176
const char * protocol_whitelist
Definition: url.h:49
#define AVERROR(e)
Definition: error.h:43
static void handle_packet_stream_changing_type(MMSTContext *mmst)
Definition: mmst.c:215
static int send_stream_selection_request(MMSTContext *mmst)
Send MMST stream selection command based on the AVStream->discard values.
Definition: mmst.c:446
static void clear_stream_buffers(MMSContext *mms)
Definition: mmst.c:505
#define fail()
Definition: checkasm.h:116
uint8_t * write_out_ptr
Buffer for outgoing packets.
Definition: mms.h:36
static int send_close_packet(MMSTContext *mmst)
Definition: mmst.c:461
int asf_header_read_size
Definition: mms.h:53
static int send_keepalive_packet(MMSTContext *mmst)
Definition: mmst.c:225
static int mms_read(URLContext *h, uint8_t *buf, int size)
Read ASF data through the protocol.
Definition: mmst.c:591
static int send_command_packet(MMSTContext *mmst)
Send a prepared MMST command packet.
Definition: mmst.c:126
#define AV_RL32
Definition: intreadwrite.h:146
#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
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
const char * protocol_blacklist
Definition: url.h:50
int remaining_in_len
Reading length from incoming buffer.
Definition: mms.h:44
static int mms_put_utf16(MMSContext *mms, const uint8_t *src)
Definition: mmst.c:155
const URLProtocol ff_mmst_protocol
Definition: mmst.c:632
void * buf
Definition: avisynth_c.h:690
Definition: url.h:38
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:656
static int send_startup_packet(MMSTContext *mmst)
Send the initial handshake.
Definition: mmst.c:424
void * priv_data
Definition: url.h:41
cl_device_type type
int avio_put_str16le(AVIOContext *s, const char *str)
Convert an UTF-8 string to UTF-16LE and write it.
#define snprintf
Definition: snprintf.h:34
int incoming_flags
Incoming packet flags.
Definition: mmst.c:94
const char * name
Definition: url.h:55
static int send_time_test_data(MMSTContext *mmst)
Definition: mmst.c:170
#define SIZE_SPECIFIER
Definition: internal.h:262
int asf_header_size
Size of stored ASF header.
Definition: mms.h:50
int ffurl_close(URLContext *h)
Definition: avio.c:467
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:81
Control packets.
Definition: mmst.c:61
static int send_media_packet_request(MMSTContext *mmst)
Definition: mmst.c:486
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:414
#define AVUNERROR(e)
Definition: error.h:44
static int send_protocol_select(MMSTContext *mmst)
Definition: mmst.c:177
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:379
MMSStream * streams
Definition: mms.h:32
#define av_freep(p)
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:245
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:470
#define MKTAG(a, b, c, d)
Definition: common.h:366
int ff_mms_asf_header_parser(MMSContext *mms)
Definition: mms.c:54
#define AV_WL32(p, v)
Definition: intreadwrite.h:426
static uint8_t tmp[11]
Definition: aes_ctr.c:26