FFmpeg
mmsh.c
Go to the documentation of this file.
1 /*
2  * MMS protocol over HTTP
3  * Copyright (c) 2010 Zhentan Feng <spyfeng at gmail dot com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  * Reference
24  * Windows Media HTTP Streaming Protocol.
25  * http://msdn.microsoft.com/en-us/library/cc251059(PROT.10).aspx
26  */
27 
28 #include <string.h>
29 #include "libavutil/intreadwrite.h"
30 #include "libavutil/avstring.h"
31 #include "libavutil/opt.h"
32 #include "internal.h"
33 #include "mms.h"
34 #include "http.h"
35 #include "url.h"
36 
37 #define CHUNK_HEADER_LENGTH 4 // 2bytes chunk type and 2bytes chunk length.
38 #define EXT_HEADER_LENGTH 8 // 4bytes sequence, 2bytes useless and 2bytes chunk length.
39 
40 // see Ref 2.2.1.8
41 #define USERAGENT "User-Agent: NSPlayer/4.1.0.3856\r\n"
42 // see Ref 2.2.1.4.33
43 // the GUID value can be changed to any valid value.
44 #define CLIENTGUID "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}\r\n"
45 
46 // see Ref 2.2.3 for packet type define:
47 // chunk type contains 2 fields: Frame and PacketID.
48 // Frame is 0x24 or 0xA4(rarely), different PacketID indicates different packet type.
49 typedef enum {
50  CHUNK_TYPE_DATA = 0x4424,
52  CHUNK_TYPE_END = 0x4524,
54 } ChunkType;
55 
56 typedef struct MMSHContext {
58  uint8_t location[1024];
59  int request_seq; ///< request packet sequence
60  int chunk_seq; ///< data packet sequence
61 } MMSHContext;
62 
63 static int mmsh_close(URLContext *h)
64 {
65  MMSHContext *mmsh = (MMSHContext *)h->priv_data;
66  MMSContext *mms = &mmsh->mms;
67  ffurl_closep(&mms->mms_hd);
68  av_freep(&mms->streams);
69  av_freep(&mms->asf_header);
70  return 0;
71 }
72 
74 {
75  MMSContext *mms = &mmsh->mms;
76  uint8_t chunk_header[CHUNK_HEADER_LENGTH];
77  uint8_t ext_header[EXT_HEADER_LENGTH];
78  ChunkType chunk_type;
79  int chunk_len, res, ext_header_len;
80 
81  res = ffurl_read_complete(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH);
82  if (res != CHUNK_HEADER_LENGTH) {
83  av_log(NULL, AV_LOG_ERROR, "Read data packet header failed!\n");
84  return AVERROR(EIO);
85  }
86  chunk_type = AV_RL16(chunk_header);
87  chunk_len = AV_RL16(chunk_header + 2);
88 
89  switch (chunk_type) {
90  case CHUNK_TYPE_END:
92  ext_header_len = 4;
93  break;
95  case CHUNK_TYPE_DATA:
96  ext_header_len = 8;
97  break;
98  default:
99  av_log(NULL, AV_LOG_ERROR, "Strange chunk type %d\n", chunk_type);
100  return AVERROR_INVALIDDATA;
101  }
102 
103  res = ffurl_read_complete(mms->mms_hd, ext_header, ext_header_len);
104  if (res != ext_header_len) {
105  av_log(NULL, AV_LOG_ERROR, "Read ext header failed!\n");
106  return AVERROR(EIO);
107  }
108  *len = chunk_len - ext_header_len;
109  if (chunk_type == CHUNK_TYPE_END || chunk_type == CHUNK_TYPE_DATA)
110  mmsh->chunk_seq = AV_RL32(ext_header);
111  return chunk_type;
112 }
113 
114 static int read_data_packet(MMSHContext *mmsh, const int len)
115 {
116  MMSContext *mms = &mmsh->mms;
117  int res;
118  if (len > sizeof(mms->in_buffer)) {
120  "Data packet length %d exceeds the in_buffer size %"SIZE_SPECIFIER"\n",
121  len, sizeof(mms->in_buffer));
122  return AVERROR(EIO);
123  }
124  res = ffurl_read_complete(mms->mms_hd, mms->in_buffer, len);
125  av_log(NULL, AV_LOG_TRACE, "Data packet len = %d\n", len);
126  if (res != len) {
127  av_log(NULL, AV_LOG_ERROR, "Read data packet failed!\n");
128  return AVERROR(EIO);
129  }
130  if (len > mms->asf_packet_len) {
132  "Chunk length %d exceed packet length %d\n",len, mms->asf_packet_len);
133  return AVERROR_INVALIDDATA;
134  } else {
135  memset(mms->in_buffer + len, 0, mms->asf_packet_len - len); // padding
136  }
137  mms->read_in_ptr = mms->in_buffer;
138  mms->remaining_in_len = mms->asf_packet_len;
139  return 0;
140 }
141 
143 {
144  MMSContext *mms = &mmsh->mms;
145  int res, len;
146  ChunkType chunk_type;
147 
148  for (;;) {
149  len = 0;
150  res = chunk_type = get_chunk_header(mmsh, &len);
151  if (res < 0) {
152  return res;
153  } else if (chunk_type == CHUNK_TYPE_ASF_HEADER){
154  // get asf header and stored it
155  if (!mms->header_parsed) {
156  if (mms->asf_header) {
157  if (len != mms->asf_header_size) {
158  mms->asf_header_size = len;
159  av_log(NULL, AV_LOG_TRACE, "Header len changed from %d to %d\n",
160  mms->asf_header_size, len);
161  av_freep(&mms->asf_header);
162  }
163  }
164  mms->asf_header = av_mallocz(len);
165  if (!mms->asf_header) {
166  return AVERROR(ENOMEM);
167  }
168  mms->asf_header_size = len;
169  }
170  if (len > mms->asf_header_size) {
172  "Asf header packet len = %d exceed the asf header buf size %d\n",
173  len, mms->asf_header_size);
174  return AVERROR(EIO);
175  }
176  res = ffurl_read_complete(mms->mms_hd, mms->asf_header, len);
177  if (res != len) {
179  "Recv asf header data len %d != expected len %d\n", res, len);
180  return AVERROR(EIO);
181  }
182  mms->asf_header_size = len;
183  if (!mms->header_parsed) {
184  res = ff_mms_asf_header_parser(mms);
185  mms->header_parsed = 1;
186  return res;
187  }
188  } else if (chunk_type == CHUNK_TYPE_DATA) {
189  // read data packet and do padding
190  return read_data_packet(mmsh, len);
191  } else {
192  if (len) {
193  if (len > sizeof(mms->in_buffer)) {
195  "Other packet len = %d exceed the in_buffer size %"SIZE_SPECIFIER"\n",
196  len, sizeof(mms->in_buffer));
197  return AVERROR(EIO);
198  }
199  res = ffurl_read_complete(mms->mms_hd, mms->in_buffer, len);
200  if (res != len) {
201  av_log(NULL, AV_LOG_ERROR, "Read other chunk type data failed!\n");
202  return AVERROR(EIO);
203  } else {
204  av_log(NULL, AV_LOG_TRACE, "Skip chunk type %d \n", chunk_type);
205  continue;
206  }
207  }
208  }
209  }
210 }
211 
212 static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int timestamp, int64_t pos)
213 {
214  int i, port, err;
215  char httpname[256], path[256], host[128];
216  char *stream_selection = NULL;
217  char headers[1024];
218  MMSHContext *mmsh = h->priv_data;
219  MMSContext *mms;
220 
221  mmsh->request_seq = h->is_streamed = 1;
222  mms = &mmsh->mms;
223  av_strlcpy(mmsh->location, uri, sizeof(mmsh->location));
224 
225  av_url_split(NULL, 0, NULL, 0,
226  host, sizeof(host), &port, path, sizeof(path), mmsh->location);
227  if (port<0)
228  port = 80; // default mmsh protocol port
229  ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, "%s", path);
230 
231  if (ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
232  &h->interrupt_callback) < 0) {
233  return AVERROR(EIO);
234  }
235 
236  snprintf(headers, sizeof(headers),
237  "Accept: */*\r\n"
238  USERAGENT
239  "Host: %s:%d\r\n"
240  "Pragma: no-cache,rate=1.000000,stream-time=0,"
241  "stream-offset=0:0,request-context=%u,max-duration=0\r\n"
242  CLIENTGUID
243  "Connection: Close\r\n",
244  host, port, mmsh->request_seq++);
245  av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0);
246 
247  if (!mms->mms_hd->protocol_whitelist && h->protocol_whitelist) {
248  mms->mms_hd->protocol_whitelist = av_strdup(h->protocol_whitelist);
249  if (!mms->mms_hd->protocol_whitelist) {
250  err = AVERROR(ENOMEM);
251  goto fail;
252  }
253  }
254 
255  err = ffurl_connect(mms->mms_hd, NULL);
256  if (err) {
257  goto fail;
258  }
259  err = get_http_header_data(mmsh);
260  if (err) {
261  av_log(NULL, AV_LOG_ERROR, "Get http header data failed!\n");
262  goto fail;
263  }
264 
265  // close the socket and then reopen it for sending the second play request.
266  ffurl_closep(&mms->mms_hd);
267  memset(headers, 0, sizeof(headers));
268  if ((err = ffurl_alloc(&mms->mms_hd, httpname, AVIO_FLAG_READ,
269  &h->interrupt_callback)) < 0) {
270  goto fail;
271  }
272  stream_selection = av_mallocz(mms->stream_num * 19 + 1);
273  if (!stream_selection)
274  return AVERROR(ENOMEM);
275  for (i = 0; i < mms->stream_num; i++) {
276  char tmp[20];
277  err = snprintf(tmp, sizeof(tmp), "ffff:%d:0 ", mms->streams[i].id);
278  if (err < 0)
279  goto fail;
280  av_strlcat(stream_selection, tmp, mms->stream_num * 19 + 1);
281  }
282  // send play request
283  err = snprintf(headers, sizeof(headers),
284  "Accept: */*\r\n"
285  USERAGENT
286  "Host: %s:%d\r\n"
287  "Pragma: no-cache,rate=1.000000,request-context=%u\r\n"
288  "Pragma: xPlayStrm=1\r\n"
289  CLIENTGUID
290  "Pragma: stream-switch-count=%d\r\n"
291  "Pragma: stream-switch-entry=%s\r\n"
292  "Pragma: no-cache,rate=1.000000,stream-time=%u"
293  "Connection: Close\r\n",
294  host, port, mmsh->request_seq++, mms->stream_num, stream_selection, timestamp);
295  av_freep(&stream_selection);
296  if (err < 0) {
297  av_log(NULL, AV_LOG_ERROR, "Build play request failed!\n");
298  goto fail;
299  }
300  av_log(NULL, AV_LOG_TRACE, "out_buffer is %s", headers);
301  av_opt_set(mms->mms_hd->priv_data, "headers", headers, 0);
302 
303  err = ffurl_connect(mms->mms_hd, NULL);
304  if (err) {
305  goto fail;
306  }
307 
308  err = get_http_header_data(mmsh);
309  if (err) {
310  av_log(NULL, AV_LOG_ERROR, "Get http header data failed!\n");
311  goto fail;
312  }
313 
314  av_log(NULL, AV_LOG_TRACE, "Connection successfully open\n");
315  return 0;
316 fail:
317  av_freep(&stream_selection);
318  mmsh_close(h);
319  av_log(NULL, AV_LOG_TRACE, "Connection failed with error %d\n", err);
320  return err;
321 }
322 
323 static int mmsh_open(URLContext *h, const char *uri, int flags)
324 {
325  return mmsh_open_internal(h, uri, flags, 0, 0);
326 }
327 
329 {
330  MMSContext *mms = &mmsh->mms;
331  int res, len = 0;
332  ChunkType chunk_type;
333  chunk_type = get_chunk_header(mmsh, &len);
334 
335  switch (chunk_type) {
336  case CHUNK_TYPE_END:
337  mmsh->chunk_seq = 0;
338  av_log(NULL, AV_LOG_ERROR, "Stream ended!\n");
339  return AVERROR(EIO);
341  mms->header_parsed = 0;
342  if (res = get_http_header_data(mmsh)) {
343  av_log(NULL, AV_LOG_ERROR,"Stream changed! Failed to get new header!\n");
344  return res;
345  }
346  break;
347  case CHUNK_TYPE_DATA:
348  return read_data_packet(mmsh, len);
349  default:
350  av_log(NULL, AV_LOG_ERROR, "Recv other type packet %d\n", chunk_type);
351  return AVERROR_INVALIDDATA;
352  }
353  return 0;
354 }
355 
356 static int mmsh_read(URLContext *h, uint8_t *buf, int size)
357 {
358  int res = 0;
359  MMSHContext *mmsh = h->priv_data;
360  MMSContext *mms = &mmsh->mms;
361  do {
362  if (mms->asf_header_read_size < mms->asf_header_size) {
363  // copy asf header into buffer
364  res = ff_mms_read_header(mms, buf, size);
365  } else {
366  if (!mms->remaining_in_len && (res = handle_chunk_type(mmsh)))
367  return res;
368  res = ff_mms_read_data(mms, buf, size);
369  }
370  } while (!res);
371  return res;
372 }
373 
374 static int64_t mmsh_read_seek(URLContext *h, int stream_index,
375  int64_t timestamp, int flags)
376 {
377  MMSHContext *mmsh_old = h->priv_data;
378  MMSHContext *mmsh = av_mallocz(sizeof(*mmsh));
379  int ret;
380 
381  if (!mmsh)
382  return AVERROR(ENOMEM);
383 
384  h->priv_data = mmsh;
385  ret= mmsh_open_internal(h, mmsh_old->location, 0, FFMAX(timestamp, 0), 0);
386  if(ret>=0){
387  h->priv_data = mmsh_old;
388  mmsh_close(h);
389  h->priv_data = mmsh;
390  av_free(mmsh_old);
392  }else {
393  h->priv_data = mmsh_old;
394  av_free(mmsh);
395  }
396 
397  return ret;
398 }
399 
400 static int64_t mmsh_seek(URLContext *h, int64_t pos, int whence)
401 {
402  MMSHContext *mmsh = h->priv_data;
403  MMSContext *mms = &mmsh->mms;
404 
405  if(pos == 0 && whence == SEEK_CUR)
406  return mms->asf_header_read_size + mms->remaining_in_len + mmsh->chunk_seq * (int64_t)mms->asf_packet_len;
407  return AVERROR(ENOSYS);
408 }
409 
411  .name = "mmsh",
412  .url_open = mmsh_open,
413  .url_read = mmsh_read,
414  .url_seek = mmsh_seek,
415  .url_close = mmsh_close,
416  .url_read_seek = mmsh_read_seek,
417  .priv_data_size = sizeof(MMSHContext),
419  .default_whitelist = "http,tcp",
420 };
handle_chunk_type
static int handle_chunk_type(MMSHContext *mmsh)
Definition: mmsh.c:328
get_chunk_header
static ChunkType get_chunk_header(MMSHContext *mmsh, int *len)
Definition: mmsh.c:73
AVERROR
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
opt.h
CHUNK_HEADER_LENGTH
#define CHUNK_HEADER_LENGTH
Definition: mmsh.c:37
MMSHContext::location
uint8_t location[1024]
Definition: mmsh.c:58
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
CHUNK_TYPE_STREAM_CHANGE
@ CHUNK_TYPE_STREAM_CHANGE
Definition: mmsh.c:53
MMSContext::header_parsed
int header_parsed
The header has been received and parsed.
Definition: mms.h:51
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
MMSContext::asf_header
uint8_t * asf_header
Internal handling of the ASF header.
Definition: mms.h:49
USERAGENT
#define USERAGENT
Definition: mmsh.c:41
mmsh_open
static int mmsh_open(URLContext *h, const char *uri, int flags)
Definition: mmsh.c:323
MMSContext::asf_packet_len
int asf_packet_len
Definition: mms.h:52
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
URLProtocol
Definition: url.h:53
MMSContext::stream_num
int stream_num
stream numbers.
Definition: mms.h:56
fail
#define fail()
Definition: checkasm.h:134
mms.h
MMSContext
Definition: mms.h:30
ffurl_connect
int ffurl_connect(URLContext *uc, AVDictionary **options)
Connect an URLContext that has been allocated by ffurl_alloc.
Definition: avio.c:166
CHUNK_TYPE_ASF_HEADER
@ CHUNK_TYPE_ASF_HEADER
Definition: mmsh.c:51
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:487
ChunkType
ChunkType
Definition: mmsh.c:49
URLContext::priv_data
void * priv_data
Definition: url.h:40
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:206
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
ff_mms_asf_header_parser
int ff_mms_asf_header_parser(MMSContext *mms)
Definition: mms.c:54
MMSHContext::mms
MMSContext mms
Definition: mmsh.c:57
CHUNK_TYPE_DATA
@ CHUNK_TYPE_DATA
Definition: mmsh.c:50
intreadwrite.h
ff_mms_read_header
int ff_mms_read_header(MMSContext *mms, uint8_t *buf, const int size)
Definition: mms.c:29
ff_url_join
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:38
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
MMSContext::asf_header_read_size
int asf_header_read_size
Definition: mms.h:53
MMSContext::in_buffer
uint8_t in_buffer[65536]
Buffer for incoming packets.
Definition: mms.h:42
mmsh_open_internal
static int mmsh_open_internal(URLContext *h, const char *uri, int flags, int timestamp, int64_t pos)
Definition: mmsh.c:212
internal.h
URLContext::protocol_whitelist
const char * protocol_whitelist
Definition: url.h:48
NULL
#define NULL
Definition: coverity.c:32
ff_mmsh_protocol
const URLProtocol ff_mmsh_protocol
Definition: mmsh.c:410
MMSHContext::request_seq
int request_seq
request packet sequence
Definition: mmsh.c:59
read_data_packet
static int read_data_packet(MMSHContext *mmsh, const int len)
Definition: mmsh.c:114
MMSStream::id
int id
Definition: mms.h:27
mmsh_seek
static int64_t mmsh_seek(URLContext *h, int64_t pos, int whence)
Definition: mmsh.c:400
ff_mms_read_data
int ff_mms_read_data(MMSContext *mms, uint8_t *buf, const int size)
Definition: mms.c:44
MMSContext::remaining_in_len
int remaining_in_len
Reading length from incoming buffer.
Definition: mms.h:44
mmsh_read_seek
static int64_t mmsh_read_seek(URLContext *h, int stream_index, int64_t timestamp, int flags)
Definition: mmsh.c:374
size
int size
Definition: twinvq_data.h:10344
URLProtocol::name
const char * name
Definition: url.h:54
mmsh_close
static int mmsh_close(URLContext *h)
Definition: mmsh.c:63
CLIENTGUID
#define CLIENTGUID
Definition: mmsh.c:44
MMSHContext
Definition: mmsh.c:56
CHUNK_TYPE_END
@ CHUNK_TYPE_END
Definition: mmsh.c:52
ffurl_alloc
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb)
Create a URLContext for accessing to the resource indicated by url, but do not initiate the connectio...
Definition: avio.c:293
URLContext
Definition: url.h:37
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
av_url_split
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:357
url.h
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
len
int len
Definition: vorbis_enc_data.h:426
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:438
ret
ret
Definition: filter_design.txt:187
av_strlcat
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes,...
Definition: avstring.c:96
mmsh_read
static int mmsh_read(URLContext *h, uint8_t *buf, int size)
Definition: mmsh.c:356
pos
unsigned int pos
Definition: spdifenc.c:413
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:150
EXT_HEADER_LENGTH
#define EXT_HEADER_LENGTH
Definition: mmsh.c:38
get_http_header_data
static int get_http_header_data(MMSHContext *mmsh)
Definition: mmsh.c:142
headers
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test note that you must have installed it fate list List all fate regression test targets install Install headers
Definition: build_system.txt:34
MMSContext::asf_header_size
int asf_header_size
Size of stored ASF header.
Definition: mms.h:50
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:623
MMSHContext::chunk_seq
int chunk_seq
data packet sequence
Definition: mmsh.c:60
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:270
ffurl_read_complete
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:408
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:86
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
ChunkType
ChunkType
Definition: g2meet.c:48
h
h
Definition: vp9dsp_template.c:2038
avstring.h
http.h
MMSContext::mms_hd
URLContext * mms_hd
TCP connection handle.
Definition: mms.h:31
snprintf
#define snprintf
Definition: snprintf.h:34
MMSContext::streams
MMSStream * streams
Definition: mms.h:32
MMSContext::read_in_ptr
uint8_t * read_in_ptr
Pointer for reading from incoming buffer.
Definition: mms.h:43