libavutil/base64.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
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 /**
22  * @file
23  * @brief Base64 encode/decode
24  * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
25  */
26 
27 #include "common.h"
28 #include "base64.h"
29 #include "intreadwrite.h"
30 
31 /* ---------------- private code */
32 static const uint8_t map2[256] =
33 {
34  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39  0xff, 0xff, 0xff,
40 
41  0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
42  0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
43  0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x01,
44  0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
45  0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
46  0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
47  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
48  0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
49  0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
50  0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
51 
52  0xff, 0xff, 0xff, 0xff, 0xff,
53  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
56  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
58  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
62  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 };
70 
71 #define BASE64_DEC_STEP(i) do { \
72  bits = map2[in[i]]; \
73  if (bits & 0x80) \
74  goto out ## i; \
75  v = i ? (v << 6) + bits : bits; \
76 } while(0)
77 
78 int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
79 {
80  uint8_t *dst = out;
81  uint8_t *end = out + out_size;
82  // no sign extension
83  const uint8_t *in = in_str;
84  unsigned bits = 0xff;
85  unsigned v;
86 
87  while (end - dst > 3) {
88  BASE64_DEC_STEP(0);
89  BASE64_DEC_STEP(1);
90  BASE64_DEC_STEP(2);
91  BASE64_DEC_STEP(3);
92  // Using AV_WB32 directly confuses compiler
93  v = av_be2ne32(v << 8);
94  AV_WN32(dst, v);
95  dst += 3;
96  in += 4;
97  }
98  if (end - dst) {
99  BASE64_DEC_STEP(0);
100  BASE64_DEC_STEP(1);
101  BASE64_DEC_STEP(2);
102  BASE64_DEC_STEP(3);
103  *dst++ = v >> 16;
104  if (end - dst)
105  *dst++ = v >> 8;
106  if (end - dst)
107  *dst++ = v;
108  in += 4;
109  }
110  while (1) {
111  BASE64_DEC_STEP(0);
112  in++;
113  BASE64_DEC_STEP(0);
114  in++;
115  BASE64_DEC_STEP(0);
116  in++;
117  BASE64_DEC_STEP(0);
118  in++;
119  }
120 
121 out3:
122  *dst++ = v >> 10;
123  v <<= 2;
124 out2:
125  *dst++ = v >> 4;
126 out1:
127 out0:
128  return bits & 1 ? AVERROR_INVALIDDATA : dst - out;
129 }
130 
131 /*****************************************************************************
132 * b64_encode: Stolen from VLC's http.c.
133 * Simplified by Michael.
134 * Fixed edge cases and made it work from data (vs. strings) by Ryan.
135 *****************************************************************************/
136 
137 char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
138 {
139  static const char b64[] =
140  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
141  char *ret, *dst;
142  unsigned i_bits = 0;
143  int i_shift = 0;
144  int bytes_remaining = in_size;
145 
146  if (in_size >= UINT_MAX / 4 ||
147  out_size < AV_BASE64_SIZE(in_size))
148  return NULL;
149  ret = dst = out;
150  while (bytes_remaining > 3) {
151  i_bits = AV_RB32(in);
152  in += 3; bytes_remaining -= 3;
153  *dst++ = b64[ i_bits>>26 ];
154  *dst++ = b64[(i_bits>>20) & 0x3F];
155  *dst++ = b64[(i_bits>>14) & 0x3F];
156  *dst++ = b64[(i_bits>>8 ) & 0x3F];
157  }
158  i_bits = 0;
159  while (bytes_remaining) {
160  i_bits = (i_bits << 8) + *in++;
161  bytes_remaining--;
162  i_shift += 8;
163  }
164  while (i_shift > 0) {
165  *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
166  i_shift -= 6;
167  }
168  while ((dst - ret) & 3)
169  *dst++ = '=';
170  *dst = '\0';
171 
172  return ret;
173 }
174 
175 #ifdef TEST
176 // LCOV_EXCL_START
177 
178 #define MAX_DATA_SIZE 1024
179 #define MAX_ENCODED_SIZE 2048
180 
181 static int test_encode_decode(const uint8_t *data, unsigned int data_size,
182  const char *encoded_ref)
183 {
184  char encoded[MAX_ENCODED_SIZE];
185  uint8_t data2[MAX_DATA_SIZE];
186  int data2_size, max_data2_size = MAX_DATA_SIZE;
187 
188  if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
189  printf("Failed: cannot encode the input data\n");
190  return 1;
191  }
192  if (encoded_ref && strcmp(encoded, encoded_ref)) {
193  printf("Failed: encoded string differs from reference\n"
194  "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
195  return 1;
196  }
197 
198  if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) {
199  printf("Failed: cannot decode the encoded string\n"
200  "Encoded:\n%s\n", encoded);
201  return 1;
202  }
203  if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) {
204  printf("Failed: cannot decode with minimal buffer\n"
205  "Encoded:\n%s\n", encoded);
206  return 1;
207  }
208  if (memcmp(data2, data, data_size)) {
209  printf("Failed: encoded/decoded data differs from original data\n");
210  return 1;
211  }
212  if (av_base64_decode(NULL, encoded, 0) != 0) {
213  printf("Failed: decode to NULL buffer\n");
214  return 1;
215  }
216  if (strlen(encoded)) {
217  char *end = strchr(encoded, '=');
218  if (!end)
219  end = encoded + strlen(encoded) - 1;
220  *end = '%';
221  if (av_base64_decode(NULL, encoded, 0) >= 0) {
222  printf("Failed: error detection\n");
223  return 1;
224  }
225  }
226 
227  printf("Passed!\n");
228  return 0;
229 }
230 
231 int main(int argc, char ** argv)
232 {
233  int i, error_count = 0;
234  struct test {
235  const uint8_t *data;
236  const char *encoded_ref;
237  } tests[] = {
238  { "", ""},
239  { "1", "MQ=="},
240  { "22", "MjI="},
241  { "333", "MzMz"},
242  { "4444", "NDQ0NA=="},
243  { "55555", "NTU1NTU="},
244  { "666666", "NjY2NjY2"},
245  { "abc:def", "YWJjOmRlZg=="},
246  };
247  char in[1024], out[2048];
248 
249  printf("Encoding/decoding tests\n");
250  for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
251  error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
252 
253  if (argc>1 && !strcmp(argv[1], "-t")) {
254  memset(in, 123, sizeof(in));
255  for(i=0; i<10000; i++){
257  av_base64_encode(out, sizeof(out), in, sizeof(in));
258  STOP_TIMER("encode")
259  }
260  for(i=0; i<10000; i++){
262  av_base64_decode(in, out, sizeof(in));
263  STOP_TIMER("decode")
264  }
265 
266  for(i=0; i<10000; i++){
268  av_base64_decode(NULL, out, 0);
269  STOP_TIMER("syntax check")
270  }
271  }
272 
273  return error_count;
274 }
275 
276 // LCOV_EXCL_STOP
277 #endif
float v
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
#define FF_ARRAY_ELEMS(a)
#define av_be2ne32(x)
Definition: bswap.h:93
Definition: test.py:1
uint8_t bits
Definition: crc.c:216
uint8_t
#define AV_RB32
static const uint8_t map2[256]
end end
#define BASE64_DEC_STEP(i)
Spectrum Plot time data
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
Definition: base64.h:61
ret
Definition: avfilter.c:821
NULL
Definition: eval.c:55
#define START_TIMER
Definition: timer.h:74
synthesis window for stochastic i
common internal and external API header
#define AV_WN32(p, v)
Definition: intreadwrite.h:368
#define STOP_TIMER(id)
Definition: timer.h:75
printf("static const uint8_t my_array[100] = {\n")
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;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);return NULL;}return ac;}in_planar=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_dlog(ac->avr,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
int main(int argc, char **argv)
Definition: main.c:22