FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
data_uri.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 Nicolas George
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 License
8  * 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
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <string.h>
22 #include "libavutil/avstring.h"
23 #include "libavutil/base64.h"
24 #include "url.h"
25 
26 typedef struct {
27  const uint8_t *data;
28  void *tofree;
29  size_t size;
30  size_t pos;
31 } DataContext;
32 
33 static av_cold int data_open(URLContext *h, const char *uri, int flags)
34 {
35  DataContext *dc = h->priv_data;
36  const char *data, *opt, *next;
37  char *ddata;
38  int ret, base64 = 0;
39  size_t in_size;
40 
41  /* data:content/type[;base64],payload */
42 
43  av_strstart(uri, "data:", &uri);
44  data = strchr(uri, ',');
45  if (!data) {
46  av_log(h, AV_LOG_ERROR, "No ',' delimiter in URI\n");
47  return AVERROR(EINVAL);
48  }
49  opt = uri;
50  while (opt < data) {
51  next = av_x_if_null(memchr(opt, ';', data - opt), data);
52  if (opt == uri) {
53  if (!memchr(opt, '/', next - opt)) { /* basic validity check */
54  av_log(h, AV_LOG_ERROR, "Invalid content-type '%.*s'\n",
55  (int)(next - opt), opt);
56  return AVERROR(EINVAL);
57  }
58  av_log(h, AV_LOG_VERBOSE, "Content-type: %.*s\n",
59  (int)(next - opt), opt);
60  } else {
61  if (!av_strncasecmp(opt, "base64", next - opt)) {
62  base64 = 1;
63  } else {
64  av_log(h, AV_LOG_VERBOSE, "Ignoring option '%.*s'\n",
65  (int)(next - opt), opt);
66  }
67  }
68  opt = next + 1;
69  }
70 
71  data++;
72  in_size = strlen(data);
73  if (base64) {
74  size_t out_size = 3 * (in_size / 4) + 1;
75 
76  if (out_size > INT_MAX || !(ddata = av_malloc(out_size)))
77  return AVERROR(ENOMEM);
78  if ((ret = av_base64_decode(ddata, data, out_size)) < 0) {
79  av_free(ddata);
80  av_log(h, AV_LOG_ERROR, "Invalid base64 in URI\n");
81  return ret;
82  }
83  dc->data = dc->tofree = ddata;
84  dc->size = ret;
85  } else {
86  dc->data = data;
87  dc->size = in_size;
88  }
89  return 0;
90 }
91 
93 {
94  DataContext *dc = h->priv_data;
95 
96  av_freep(&dc->tofree);
97  return 0;
98 }
99 
100 static int data_read(URLContext *h, unsigned char *buf, int size)
101 {
102  DataContext *dc = h->priv_data;
103 
104  if (dc->pos >= dc->size)
105  return AVERROR_EOF;
106  size = FFMIN(size, dc->size - dc->pos);
107  memcpy(buf, dc->data + dc->pos, size);
108  dc->pos += size;
109  return size;
110 }
111 
113  .name = "data",
114  .url_open = data_open,
115  .url_close = data_close,
116  .url_read = data_read,
117  .priv_data_size = sizeof(DataContext),
118 };
static int data_read(URLContext *h, unsigned char *buf, int size)
Definition: data_uri.c:100
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
const uint8_t * data
Definition: data_uri.c:27
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
int out_size
Definition: movenc.c:55
size_t pos
Definition: data_uri.c:30
void * tofree
Definition: data_uri.c:28
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
const URLProtocol ff_data_protocol
Definition: data_uri.c:112
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
ptrdiff_t size
Definition: opengl_enc.c:101
#define av_log(a,...)
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition: avutil.h:308
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
static av_cold int data_open(URLContext *h, const char *uri, int flags)
Definition: data_uri.c:33
#define FFMIN(a, b)
Definition: common.h:96
static av_cold int data_close(URLContext *h)
Definition: data_uri.c:92
size_t size
Definition: data_uri.c:29
void * buf
Definition: avisynth_c.h:690
Definition: url.h:38
void * priv_data
Definition: url.h:41
const char * name
Definition: url.h:55
#define flags(name, subs,...)
Definition: cbs_av1.c:596
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
#define av_free(p)
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
Definition: base64.c:79
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> dc
#define av_freep(p)
unbuffered private I/O API