FFmpeg
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:4743
#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
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
GLint GLenum type
Definition: opengl_enc.c:104
#define src
Definition: vp8dsp.c:254
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:87
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
MMSSCPacketType
Server to client packet types.
Definition: mmst.c:58
ptrdiff_t size
Definition: opengl_enc.c:100
#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 i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
const char * protocol_whitelist
Definition: url.h:49
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:121
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 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:766
Definition: url.h:38
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:676
static int send_startup_packet(MMSTContext *mmst)
Send the initial handshake.
Definition: mmst.c:424
void * priv_data
Definition: url.h:41
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
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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
and forward the result(frame or status change) to the corresponding input.If nothing is possible
#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
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
#define MKTAG(a, b, c, d)
Definition: common.h:366
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:87
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