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  ffurl_closep(&c->tls_shared.tcp);
142  return 0;
143 }
144 
145 static int tls_client_handshake_loop(URLContext *h, int initial)
146 {
147  TLSContext *c = h->priv_data;
148  TLSShared *s = &c->tls_shared;
149  SECURITY_STATUS sspi_ret;
150  SecBuffer outbuf[3] = { 0 };
151  SecBufferDesc outbuf_desc;
152  SecBuffer inbuf[2];
153  SecBufferDesc inbuf_desc;
154  int i, ret = 0, read_data = initial;
155 
156  if (c->enc_buf == NULL) {
157  c->enc_buf_offset = 0;
159  if (ret < 0)
160  goto fail;
161  c->enc_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
162  }
163 
164  if (c->dec_buf == NULL) {
165  c->dec_buf_offset = 0;
167  if (ret < 0)
168  goto fail;
169  c->dec_buf_size = SCHANNEL_INITIAL_BUFFER_SIZE;
170  }
171 
172  while (1) {
173  if (c->enc_buf_size - c->enc_buf_offset < SCHANNEL_FREE_BUFFER_SIZE) {
174  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
175  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
176  if (ret < 0) {
177  c->enc_buf_size = c->enc_buf_offset = 0;
178  goto fail;
179  }
180  }
181 
182  if (read_data) {
183  ret = ffurl_read(c->tls_shared.tcp, c->enc_buf + c->enc_buf_offset,
184  c->enc_buf_size - c->enc_buf_offset);
185  if (ret < 0) {
186  av_log(h, AV_LOG_ERROR, "Failed to read handshake response\n");
187  goto fail;
188  }
189  c->enc_buf_offset += ret;
190  }
191 
192  /* input buffers */
193  init_sec_buffer(&inbuf[0], SECBUFFER_TOKEN, av_malloc(c->enc_buf_offset), c->enc_buf_offset);
194  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
195  init_sec_buffer_desc(&inbuf_desc, inbuf, 2);
196 
197  if (inbuf[0].pvBuffer == NULL) {
198  av_log(h, AV_LOG_ERROR, "Failed to allocate input buffer\n");
199  ret = AVERROR(ENOMEM);
200  goto fail;
201  }
202 
203  memcpy(inbuf[0].pvBuffer, c->enc_buf, c->enc_buf_offset);
204 
205  /* output buffers */
206  init_sec_buffer(&outbuf[0], SECBUFFER_TOKEN, NULL, 0);
207  init_sec_buffer(&outbuf[1], SECBUFFER_ALERT, NULL, 0);
208  init_sec_buffer(&outbuf[2], SECBUFFER_EMPTY, NULL, 0);
209  init_sec_buffer_desc(&outbuf_desc, outbuf, 3);
210 
211  sspi_ret = InitializeSecurityContext(&c->cred_handle, &c->ctxt_handle, s->host, c->request_flags,
212  0, 0, &inbuf_desc, 0, NULL, &outbuf_desc, &c->context_flags,
213  &c->ctxt_timestamp);
214  av_freep(&inbuf[0].pvBuffer);
215 
216  if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
217  av_log(h, AV_LOG_DEBUG, "Received incomplete handshake, need more data\n");
218  read_data = 1;
219  continue;
220  }
221 
222  /* remote requests a client certificate - attempt to continue without one anyway */
223  if (sspi_ret == SEC_I_INCOMPLETE_CREDENTIALS &&
224  !(c->request_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
225  av_log(h, AV_LOG_VERBOSE, "Client certificate has been requested, ignoring\n");
226  c->request_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
227  read_data = 0;
228  continue;
229  }
230 
231  /* continue handshake */
232  if (sspi_ret == SEC_I_CONTINUE_NEEDED || sspi_ret == SEC_E_OK) {
233  for (i = 0; i < 3; i++) {
234  if (outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) {
235  ret = ffurl_write(c->tls_shared.tcp, outbuf[i].pvBuffer, outbuf[i].cbBuffer);
236  if (ret < 0 || ret != outbuf[i].cbBuffer) {
237  av_log(h, AV_LOG_VERBOSE, "Failed to send handshake data\n");
238  ret = AVERROR(EIO);
239  goto fail;
240  }
241  }
242 
243  if (outbuf[i].pvBuffer != NULL) {
244  FreeContextBuffer(outbuf[i].pvBuffer);
245  outbuf[i].pvBuffer = NULL;
246  }
247  }
248  } else {
249  if (sspi_ret == SEC_E_WRONG_PRINCIPAL)
250  av_log(h, AV_LOG_ERROR, "SNI or certificate check failed\n");
251  else
252  av_log(h, AV_LOG_ERROR, "Creating security context failed (0x%lx)\n", sspi_ret);
254  goto fail;
255  }
256 
257  if (inbuf[1].BufferType == SECBUFFER_EXTRA && inbuf[1].cbBuffer > 0) {
258  if (c->enc_buf_offset > inbuf[1].cbBuffer) {
259  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[1].cbBuffer,
260  inbuf[1].cbBuffer);
261  c->enc_buf_offset = inbuf[1].cbBuffer;
262  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
263  read_data = 0;
264  continue;
265  }
266  }
267  } else {
268  c->enc_buf_offset = 0;
269  }
270 
271  if (sspi_ret == SEC_I_CONTINUE_NEEDED) {
272  read_data = 1;
273  continue;
274  }
275 
276  break;
277  }
278 
279  return 0;
280 
281 fail:
282  /* free any remaining output data */
283  for (i = 0; i < 3; i++) {
284  if (outbuf[i].pvBuffer != NULL) {
285  FreeContextBuffer(outbuf[i].pvBuffer);
286  outbuf[i].pvBuffer = NULL;
287  }
288  }
289 
290  return ret;
291 }
292 
294 {
295  TLSContext *c = h->priv_data;
296  TLSShared *s = &c->tls_shared;
297  SecBuffer outbuf;
298  SecBufferDesc outbuf_desc;
299  SECURITY_STATUS sspi_ret;
300  int ret;
301 
302  init_sec_buffer(&outbuf, SECBUFFER_EMPTY, NULL, 0);
303  init_sec_buffer_desc(&outbuf_desc, &outbuf, 1);
304 
305  c->request_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
306  ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
307  ISC_REQ_STREAM;
308 
309  sspi_ret = InitializeSecurityContext(&c->cred_handle, NULL, s->host, c->request_flags, 0, 0,
310  NULL, 0, &c->ctxt_handle, &outbuf_desc, &c->context_flags,
311  &c->ctxt_timestamp);
312  if (sspi_ret != SEC_I_CONTINUE_NEEDED) {
313  av_log(h, AV_LOG_ERROR, "Unable to create initial security context (0x%lx)\n", sspi_ret);
315  goto fail;
316  }
317 
318  ret = ffurl_write(s->tcp, outbuf.pvBuffer, outbuf.cbBuffer);
319  FreeContextBuffer(outbuf.pvBuffer);
320  if (ret < 0 || ret != outbuf.cbBuffer) {
321  av_log(h, AV_LOG_ERROR, "Failed to send initial handshake data\n");
322  ret = AVERROR(EIO);
323  goto fail;
324  }
325 
326  return tls_client_handshake_loop(h, 1);
327 
328 fail:
329  DeleteSecurityContext(&c->ctxt_handle);
330  return ret;
331 }
332 
333 static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
334 {
335  TLSContext *c = h->priv_data;
336  TLSShared *s = &c->tls_shared;
337  SECURITY_STATUS sspi_ret;
338  SCHANNEL_CRED schannel_cred = { 0 };
339  int ret;
340 
341  if ((ret = ff_tls_open_underlying(s, h, uri, options)) < 0)
342  goto fail;
343 
344  if (s->listen) {
345  av_log(h, AV_LOG_ERROR, "TLS Listen Sockets with SChannel is not implemented.\n");
346  ret = AVERROR(EINVAL);
347  goto fail;
348  }
349 
350  /* SChannel Options */
351  schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
352 
353  if (s->verify)
354  schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
355  SCH_CRED_REVOCATION_CHECK_CHAIN;
356  else
357  schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
358  SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
359  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
360 
361  /* Get credential handle */
362  sspi_ret = AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME, SECPKG_CRED_OUTBOUND,
363  NULL, &schannel_cred, NULL, NULL, &c->cred_handle,
364  &c->cred_timestamp);
365  if (sspi_ret != SEC_E_OK) {
366  av_log(h, AV_LOG_ERROR, "Unable to acquire security credentials (0x%lx)\n", sspi_ret);
368  goto fail;
369  }
370 
372  if (ret < 0)
373  goto fail;
374 
375  c->connected = 1;
376 
377  return 0;
378 
379 fail:
380  tls_close(h);
381  return ret;
382 }
383 
384 static int tls_read(URLContext *h, uint8_t *buf, int len)
385 {
386  TLSContext *c = h->priv_data;
387  TLSShared *s = &c->tls_shared;
388  SECURITY_STATUS sspi_ret = SEC_E_OK;
389  SecBuffer inbuf[4];
390  SecBufferDesc inbuf_desc;
391  int size, ret;
392  int min_enc_buf_size = len + SCHANNEL_FREE_BUFFER_SIZE;
393 
394  /* If we have some left-over data from previous network activity,
395  * return it first in case it is enough. It may contain
396  * data that is required to know whether this connection
397  * is still required or not, esp. in case of HTTP keep-alive
398  * connections. */
399  if (c->dec_buf_offset > 0)
400  goto cleanup;
401 
402  if (c->sspi_close_notify)
403  goto cleanup;
404 
405  if (!c->connection_closed) {
406  size = c->enc_buf_size - c->enc_buf_offset;
407  if (size < SCHANNEL_FREE_BUFFER_SIZE || c->enc_buf_size < min_enc_buf_size) {
408  c->enc_buf_size = c->enc_buf_offset + SCHANNEL_FREE_BUFFER_SIZE;
409  if (c->enc_buf_size < min_enc_buf_size)
410  c->enc_buf_size = min_enc_buf_size;
411  ret = av_reallocp(&c->enc_buf, c->enc_buf_size);
412  if (ret < 0) {
413  c->enc_buf_size = c->enc_buf_offset = 0;
414  return ret;
415  }
416  }
417 
418  ret = ffurl_read(s->tcp, c->enc_buf + c->enc_buf_offset,
419  c->enc_buf_size - c->enc_buf_offset);
420  if (ret == AVERROR_EOF) {
421  c->connection_closed = 1;
422  ret = 0;
423  } else if (ret < 0) {
424  av_log(h, AV_LOG_ERROR, "Unable to read from socket\n");
425  return ret;
426  }
427 
428  c->enc_buf_offset += ret;
429  }
430 
431  while (c->enc_buf_offset > 0 && sspi_ret == SEC_E_OK) {
432  /* input buffer */
433  init_sec_buffer(&inbuf[0], SECBUFFER_DATA, c->enc_buf, c->enc_buf_offset);
434 
435  /* additional buffers for possible output */
436  init_sec_buffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
437  init_sec_buffer(&inbuf[2], SECBUFFER_EMPTY, NULL, 0);
438  init_sec_buffer(&inbuf[3], SECBUFFER_EMPTY, NULL, 0);
439  init_sec_buffer_desc(&inbuf_desc, inbuf, 4);
440 
441  sspi_ret = DecryptMessage(&c->ctxt_handle, &inbuf_desc, 0, NULL);
442  if (sspi_ret == SEC_E_OK || sspi_ret == SEC_I_RENEGOTIATE ||
443  sspi_ret == SEC_I_CONTEXT_EXPIRED) {
444  /* handle decrypted data */
445  if (inbuf[1].BufferType == SECBUFFER_DATA) {
446  /* grow buffer if needed */
447  size = inbuf[1].cbBuffer > SCHANNEL_FREE_BUFFER_SIZE ?
448  inbuf[1].cbBuffer : SCHANNEL_FREE_BUFFER_SIZE;
449  if (c->dec_buf_size - c->dec_buf_offset < size || c->dec_buf_size < len) {
450  c->dec_buf_size = c->dec_buf_offset + size;
451  if (c->dec_buf_size < len)
452  c->dec_buf_size = len;
453  ret = av_reallocp(&c->dec_buf, c->dec_buf_size);
454  if (ret < 0) {
455  c->dec_buf_size = c->dec_buf_offset = 0;
456  return ret;
457  }
458  }
459 
460  /* copy decrypted data to buffer */
461  size = inbuf[1].cbBuffer;
462  if (size) {
463  memcpy(c->dec_buf + c->dec_buf_offset, inbuf[1].pvBuffer, size);
464  c->dec_buf_offset += size;
465  }
466  }
467  if (inbuf[3].BufferType == SECBUFFER_EXTRA && inbuf[3].cbBuffer > 0) {
468  if (c->enc_buf_offset > inbuf[3].cbBuffer) {
469  memmove(c->enc_buf, (c->enc_buf + c->enc_buf_offset) - inbuf[3].cbBuffer,
470  inbuf[3].cbBuffer);
471  c->enc_buf_offset = inbuf[3].cbBuffer;
472  }
473  } else
474  c->enc_buf_offset = 0;
475 
476  if (sspi_ret == SEC_I_RENEGOTIATE) {
477  if (c->enc_buf_offset) {
478  av_log(h, AV_LOG_ERROR, "Cannot renegotiate, encrypted data buffer not empty\n");
480  goto cleanup;
481  }
482 
483  av_log(h, AV_LOG_VERBOSE, "Re-negotiating security context\n");
485  if (ret < 0) {
486  goto cleanup;
487  }
488  sspi_ret = SEC_E_OK;
489  continue;
490  } else if (sspi_ret == SEC_I_CONTEXT_EXPIRED) {
491  c->sspi_close_notify = 1;
492  if (!c->connection_closed) {
493  c->connection_closed = 1;
494  av_log(h, AV_LOG_VERBOSE, "Server closed the connection\n");
495  }
496  ret = 0;
497  goto cleanup;
498  }
499  } else if (sspi_ret == SEC_E_INCOMPLETE_MESSAGE) {
500  ret = AVERROR(EAGAIN);
501  goto cleanup;
502  } else {
503  av_log(h, AV_LOG_ERROR, "Unable to decrypt message (error 0x%x)\n", (unsigned)sspi_ret);
504  ret = AVERROR(EIO);
505  goto cleanup;
506  }
507  }
508 
509  ret = 0;
510 
511 cleanup:
512  size = FFMIN(len, c->dec_buf_offset);
513  if (size) {
514  memcpy(buf, c->dec_buf, size);
515  memmove(c->dec_buf, c->dec_buf + size, c->dec_buf_offset - size);
516  c->dec_buf_offset -= size;
517 
518  return size;
519  }
520 
521  if (ret == 0 && !c->connection_closed)
522  ret = AVERROR(EAGAIN);
523 
524  return ret < 0 ? ret : AVERROR_EOF;
525 }
526 
527 static int tls_write(URLContext *h, const uint8_t *buf, int len)
528 {
529  TLSContext *c = h->priv_data;
530  TLSShared *s = &c->tls_shared;
531  SECURITY_STATUS sspi_ret;
532  int ret = 0, data_size;
533  uint8_t *data = NULL;
534  SecBuffer outbuf[4];
535  SecBufferDesc outbuf_desc;
536 
537  if (c->sizes.cbMaximumMessage == 0) {
538  sspi_ret = QueryContextAttributes(&c->ctxt_handle, SECPKG_ATTR_STREAM_SIZES, &c->sizes);
539  if (sspi_ret != SEC_E_OK)
540  return AVERROR_UNKNOWN;
541  }
542 
543  /* limit how much data we can consume */
544  len = FFMIN(len, c->sizes.cbMaximumMessage);
545 
546  data_size = c->sizes.cbHeader + len + c->sizes.cbTrailer;
547  data = av_malloc(data_size);
548  if (data == NULL)
549  return AVERROR(ENOMEM);
550 
551  init_sec_buffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
552  data, c->sizes.cbHeader);
553  init_sec_buffer(&outbuf[1], SECBUFFER_DATA,
554  data + c->sizes.cbHeader, len);
555  init_sec_buffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
556  data + c->sizes.cbHeader + len,
557  c->sizes.cbTrailer);
558  init_sec_buffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
559  init_sec_buffer_desc(&outbuf_desc, outbuf, 4);
560 
561  memcpy(outbuf[1].pvBuffer, buf, len);
562 
563  sspi_ret = EncryptMessage(&c->ctxt_handle, 0, &outbuf_desc, 0);
564  if (sspi_ret == SEC_E_OK) {
565  len = outbuf[0].cbBuffer + outbuf[1].cbBuffer + outbuf[2].cbBuffer;
566  ret = ffurl_write(s->tcp, data, len);
567  if (ret < 0 || ret != len) {
568  ret = AVERROR(EIO);
569  av_log(h, AV_LOG_ERROR, "Writing encrypted data to socket failed\n");
570  goto done;
571  }
572  } else {
573  av_log(h, AV_LOG_ERROR, "Encrypting data failed\n");
574  if (sspi_ret == SEC_E_INSUFFICIENT_MEMORY)
575  ret = AVERROR(ENOMEM);
576  else
577  ret = AVERROR(EIO);
578  goto done;
579  }
580 
581 done:
582  av_freep(&data);
583  return ret < 0 ? ret : outbuf[1].cbBuffer;
584 }
585 
587 {
588  TLSContext *c = h->priv_data;
589  return ffurl_get_file_handle(c->tls_shared.tcp);
590 }
591 
592 static const AVOption options[] = {
593  TLS_COMMON_OPTIONS(TLSContext, tls_shared),
594  { NULL }
595 };
596 
597 static const AVClass tls_class = {
598  .class_name = "tls",
599  .item_name = av_default_item_name,
600  .option = options,
601  .version = LIBAVUTIL_VERSION_INT,
602 };
603 
605  .name = "tls",
606  .url_open2 = tls_open,
607  .url_read = tls_read,
608  .url_write = tls_write,
609  .url_close = tls_close,
610  .url_get_file_handle = tls_get_file_handle,
611  .priv_data_size = sizeof(TLSContext),
613  .priv_data_class = &tls_class,
614 };
TLSContext
Definition: tls_gnutls.c:48
read_data
static int read_data(void *opaque, uint8_t *buf, int buf_size)
Definition: dashdec.c:1767
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:604
AVOption
AVOption.
Definition: opt.h:246
data
const char data[16]
Definition: mxf.c:91
options
static const AVOption options[]
Definition: tls_schannel.c:592
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
AVDictionary
Definition: dict.c:30
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
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:597
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:527
TLS_COMMON_OPTIONS
#define TLS_COMMON_OPTIONS(pstruct, options_field)
Definition: tls.h:45
fail
#define fail()
Definition: checkasm.h:123
tls_open
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: tls_schannel.c:333
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
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:384
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:235
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:79
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:161
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:269
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:293
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
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:446
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
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:409
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:423
tls_get_file_handle
static int tls_get_file_handle(URLContext *h)
Definition: tls_schannel.c:586
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:145
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:628