FFmpeg
tls_schannel.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Hendrik Leppkes
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /** Based on the CURL SChannel module */
22 
23 #include "avformat.h"
24 #include "internal.h"
25 #include "network.h"
26 #include "os_support.h"
27 #include "url.h"
28 #include "tls.h"
29 
30 #define SECURITY_WIN32
31 #include <windows.h>
32 #include <security.h>
33 #include <schnlsp.h>
34 
35 #define SCHANNEL_INITIAL_BUFFER_SIZE 4096
36 #define SCHANNEL_FREE_BUFFER_SIZE 1024
37 
38 /* mingw does not define this symbol */
39 #ifndef SECBUFFER_ALERT
40 #define SECBUFFER_ALERT 17
41 #endif
42 
43 typedef struct TLSContext {
44  const AVClass *class;
46 
47  CredHandle cred_handle;
48  TimeStamp cred_timestamp;
49 
50  CtxtHandle ctxt_handle;
51  TimeStamp ctxt_timestamp;
52 
55 
59 
63 
64  SecPkgContext_StreamSizes sizes;
65 
66  int connected;
69 } TLSContext;
70 
71 static void init_sec_buffer(SecBuffer *buffer, unsigned long type,
72  void *data, unsigned long size)
73 {
74  buffer->cbBuffer = size;
75  buffer->BufferType = type;
76  buffer->pvBuffer = data;
77 }
78 
79 static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers,
80  unsigned long buffer_count)
81 {
82  desc->ulVersion = SECBUFFER_VERSION;
83  desc->pBuffers = buffers;
84  desc->cBuffers = buffer_count;
85 }
86 
88 {
89  TLSContext *c = h->priv_data;
90  TLSShared *s = &c->tls_shared;
91  int ret;
92 
93  if (c->connected) {
94  SecBufferDesc BuffDesc;
95  SecBuffer Buffer;
96  SECURITY_STATUS sspi_ret;
97  SecBuffer outbuf;
98  SecBufferDesc outbuf_desc;
99 
100  DWORD dwshut = SCHANNEL_SHUTDOWN;
101  init_sec_buffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
102  init_sec_buffer_desc(&BuffDesc, &Buffer, 1);
103 
104  sspi_ret = ApplyControlToken(&c->ctxt_handle, &BuffDesc);
105  if (sspi_ret != SEC_E_OK)
106  av_log(h, AV_LOG_ERROR, "ApplyControlToken failed\n");
107 
108  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
109  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
110 
111  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host,
112  c->request_flags, 0, 0, NULL, 0, &c->ctxt_handle,
113  &outbuf_desc, &c->context_flags, &c->ctxt_timestamp);
114  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_CONTEXT_EXPIRED) {
115  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
116  FreeContextBuffer(outbuf.pvBuffer);
117  if (ret < 0 || ret != outbuf.cbBuffer)
118  av_log(h, AV_LOG_ERROR, "Failed to send close message\n");
119  }
120 
121  c->connected = 0;
122  }
123  return 0;
124 }
125 
126 static int tls_close(URLContext *h)
127 {
128  TLSContext *c = h->priv_data;
129 
131 
132  DeleteSecurityContext(&c->ctxt_handle);
133  FreeCredentialsHandle(&c->cred_handle);
134 
135  av_freep(&c->enc_buf);
136  c->enc_buf_size = c->enc_buf_offset = 0;
137 
138  av_freep(&c->dec_buf);
139  c->dec_buf_size = c->dec_buf_offset = 0;
140 
141  if (c->tls_shared.tcp)
142  ffurl_close(c->tls_shared.tcp);
143  return 0;
144 }
145 
146 static int tls_client_handshake_loop(URLContext *h, int initial)
147 {
148  TLSContext *c = h->priv_data;
149  TLSShared *s = &c->tls_shared;
150  SECURITY_STATUS sspi_ret;
151  SecBuffer outbuf[3] = { 0 };
152  SecBufferDesc outbuf_desc;
153  SecBuffer inbuf[2];
154  SecBufferDesc inbuf_desc;
155  int i, ret = 0, read_data = initial;
156 
157  if (c->enc_buf == NULL) {
158  c->enc_buf_offset = 0;
160  if (ret < 0)
161  goto fail;
162  c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
163  }
164 
165  if (c->dec_buf == NULL) {
166  c->dec_buf_offset = 0;
168  if (ret < 0)
169  goto fail;
170  c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
171  }
172 
173  while (1) {
174  if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
175  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
176  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
177  if (ret < 0) {
178  c->enc_buf_size = c->enc_buf_offset = 0;
179  goto fail;
180  }
181  }
182 
183  if (read_data) {
184  ret = ffurl_read(c->tls_shared.tcp, c->enc_buf + c->enc_buf_offset,
185  c->enc_buf_size - c->enc_buf_offset);
186  if (ret < 0) {
187  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
188  goto fail;
189  }
190  c->enc_buf_offset += ret;
191  }
192 
193  /* input buffers */
194  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
195  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
196  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
197 
198  if (inbuf[0].pvBuffer == NULL) {
199  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
200  ret = AVERROR(ENOMEM);
201  goto fail;
202  }
203 
204  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
205 
206  /* output buffers */
207  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
208  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
209  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
210  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
211 
212  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags,
213  0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &c->context_flags,
214  &c->ctxt_timestamp);
215  av_freep(&inbuf[0].pvBuffer);
216 
217  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
218  av_log(h, AV_LOG_DEBUG, "Received incomplete handshake, need more data\n");
219  read_data = 1;
220  continue;
221  }
222 
223  /* remote requests a client certificate - attempt to continue without one anyway */
224  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
225  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
226  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
227  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
228  read_data = 0;
229  continue;
230  }
231 
232  /* continue handshake */
233  if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
234  for (i = 0; i < 3; i++) {
235  if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
236  ret = ffurl_write(c->tls_shared.tcp, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
237  if (ret < 0 || ret != outbuf[i].cbBuffer) {
238  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
239  ret = AVERROR(EIO);
240  goto fail;
241  }
242  }
243 
244  if (outbuf[i].pvBuffer != NULL) {
245  FreeContextBuffer(outbuf[i].pvBuffer);
246  outbuf[i].pvBuffer = NULL;
247  }
248  }
249  } else {
250  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
251  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
252  else
253  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
255  goto fail;
256  }
257 
258  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
259  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
260  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
261  inbuf[1].cbBuffer);
262  c->enc_buf_offset = inbuf[1].cbBuffer;
263  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
264  read_data = 0;
265  continue;
266  }
267  }
268  } else {
269  c->enc_buf_offset = 0;
270  }
271 
272  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
273  read_data = 1;
274  continue;
275  }
276 
277  break;
278  }
279 
280  return 0;
281 
282 fail:
283  /* free any remaining output data */
284  for (i = 0; i < 3; i++) {
285  if (outbuf[i].pvBuffer != NULL) {
286  FreeContextBuffer(outbuf[i].pvBuffer);
287  outbuf[i].pvBuffer = NULL;
288  }
289  }
290 
291  return ret;
292 }
293 
295 {
296  TLSContext *c = h->priv_data;
297  TLSShared *s = &c->tls_shared;
298  SecBuffer outbuf;
299  SecBufferDesc outbuf_desc;
300  SECURITY_STATUS sspi_ret;
301  int ret;
302 
303  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
304  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
305 
306  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
307  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
308  ISC_REQ_STREAM;
309 
310  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
311  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
312  &c->ctxt_timestamp);
313  if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
314  av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
316  goto fail;
317  }
318 
319  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
320  FreeContextBuffer(outbuf.pvBuffer);
321  if (ret < 0 || ret != outbuf.cbBuffer) {
322  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
323  ret = AVERROR(EIO);
324  goto fail;
325  }
326 
327  return tls_client_handshake_loop(h, 1);
328 
329 fail:
330  DeleteSecurityContext(&c->ctxt_handle);
331  return ret;
332 }
333 
334 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
335 {
336  TLSContext *c = h->priv_data;
337  TLSShared *s = &c->tls_shared;
338  SECURITY_STATUS sspi_ret;
339  SCHANNEL_CRED schannel_cred = { 0 };
340  int ret;
341 
342  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
343  goto fail;
344 
345  if (s->listen) {
346  av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n");
347  ret = AVERROR(EINVAL);
348  goto fail;
349  }
350 
351  /* SChannel Options */
352  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
353 
354  if (s->verify)
355  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
356  SCH_CRED_REVOCATION_CHECK_CHAIN;
357  else
358  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
359  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
360  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
361 
362  /* Get credential handle */
363  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
364  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
365  &c->cred_timestamp);
366  if (sspi_ret != SEC_E_OK) {
367  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
369  goto fail;
370  }
371 
373  if (ret < 0)
374  goto fail;
375 
376  c->connected = 1;
377 
378  return 0;
379 
380 fail:
381  tls_close(h);
382  return ret;
383 }
384 
385 static int tls_read(URLContext *h, uint8_t *buf, int len)
386 {
387  TLSContext *c = h->priv_data;
388  TLSShared *s = &c->tls_shared;
389  SECURITY_STATUS sspi_ret = SEC_E_OK;
390  SecBuffer inbuf[4];
391  SecBufferDesc inbuf_desc;
392  int size, ret;
393  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
394 
395  /* If we have some left-over data from previous network activity,
396  * return it first in case it is enough. It may contain
397  * data that is required to know whether this connection
398  * is still required or not, esp. in case of HTTP keep-alive
399  * connections. */
400  if (c->dec_buf_offset > 0)
401  goto cleanup;
402 
403  if (c->sspi_close_notify)
404  goto cleanup;
405 
406  if (!c->connection_closed) {
407  size = c->enc_buf_size - c->enc_buf_offset;
408  if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
409  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
410  if (c->enc_buf_size < min_enc_buf_size)
411  c->enc_buf_size = min_enc_buf_size;
412  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
413  if (ret < 0) {
414  c->enc_buf_size = c->enc_buf_offset = 0;
415  return ret;
416  }
417  }
418 
419  ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset,
420  c->enc_buf_size - c->enc_buf_offset);
421  if (ret == AVERROR_EOF) {
422  c->connection_closed = 1;
423  ret = 0;
424  } else if (ret < 0) {
425  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
426  return ret;
427  }
428 
429  c->enc_buf_offset += ret;
430  }
431 
432  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
433  /* input buffer */
434  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
435 
436  /* additional buffers for possible output */
437  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
438  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
439  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
440  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
441 
442  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
443  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
444  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
445  /* handle decrypted data */
446  if (inbuf[1].BufferType == SECBUFFER_DATA) {
447  /* grow buffer if needed */
448  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
449  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
450  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
451  c->dec_buf_size = c->dec_buf_offset + size;
452  if (c->dec_buf_size < len)
453  c->dec_buf_size = len;
454  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
455  if (ret < 0) {
456  c->dec_buf_size = c->dec_buf_offset = 0;
457  return ret;
458  }
459  }
460 
461  /* copy decrypted data to buffer */
462  size = inbuf[1].cbBuffer;
463  if (size) {
464  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
465  c->dec_buf_offset += size;
466  }
467  }
468  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
469  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
470  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
471  inbuf[3].cbBuffer);
472  c->enc_buf_offset = inbuf[3].cbBuffer;
473  }
474  } else
475  c->enc_buf_offset = 0;
476 
477  if (sspi_ret == SEC_I_RENEGOTIATE) {
478  if (c->enc_buf_offset) {
479  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
481  goto cleanup;
482  }
483 
484  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
486  if (ret < 0) {
487  goto cleanup;
488  }
489  sspi_ret = SEC_E_OK;
490  continue;
491  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
492  c->sspi_close_notify = 1;
493  if (!c->connection_closed) {
494  c->connection_closed = 1;
495  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
496  }
497  ret = 0;
498  goto cleanup;
499  }
500  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
501  ret = AVERROR(EAGAIN);
502  goto cleanup;
503  } else {
504  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
505  ret = AVERROR(EIO);
506  goto cleanup;
507  }
508  }
509 
510  ret = 0;
511 
512 cleanup:
513  size = FFMIN(len, c->dec_buf_offset);
514  if (size) {
515  memcpy(buf, c->dec_buf, size);
516  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
517  c->dec_buf_offset -= size;
518 
519  return size;
520  }
521 
522  if (ret == 0 && !c->connection_closed)
523  ret = AVERROR(EAGAIN);
524 
525  return ret < 0 ? ret : AVERROR_EOF;
526 }
527 
528 static int tls_write(URLContext *h, const uint8_t *buf, int len)
529 {
530  TLSContext *c = h->priv_data;
531  TLSShared *s = &c->tls_shared;
532  SECURITY_STATUS sspi_ret;
533  int ret = 0, data_size;
534  uint8_t *data = NULL;
535  SecBuffer outbuf[4];
536  SecBufferDesc outbuf_desc;
537 
538  if (c->sizes.cbMaximumMessage == 0) {
539  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
540  if (sspi_ret != SEC_E_OK)
541  return AVERROR_UNKNOWN;
542  }
543 
544  /* limit how much data we can consume */
545  len = FFMIN(len, c->sizes.cbMaximumMessage);
546 
547  data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
548  data = av_malloc(data_size);
549  if (data == NULL)
550  return AVERROR(ENOMEM);
551 
552  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
553  data, c->sizes.cbHeader);
554  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
555  data + c->sizes.cbHeader, len);
556  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
557  data + c->sizes.cbHeader + len,
558  c->sizes.cbTrailer);
559  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
560  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
561 
562  memcpy(outbuf[1].pvBuffer, buf, len);
563 
564  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
565  if (sspi_ret == SEC_E_OK) {
566  len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
567  ret = ffurl_write(s->tcp, data, len);
568  if (ret < 0 || ret != len) {
569  ret = AVERROR(EIO);
570  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
571  goto done;
572  }
573  } else {
574  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
575  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
576  ret = AVERROR(ENOMEM);
577  else
578  ret = AVERROR(EIO);
579  goto done;
580  }
581 
582 done:
583  av_freep(&data);
584  return ret < 0 ? ret : outbuf[1].cbBuffer;
585 }
586 
588 {
589  TLSContext *c = h->priv_data;
590  return ffurl_get_file_handle(c->tls_shared.tcp);
591 }
592 
593 static const AVOption options[] = {
594  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
595  { NULL }
596 };
597 
598 static const AVClass tls_class = {
599  .class_name = "tls",
600  .item_name = av_default_item_name,
601  .option = options,
602  .version = LIBAVUTIL_VERSION_INT,
603 };
604 
606  .name = "tls",
607  .url_open2 = tls_open,
608  .url_read = tls_read,
609  .url_write = tls_write,
610  .url_close = tls_close,
611  .url_get_file_handle = tls_get_file_handle,
612  .priv_data_size = sizeof(TLSContext),
614  .priv_data_class = &tls_class,
615 };
TLSContext
Definition: tls_gnutls.c:48
read_data
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1742
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
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
TLSContext::context_flags
ULONG context_flags
Definition: tls_schannel.c:54
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
TLSContext::request_flags
ULONG request_flags
Definition: tls_schannel.c:53
SCHANNEL_FREE_BUFFER_SIZE
#define SCHANNEL_FREE_BUFFER_SIZE
Definition: tls_schannel.c:36
cleanup
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:127
ff_tls_protocol
const URLProtocol ff_tls_protocol
Definition: tls_schannel.c:605
AVOption
AVOption.
Definition: opt.h:246
data
const char data[16]
Definition: mxf.c:91
options
static const AVOption options[]
Definition: tls_schannel.c:593
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
ffurl_close
int ffurl_close(URLContext *h)
Definition: avio.c:470
AVDictionary
Definition: dict.c:30
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
ULONG
uint32_t ULONG
Definition: basicDataTypeConversions.h:60
URLProtocol
Definition: url.h:54
os_support.h
TLSContext::dec_buf
uint8_t * dec_buf
Definition: tls_schannel.c:60
TLSContext::cred_handle
CredHandle cred_handle
Definition: tls_schannel.c:47
tls_class
static const AVClass tls_class
Definition: tls_schannel.c:598
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
tls_write
static int tls_write(URLContext *h, const uint8_t *buf, int len)
Definition: tls_schannel.c:528
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:45
fail
#define fail()
Definition: checkasm.h:120
TCHAR
char TCHAR
Definition: basicDataTypeConversions.h:40
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_schannel.c:334
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
TLSContext::sspi_close_notify
int sspi_close_notify
Definition: tls_schannel.c:68
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
init_sec_buffer_desc
static void init_sec_buffer_desc(SecBufferDesc *desc, SecBuffer *buffers, unsigned long buffer_count)
Definition: tls_schannel.c:79
s
#define s(width, name)
Definition: cbs_vp9.c:257
TLSContext::dec_buf_offset
int dec_buf_offset
Definition: tls_schannel.c:62
tls_read
static int tls_read(URLContext *h, uint8_t *buf, int len)
Definition: tls_schannel.c:385
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
TLSContext::enc_buf_offset
int enc_buf_offset
Definition: tls_schannel.c:58
internal.h
SECBUFFER_ALERT
#define SECBUFFER_ALERT
Definition: tls_schannel.c:40
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
tls_shutdown_client
static int tls_shutdown_client(URLContext *h)
Definition: tls_schannel.c:87
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
init_sec_buffer
static void init_sec_buffer(SecBuffer *buffer, unsigned long type, void *data, unsigned long size)
Definition: tls_schannel.c:71
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
desc
const char * desc
Definition: nvenc.c:68
tls_close
static int tls_close(URLContext *h)
Definition: tls_schannel.c:126
size
int size
Definition: twinvq_data.h:11134
av_reallocp
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
TLSContext::tls_shared
TLSShared tls_shared
Definition: tls_gnutls.c:50
URLProtocol::name
const char * name
Definition: url.h:55
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
TLSContext::enc_buf_size
int enc_buf_size
Definition: tls_schannel.c:57
URLContext
Definition: url.h:38
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
TLSContext::ctxt_timestamp
TimeStamp ctxt_timestamp
Definition: tls_schannel.c:51
TLSContext::connected
int connected
Definition: tls_schannel.c:66
TLSContext::ctxt_handle
CtxtHandle ctxt_handle
Definition: tls_schannel.c:50
tls_client_handshake
static int tls_client_handshake(URLContext *h)
Definition: tls_schannel.c:294
TLSContext::cred_timestamp
TimeStamp cred_timestamp
Definition: tls_schannel.c:48
url.h
uint8_t
uint8_t
Definition: audio_convert.c:194
len
int len
Definition: vorbis_enc_data.h:452
TLSContext::sizes
SecPkgContext_StreamSizes sizes
Definition: tls_schannel.c:64
ff_tls_open_underlying
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition: tls.c:56
ret
ret
Definition: filter_design.txt:187
SCHANNEL_INITIAL_BUFFER_SIZE
#define SCHANNEL_INITIAL_BUFFER_SIZE
Definition: tls_schannel.c:35
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
DWORD
uint32_t DWORD
Definition: basicDataTypeConversions.h:51
avformat.h
network.h
TLSContext::enc_buf
uint8_t * enc_buf
Definition: tls_schannel.c:56
tls.h
ffurl_read
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition: avio.c:410
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ffurl_write
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:424
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_schannel.c:587
TLSShared
Definition: tls.h:29
TLSContext::connection_closed
int connection_closed
Definition: tls_schannel.c:67
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
tls_client_handshake_loop
static int tls_client_handshake_loop(URLContext *h, int initial)
Definition: tls_schannel.c:146
TLSContext::dec_buf_size
int dec_buf_size
Definition: tls_schannel.c:61
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
h
h
Definition: vp9dsp_template.c:2038
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:629