1 /*
2 * Copyright 2013-2016, Björn Ståhl
3 * License: 3-Clause BSD, see COPYING file in arcan source repository.
4 * Reference: http://arcan-fe.com
5 */
6
7 #include <libavcodec/avcodec.h>
8 #include <libavformat/avformat.h>
9 #include <libavformat/avio.h>
10 #include <libavutil/imgutils.h>
11
12 #include <sys/stat.h>
13 #include <assert.h>
14 #include <stdbool.h>
15 #include <stdint.h>
16 #include <unistd.h>
17
18 #include <arcan_shmif.h>
19 #include "frameserver.h"
20 #include "encode_presets.h"
21
vcodec_defaults(struct codec_ent * dst,unsigned width,unsigned height,float fps,unsigned vbr)22 static void vcodec_defaults(struct codec_ent* dst, unsigned width,
23 unsigned height, float fps, unsigned vbr)
24 {
25 AVCodecContext* ctx = dst->storage.video.context;
26
27 ctx->width = width;
28 ctx->height = height;
29 ctx->bit_rate = vbr;
30 ctx->pix_fmt = AV_PIX_FMT_YUV420P;
31 ctx->gop_size = 12;
32 ctx->time_base.den = fps;
33 ctx->time_base.num = 1;
34
35 AVFrame* pframe = av_frame_alloc();
36 pframe->width = width;
37 pframe->height = height;
38 pframe->format = ctx->pix_fmt;
39 av_image_alloc(pframe->data, pframe->linesize,
40 width, height, ctx->pix_fmt, 32);
41
42 dst->storage.video.pframe = pframe;
43 }
44
default_vcodec_setup(struct codec_ent * dst,unsigned width,unsigned height,float fps,unsigned vbr,bool stream)45 static bool default_vcodec_setup(struct codec_ent* dst, unsigned width,
46 unsigned height, float fps, unsigned vbr, bool stream)
47 {
48 AVCodecContext* ctx = dst->storage.video.context;
49
50 assert(width % 2 == 0);
51 assert(height % 2 == 0);
52 assert(fps > 0 && fps <= 60);
53 assert(ctx);
54
55 vcodec_defaults(dst, width, height, fps, vbr);
56 /* terrible */
57 if (vbr <= 10){
58 vbr = 150 * 1024;
59 }
60
61 ctx->bit_rate = vbr;
62
63 if (avcodec_open2(dst->storage.video.context,
64 dst->storage.video.codec, NULL) != 0){
65 dst->storage.video.codec = NULL;
66 dst->storage.video.context = NULL;
67 avcodec_close(dst->storage.video.context);
68 return false;
69 }
70
71 return true;
72 }
73
default_acodec_setup(struct codec_ent * dst,unsigned channels,unsigned samplerate,unsigned abr)74 static bool default_acodec_setup(struct codec_ent* dst, unsigned channels,
75 unsigned samplerate, unsigned abr)
76 {
77 AVCodecContext* ctx = dst->storage.audio.context;
78 AVCodec* codec = dst->storage.audio.codec;
79
80 assert(channels == 2);
81 assert(samplerate > 0 && samplerate <= 48000);
82 assert(codec);
83
84 ctx->channels = channels;
85 ctx->channel_layout = av_get_default_channel_layout(channels);
86
87 ctx->sample_rate = samplerate;
88 ctx->time_base = av_d2q(1.0 / (double) samplerate, 1000000);
89 ctx->sample_fmt = codec->sample_fmts[0];
90
91 /* kept for documentation, now we assume the swr_convert just
92 * handles all sample formats for us,
93 * if we prefer or require a certain on in the future, the following code
94 * shows how:
95 for (int i = 0; codec->sample_fmts[i] != -1 && ctx->sample_fmt ==
96 AV_SAMPLE_FMT_NONE; i++){
97 if (codec->sample_fmts[i] == AV_SAMPLE_FMT_S16 ||
98 codec->sample_fmts[i] == AV_SAMPLE_FMT_FLTP)
99 ctx->sample_fmt = codec->sample_fmts[i];
100 }
101
102 if (ctx->sample_fmt == AV_SAMPLE_FMT_NONE){
103 LOG("(encoder) Couldn't find supported matching sample format for
104 codec, giving up.\n");
105 return false;
106 }
107 */
108
109 /* rough quality estimate */
110 if (abr <= 10)
111 ctx->bit_rate = 1024 * ( 320 - 240 * ((float)(11.0 - abr) / 11.0) );
112 else
113 ctx->bit_rate = abr;
114
115 /* AAC may need this */
116 ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
117
118 LOG("(encode) audio encoder setup @ %d hz, requested quality: %d, "
119 "got %d kbit/s using %s\n", samplerate, abr,
120 (int)(ctx->bit_rate / 1000), codec->name);
121
122 if (avcodec_open2(dst->storage.audio.context,
123 dst->storage.audio.codec, NULL) != 0){
124 avcodec_close(dst->storage.audio.context);
125 dst->storage.audio.context = NULL;
126 dst->storage.audio.codec = NULL;
127 return false;
128 }
129
130 return true;
131 }
132
default_format_setup(struct codec_ent * dst)133 static bool default_format_setup(struct codec_ent* dst)
134 {
135 int rc = avformat_write_header(dst->storage.container.context, NULL);
136 LOG("(encode) header status (%d)\n", rc);
137 return rc == 0;
138 }
139
setup_cb_x264(struct codec_ent * dst,unsigned width,unsigned height,float fps,unsigned vbr,bool stream)140 static bool setup_cb_x264(struct codec_ent* dst, unsigned width,
141 unsigned height, float fps, unsigned vbr, bool stream)
142 {
143 AVDictionary* opts = NULL;
144 float vbrf = 1000 * (height >= 720 ? 2.0 : 1.0);
145
146 vcodec_defaults(dst, width, height, fps, vbr);
147 if (vbr == 10){
148 av_dict_set(&opts, "preset", "medium", 0);
149 av_dict_set(&opts, "crf", "4", 0);
150 vbr = vbrf * 1200;
151 } else if (vbr == 9){
152 av_dict_set(&opts, "preset", "medium", 0);
153 av_dict_set(&opts, "crf", "8", 0);
154 vbr = vbrf * 1100;
155 } else if (vbr == 8){
156 av_dict_set(&opts, "preset", "medium", 0);
157 av_dict_set(&opts, "crf", "14", 0);
158 vbr = vbrf * 1000;
159 } else if (vbr == 7){
160 av_dict_set(&opts, "preset", "medium", 0);
161 av_dict_set(&opts, "crf", "18", 0);
162 vbr = vbrf * 900;
163 } else if (vbr == 6){
164 av_dict_set(&opts, "preset", "fast", 0 );
165 av_dict_set(&opts, "crf", "22", 0);
166 vbr = vbrf * 800;
167 } else if (vbr == 5){
168 av_dict_set(&opts, "preset", "fast", 0 );
169 av_dict_set(&opts, "crf", "24", 0);
170 vbr = vbrf * 700;
171 } else if (vbr == 4){
172 av_dict_set(&opts, "preset", "faster", 0);
173 av_dict_set(&opts, "crf", "26", 0);
174 vbr = vbrf * 600;
175 } else if (vbr == 3){
176 av_dict_set(&opts, "preset", "faster", 0 );
177 av_dict_set(&opts, "crf", "32", 0);
178 vbr = vbrf * 550;
179 } else if (vbr == 2){
180 av_dict_set(&opts, "preset", "superfast", 0);
181 av_dict_set(&opts, "crf", "36", 0);
182 vbr = vbrf * 400;
183 } else if (vbr == 1){
184 av_dict_set(&opts, "preset", "superfast", 0);
185 av_dict_set(&opts, "crf", "44", 0);
186 vbr = vbrf * 350;
187 } else if (vbr == 0){
188 av_dict_set(&opts, "preset", "superfast", 0);
189 av_dict_set(&opts, "crf", "48", 0);
190 vbr = vbrf * 300;
191 } else {
192 av_dict_set(&opts, "preset", "medium", 0);
193 av_dict_set(&opts, "crf", "25", 0);
194 }
195
196 if (stream)
197 av_dict_set(&opts, "preset", "faster", 0);
198
199 dst->storage.video.context->bit_rate = vbr;
200
201 LOG("(encode) video setup @ %d * %d, %f fps, %d kbit / s.\n",
202 width, height, fps, vbr / 1000);
203
204 if (avcodec_open2(dst->storage.video.context,
205 dst->storage.video.codec, &opts) != 0){
206 avcodec_close(dst->storage.video.context);
207 dst->storage.video.context = NULL;
208 dst->storage.video.codec = NULL;
209 return false;
210 }
211
212 return true;
213 }
214
215 /* would be nice with some decent evaluation of all the parameters and
216 * their actual cost / benefit. */
setup_cb_vp8(struct codec_ent * dst,unsigned width,unsigned height,float fps,unsigned vbr,bool stream)217 static bool setup_cb_vp8(struct codec_ent* dst, unsigned width,
218 unsigned height, float fps, unsigned vbr, bool stream)
219 {
220 AVDictionary* opts = NULL;
221 const char* const lif = fps > 30.0 ? "25" : "16";
222
223 vcodec_defaults(dst, width, height, fps, vbr);
224
225 /* options we want to set irrespective of bitrate */
226 if (height > 720){
227 av_dict_set(&opts, "slices", "4", 0);
228 av_dict_set(&opts, "qmax", "54", 0);
229 av_dict_set(&opts, "qmin", "11", 0);
230 av_dict_set(&opts, "vprofile", "1", 0);
231
232 } else if (height > 480){
233 av_dict_set(&opts, "slices", "4", 0);
234 av_dict_set(&opts, "qmax", "54", 0);
235 av_dict_set(&opts, "qmin", "11", 0);
236 av_dict_set(&opts, "vprofile", "1", 0);
237
238 } else if (height > 360){
239 av_dict_set(&opts, "slices", "4", 0);
240 av_dict_set(&opts, "qmax", "54", 0);
241 av_dict_set(&opts, "qmin", "11", 0);
242 av_dict_set(&opts, "vprofile", "1", 0);
243 }
244 else {
245 av_dict_set(&opts, "qmax", "63", 0);
246 av_dict_set(&opts, "qmin", "0", 0);
247 av_dict_set(&opts, "vprofile", "0", 0);
248 }
249
250 av_dict_set(&opts, "lag-in-frames", lif, 0);
251 av_dict_set(&opts, "g", "120", 0);
252
253
254 if (vbr <= 10){
255 /* "HD" */
256 if (height > 360)
257 vbr = 1024 + 1024 * ( (float)(vbr+1) /11.0 * 2.0 );
258 /* "LD" */
259 else
260 vbr = 365 + 365 * ( (float)(vbr+1) /11.0 * 2.0 );
261
262 vbr *= 1024; /* to bit/s */
263 }
264
265 av_dict_set(&opts, "quality", "realtime", 0);
266 dst->storage.video.context->bit_rate = vbr;
267
268 LOG("(encode) video setup @ %d * %d, %f fps, %d kbit / s.\n",
269 width, height, fps, vbr / 1024);
270 if (avcodec_open2(dst->storage.video.context,
271 dst->storage.video.codec, &opts) != 0){
272 avcodec_close(dst->storage.video.context);
273 dst->storage.video.context = NULL;
274 dst->storage.video.codec = NULL;
275 return false;
276 }
277
278 return true;
279 }
280
281 static struct codec_ent vcodec_tbl[] = {
282 {.kind = CODEC_VIDEO,
283 .name = "libvpx",
284 .shortname = "VP8",
285 .id = AV_CODEC_ID_VP8,
286 .setup.video = setup_cb_vp8},
287
288 {.kind = CODEC_VIDEO,
289 .name = "libx264",
290 .shortname = "H264",
291 .id = AV_CODEC_ID_H264,
292 .setup.video = setup_cb_x264},
293
294 {.kind = CODEC_VIDEO,
295 .name = "ffv1",
296 .shortname = "FFV1",
297 .id = AV_CODEC_ID_FFV1,
298 .setup.video = default_vcodec_setup },
299 };
300
301 static struct codec_ent acodec_tbl[] = {
302 {.kind = CODEC_AUDIO, .name = "libvorbis",
303 .shortname = "VORBIS",
304 .id = 0,
305 .setup.audio = default_acodec_setup},
306
307 {.kind = CODEC_AUDIO,
308 .name = "libmp3lame",
309 .shortname = "MP3",
310 .id = 0,
311 .setup.audio = default_acodec_setup},
312
313 {.kind = CODEC_AUDIO,
314 .name = "flac",
315 .shortname = "FLAC",
316 .id = AV_CODEC_ID_FLAC,
317 .setup.audio = default_acodec_setup},
318
319 {.kind = CODEC_AUDIO,
320 .name = "aac",
321 .shortname = "AAC",
322 .id = AV_CODEC_ID_AAC,
323 .setup.audio = default_acodec_setup},
324
325 {.kind = CODEC_AUDIO,
326 .name = "pcm_s16le_planar",
327 .shortname = "RAW",
328 .id = 0,
329 .setup.audio = default_acodec_setup}
330 };
331
lookup_default(const char * const req,struct codec_ent * tbl,size_t nmemb,bool audio)332 static struct codec_ent lookup_default(const char* const req,
333 struct codec_ent* tbl, size_t nmemb, bool audio)
334 {
335 struct codec_ent res = {.name = req};
336 AVCodec** dst = audio ? &res.storage.audio.codec : &res.storage.video.codec;
337
338 if (req){
339 /* make sure that if the user supplies a name already in the standard table,
340 * that we get the same prefix setup function */
341 for (int i = 0; i < nmemb; i++)
342 if (tbl[i].name != NULL && (strcmp(req, tbl[i].name) == 0 ||
343 strcmp(req, tbl[i].shortname) == 0) ){
344 memcpy(&res, &tbl[i], sizeof(struct codec_ent));
345 *dst = avcodec_find_encoder_by_name(res.name);
346 }
347
348 /* if the codec specified is unknown (to us) then let
349 * avcodec try and sort it up, return default setup */
350 if (*dst == NULL){
351 *dst = avcodec_find_encoder_by_name(req);
352 }
353 }
354
355 /* if the user didn't supply an explicit codec, or one was not found,
356 * search the table for reasonable default */
357 for (int i = 0; i < nmemb && *dst == NULL; i++)
358 if (tbl[i].name != NULL && tbl[i].id == 0){
359 memcpy(&res, &tbl[i], sizeof(struct codec_ent));
360 *dst = avcodec_find_encoder_by_name(tbl[i].name);
361 }
362 else{
363 memcpy(&res, &tbl[i], sizeof(struct codec_ent));
364 *dst = avcodec_find_encoder(tbl[i].id);
365 }
366
367 return res;
368 }
369
encode_getvcodec(const char * const req,int flags)370 struct codec_ent encode_getvcodec(const char* const req, int flags)
371 {
372 struct codec_ent a = lookup_default(req, vcodec_tbl,
373 sizeof(vcodec_tbl) / sizeof(vcodec_tbl[0]), false);
374 if (a.storage.video.codec && !a.setup.video)
375 a.setup.video = default_vcodec_setup;
376
377 if (!a.storage.video.codec)
378 return a;
379
380 a.storage.video.context = avcodec_alloc_context3( a.storage.video.codec );
381 if (flags & AVFMT_GLOBALHEADER)
382 a.storage.video.context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
383
384 return a;
385 }
386
encode_getacodec(const char * const req,int flags)387 struct codec_ent encode_getacodec(const char* const req, int flags)
388 {
389 struct codec_ent res = lookup_default(req, acodec_tbl,
390 sizeof(acodec_tbl) / sizeof(acodec_tbl[0]), true);
391
392 if (res.storage.audio.codec && !res.setup.audio)
393 res.setup.audio = default_acodec_setup;
394
395 if (!res.storage.audio.codec)
396 return res;
397
398 res.storage.audio.context = avcodec_alloc_context3( res.storage.audio.codec);
399 if ( (flags & AVFMT_GLOBALHEADER) > 0){
400 res.storage.audio.context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
401 }
402
403 return res;
404 }
405
fds(void * infd,int64_t pos,int whence)406 static int64_t fds(void* infd, int64_t pos, int whence)
407 {
408 int fd = *(int*) infd;
409
410 int64_t ret;
411
412 if (whence == AVSEEK_SIZE){
413 struct stat st;
414 ret = fstat(fd, &st);
415
416 return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
417 }
418
419 ret = lseek(fd, pos, whence);
420 return ret < 0 ? AVERROR(errno) : ret;
421 }
422
fdw(void * fd,uint8_t * buf,int buf_size)423 static int fdw(void* fd, uint8_t* buf, int buf_size)
424 {
425 return write(*(int*)fd, buf, buf_size);
426 }
427
fdr(void * fd,uint8_t * buf,int buf_size)428 static int fdr(void* fd, uint8_t* buf, int buf_size)
429 {
430 return read(*(int*)fd, buf, buf_size);
431 }
432
433 /* slightly difference scanning function here so can't re-use lookup_default */
encode_getcontainer(const char * const requested,int dst,const char * remote)434 struct codec_ent encode_getcontainer(const char* const requested,
435 int dst, const char* remote)
436 {
437 AVFormatContext* ctx;
438 struct codec_ent res = {0};
439
440 if (requested && strcmp(requested, "stream") == 0){
441 res.storage.container.format = av_guess_format("flv", NULL, NULL);
442
443 if (!res.storage.container.format)
444 LOG("(encode) couldn't setup streaming output.\n");
445 else {
446 ctx = avformat_alloc_context();
447 ctx->oformat = res.storage.container.format;
448 res.storage.container.context = ctx;
449 res.setup.muxer = default_format_setup;
450 int rv = avio_open2(&ctx->pb, remote, AVIO_FLAG_WRITE, NULL, NULL);
451 LOG("(encode) attempting to open: %s, result: %d\n", remote, rv);
452 }
453
454 return res;
455 }
456
457 if (requested)
458 res.storage.container.format = av_guess_format(requested, NULL, NULL);
459
460 if (!res.storage.container.format){
461 LOG("(encode) couldn't find a suitable container matching (%s),"
462 " reverting to matroska (MKV)\n", requested);
463 res.storage.container.format = av_guess_format("matroska", NULL, NULL);
464 } else
465 LOG("(encode) requested container (%s) found.\n", requested);
466
467 /* no stream, nothing requested that matched and default didn't work.
468 * Give up and cascade. */
469 if (!res.storage.container.format){
470 LOG("(encode) couldn't find a suitable container.\n");
471 return res;
472 }
473
474 avformat_alloc_output_context2(&ctx, res.storage.container.format,
475 NULL, NULL);
476
477 /*
478 * Since there's no sane way for us to just pass a file descriptor and
479 * not be limited to pipe behaviors, we have to provide an entire
480 * custom avio class..
481 */
482 int* fdbuf = malloc(sizeof(int));
483 *fdbuf = dst;
484 ctx->pb = avio_alloc_context(av_malloc(4096), 4096, 1, fdbuf, fdr, fdw, fds);
485
486 res.storage.container.context = ctx;
487 res.setup.muxer = default_format_setup;
488
489 return res;
490 }
491