summaryrefslogtreecommitdiffstats
path: root/core/encode_lavc.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/encode_lavc.c')
-rw-r--r--core/encode_lavc.c1115
1 files changed, 0 insertions, 1115 deletions
diff --git a/core/encode_lavc.c b/core/encode_lavc.c
deleted file mode 100644
index 75e57a2443..0000000000
--- a/core/encode_lavc.c
+++ /dev/null
@@ -1,1115 +0,0 @@
-/*
- * muxing using libavformat
- * Copyright (C) 2010 Nicolas George <george@nsup.org>
- * Copyright (C) 2011-2012 Rudolf Polzer <divVerent@xonotic.org>
- *
- * This file is part of mpv.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include "encode_lavc.h"
-#include "core/mp_msg.h"
-#include "video/vfcap.h"
-#include "core/options.h"
-#include "osdep/timer.h"
-#include "video/out/vo.h"
-#include "talloc.h"
-#include "stream/stream.h"
-
-static int set_to_avdictionary(AVDictionary **dictp, const char *key,
- const char *val)
-{
- char keybuf[1024];
- char valuebuf[1024];
-
- if (key == NULL) {
- // we need to split at equals sign
- const char *equals = strchr(val, '=');
- if (!equals || equals - val >= sizeof(keybuf)) {
- mp_msg(MSGT_ENCODE, MSGL_WARN,
- "encode-lavc: option '%s' does not contain an equals sign\n",
- val);
- return 0;
- }
- memcpy(keybuf, val, equals - val);
- keybuf[equals - val] = 0;
- key = keybuf;
- val = equals + 1;
- }
-
- // hack: support "qscale" key as virtual "global_quality" key that multiplies by QP2LAMBDA
- if (!strcmp(key, "qscale")) {
- key = "global_quality";
- snprintf(valuebuf, sizeof(valuebuf),
- "%.1s(%s)*QP2LAMBDA",
- (val[0] == '+' || val[0] == '-') ? val : "",
- (val[0] == '+' || val[0] == '-') ? val + 1 : val);
- valuebuf[sizeof(valuebuf) - 1] = 0;
- val = valuebuf;
- }
-
- mp_msg(MSGT_ENCODE, MSGL_V,
- "encode-lavc: setting value '%s' for key '%s'\n",
- val,
- key);
-
- if (av_dict_set(dictp, key, *val ? val : NULL,
- (val[0] == '+' || val[0] == '-') ? AV_DICT_APPEND : 0) >= 0)
- return 1;
-
- return 0;
-}
-
-static bool value_has_flag(const char *value, const char *flag)
-{
- bool state = true;
- bool ret = false;
- while (*value) {
- size_t l = strcspn(value, "+-");
- if (l == 0) {
- state = (*value == '+');
- ++value;
- } else {
- if (l == strlen(flag))
- if (!memcmp(value, flag, l))
- ret = state;
- value += l;
- }
- }
- return ret;
-}
-
-#define CHECK_FAIL(ctx, val) \
- if (ctx && (ctx->failed || ctx->finished)) { \
- mp_msg(MSGT_ENCODE, MSGL_ERR, \
- "Called a function on a %s encoding context. Bailing out.\n", \
- ctx->failed ? "failed" : "finished"); \
- return val; \
- }
-
-int encode_lavc_available(struct encode_lavc_context *ctx)
-{
- CHECK_FAIL(ctx, 0);
- return ctx && ctx->avc;
-}
-
-int encode_lavc_oformat_flags(struct encode_lavc_context *ctx)
-{
- CHECK_FAIL(ctx, 0);
- return ctx->avc ? ctx->avc->oformat->flags : 0;
-}
-
-struct encode_lavc_context *encode_lavc_init(struct encode_output_conf *options)
-{
- struct encode_lavc_context *ctx;
- const char *filename = options->file;
-
- // STUPID STUPID STUPID STUPID avio
- // does not support "-" as file name to mean stdin/stdout
- // ffmpeg.c works around this too, the same way
- if (!strcmp(filename, "-"))
- filename = "pipe:1";
-
- if (filename && (
- !strcmp(filename, "/dev/stdout") ||
- !strcmp(filename, "pipe:") ||
- !strcmp(filename, "pipe:1")))
- mp_msg_stdout_in_use = 1;
-
- ctx = talloc_zero(NULL, struct encode_lavc_context);
- encode_lavc_discontinuity(ctx);
- ctx->options = options;
-
- ctx->avc = avformat_alloc_context();
-
- if (ctx->options->format) {
- char *tok;
- const char *in = ctx->options->format;
- while (*in) {
- tok = av_get_token(&in, ",");
- ctx->avc->oformat = av_guess_format(tok, filename, NULL);
- av_free(tok);
- if (ctx->avc->oformat)
- break;
- if (*in)
- ++in;
- }
- } else
- ctx->avc->oformat = av_guess_format(NULL, filename, NULL);
-
- if (!ctx->avc->oformat) {
- encode_lavc_fail(ctx, "encode-lavc: format not found\n");
- return NULL;
- }
-
- av_strlcpy(ctx->avc->filename, filename,
- sizeof(ctx->avc->filename));
-
- ctx->foptions = NULL;
- if (ctx->options->fopts) {
- char **p;
- for (p = ctx->options->fopts; *p; ++p) {
- if (!set_to_avdictionary(&ctx->foptions, NULL, *p))
- mp_msg(MSGT_ENCODE, MSGL_WARN,
- "encode-lavc: could not set option %s\n", *p);
- }
- }
-
- if (ctx->options->vcodec) {
- char *tok;
- const char *in = ctx->options->vcodec;
- while (*in) {
- tok = av_get_token(&in, ",");
- ctx->vc = avcodec_find_encoder_by_name(tok);
- av_free(tok);
- if (ctx->vc && ctx->vc->type != AVMEDIA_TYPE_VIDEO)
- ctx->vc = NULL;
- if (ctx->vc)
- break;
- if (*in)
- ++in;
- }
- } else
- ctx->vc = avcodec_find_encoder(av_guess_codec(ctx->avc->oformat, NULL,
- ctx->avc->filename, NULL,
- AVMEDIA_TYPE_VIDEO));
-
- if (ctx->options->acodec) {
- char *tok;
- const char *in = ctx->options->acodec;
- while (*in) {
- tok = av_get_token(&in, ",");
- ctx->ac = avcodec_find_encoder_by_name(tok);
- av_free(tok);
- if (ctx->ac && ctx->ac->type != AVMEDIA_TYPE_AUDIO)
- ctx->ac = NULL;
- if (ctx->ac)
- break;
- if (*in)
- ++in;
- }
- } else
- ctx->ac = avcodec_find_encoder(av_guess_codec(ctx->avc->oformat, NULL,
- ctx->avc->filename, NULL,
- AVMEDIA_TYPE_AUDIO));
-
- if (!ctx->vc && !ctx->ac) {
- encode_lavc_fail(
- ctx, "encode-lavc: neither audio nor video codec was found\n");
- return NULL;
- }
-
- /* taken from ffmpeg unchanged
- * TODO turn this into an option if anyone needs this */
-
- ctx->avc->max_delay = 0.7 * AV_TIME_BASE;
-
- ctx->abytes = 0;
- ctx->vbytes = 0;
- ctx->frames = 0;
-
- if (options->video_first)
- ctx->video_first = true;
- if (options->audio_first)
- ctx->audio_first = true;
-
- return ctx;
-}
-
-int encode_lavc_start(struct encode_lavc_context *ctx)
-{
- AVDictionaryEntry *de;
- unsigned i;
-
- if (ctx->header_written < 0)
- return 0;
- if (ctx->header_written > 0)
- return 1;
-
- CHECK_FAIL(ctx, 0);
-
- if (ctx->expect_video) {
- for (i = 0; i < ctx->avc->nb_streams; ++i)
- if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
- break;
- if (i >= ctx->avc->nb_streams) {
- encode_lavc_fail(ctx,
- "encode-lavc: video stream missing, invalid codec?\n");
- return 0;
- }
- }
- if (ctx->expect_audio) {
- for (i = 0; i < ctx->avc->nb_streams; ++i)
- if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
- break;
- if (i >= ctx->avc->nb_streams) {
- encode_lavc_fail(ctx,
- "encode-lavc: audio stream missing, invalid codec?\n");
- return 0;
- }
- }
-
- ctx->header_written = -1;
-
- if (!(ctx->avc->oformat->flags & AVFMT_NOFILE)) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Opening output file: %s\n",
- ctx->avc->filename);
-
- if (avio_open(&ctx->avc->pb, ctx->avc->filename,
- AVIO_FLAG_WRITE) < 0) {
- encode_lavc_fail(ctx, "encode-lavc: could not open '%s'\n",
- ctx->avc->filename);
- return 0;
- }
- }
-
- ctx->t0 = mp_time_sec();
-
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Opening muxer: %s [%s]\n",
- ctx->avc->oformat->long_name, ctx->avc->oformat->name);
-
- if (avformat_write_header(ctx->avc, &ctx->foptions) < 0) {
- encode_lavc_fail(ctx, "encode-lavc: could not write header\n");
- return 0;
- }
-
- for (de = NULL; (de = av_dict_get(ctx->foptions, "", de,
- AV_DICT_IGNORE_SUFFIX));)
- mp_msg(MSGT_ENCODE, MSGL_WARN, "ofopts: key '%s' not found.\n", de->key);
- av_dict_free(&ctx->foptions);
-
- ctx->header_written = 1;
- return 1;
-}
-
-void encode_lavc_free(struct encode_lavc_context *ctx)
-{
- if (!ctx)
- return;
-
- if (!ctx->finished)
- encode_lavc_fail(ctx,
- "called encode_lavc_free without encode_lavc_finish\n");
-
- talloc_free(ctx);
-}
-
-void encode_lavc_finish(struct encode_lavc_context *ctx)
-{
- unsigned i;
-
- if (!ctx)
- return;
-
- if (ctx->finished)
- return;
-
- if (ctx->avc) {
- if (ctx->header_written > 0)
- av_write_trailer(ctx->avc); // this is allowed to fail
-
- for (i = 0; i < ctx->avc->nb_streams; i++) {
- switch (ctx->avc->streams[i]->codec->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- if (ctx->twopass_bytebuffer_v) {
- char *stats = ctx->avc->streams[i]->codec->stats_out;
- if (stats)
- stream_write_buffer(ctx->twopass_bytebuffer_v,
- stats, strlen(stats));
- }
- break;
- case AVMEDIA_TYPE_AUDIO:
- if (ctx->twopass_bytebuffer_a) {
- char *stats = ctx->avc->streams[i]->codec->stats_out;
- if (stats)
- stream_write_buffer(ctx->twopass_bytebuffer_a,
- stats, strlen(stats));
- }
- break;
- default:
- break;
- }
- avcodec_close(ctx->avc->streams[i]->codec);
- talloc_free(ctx->avc->streams[i]->codec->stats_in);
- av_free(ctx->avc->streams[i]->codec);
- av_free(ctx->avc->streams[i]->info);
- av_free(ctx->avc->streams[i]);
- }
-
- if (ctx->twopass_bytebuffer_v) {
- free_stream(ctx->twopass_bytebuffer_v);
- ctx->twopass_bytebuffer_v = NULL;
- }
-
- if (ctx->twopass_bytebuffer_a) {
- free_stream(ctx->twopass_bytebuffer_a);
- ctx->twopass_bytebuffer_a = NULL;
- }
-
- mp_msg(MSGT_ENCODE, MSGL_INFO, "vo-lavc: encoded %lld bytes\n",
- ctx->vbytes);
- mp_msg(MSGT_ENCODE, MSGL_INFO, "ao-lavc: encoded %lld bytes\n",
- ctx->abytes);
- if (ctx->avc->pb) {
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "encode-lavc: muxing overhead %lld bytes\n",
- (long long) (avio_size(ctx->avc->pb) - ctx->vbytes
- - ctx->abytes));
- avio_close(ctx->avc->pb);
- }
-
- av_free(ctx->avc);
- }
-
- ctx->finished = true;
-}
-
-void encode_lavc_set_video_fps(struct encode_lavc_context *ctx, float fps)
-{
- ctx->vo_fps = fps;
-}
-
-static void encode_2pass_prepare(struct encode_lavc_context *ctx,
- AVDictionary **dictp,
- AVStream *stream, struct stream **bytebuf,
- const char *prefix)
-{
- if (!*bytebuf) {
- char buf[sizeof(ctx->avc->filename) + 12];
- AVDictionaryEntry *de = av_dict_get(ctx->voptions, "flags", NULL, 0);
-
- snprintf(buf, sizeof(buf), "%s-%s-pass1.log", ctx->avc->filename,
- prefix);
- buf[sizeof(buf) - 1] = 0;
-
- if (value_has_flag(de ? de->value : "", "pass2")) {
- if (!(*bytebuf = stream_open(buf, NULL))) {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "%s: could not open '%s', "
- "disabling 2-pass encoding at pass 2\n", prefix, buf);
- stream->codec->flags &= ~CODEC_FLAG_PASS2;
- set_to_avdictionary(dictp, "flags", "-pass2");
- } else {
- struct bstr content = stream_read_complete(*bytebuf, NULL,
- 1000000000);
- if (content.start == NULL) {
- mp_msg(MSGT_ENCODE, MSGL_WARN, "%s: could not read '%s', "
- "disabling 2-pass encoding at pass 1\n",
- prefix, ctx->avc->filename);
- } else {
- content.start[content.len] = 0;
- stream->codec->stats_in = content.start;
- }
- free_stream(*bytebuf);
- *bytebuf = NULL;
- }
- }
-
- if (value_has_flag(de ? de->value : "", "pass1")) {
- if (!(*bytebuf = open_output_stream(buf, NULL))) {
- mp_msg(
- MSGT_ENCODE, MSGL_WARN,
- "%s: could not open '%s', disabling "
- "2-pass encoding at pass 1\n",
- prefix, ctx->avc->filename);
- set_to_avdictionary(dictp, "flags", "-pass1");
- }
- }
- }
-}
-
-AVStream *encode_lavc_alloc_stream(struct encode_lavc_context *ctx,
- enum AVMediaType mt)
-{
- AVDictionaryEntry *de;
- AVStream *stream = NULL;
- char **p;
- int i;
-
- CHECK_FAIL(ctx, NULL);
-
- if (ctx->header_written)
- return NULL;
-
- for (i = 0; i < ctx->avc->nb_streams; ++i)
- if (ctx->avc->streams[i]->codec->codec_type == mt)
- // already have a stream of that type, this cannot really happen
- return NULL;
-
- if (ctx->avc->nb_streams == 0) {
- // if this stream isn't stream #0, allocate a dummy stream first for
- // the next loop to use
- if (mt == AVMEDIA_TYPE_VIDEO && ctx->audio_first) {
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "vo-lavc: preallocated audio stream for later use\n");
- avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
- }
- if (mt == AVMEDIA_TYPE_AUDIO && ctx->video_first) {
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "ao-lavc: preallocated video stream for later use\n");
- avformat_new_stream(ctx->avc, NULL); // this one is AVMEDIA_TYPE_UNKNOWN for now
- }
- } else {
- // find possibly preallocated stream
- for (i = 0; i < ctx->avc->nb_streams; ++i)
- if (ctx->avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_UNKNOWN) // preallocated stream
- stream = ctx->avc->streams[i];
- }
- if (!stream)
- stream = avformat_new_stream(ctx->avc, NULL);
-
- if (ctx->timebase.den == 0) {
- AVRational r;
-
- if (ctx->options->fps > 0)
- r = av_d2q(ctx->options->fps, ctx->options->fps * 1001 + 2);
- else if (ctx->options->autofps && ctx->vo_fps > 0) {
- r = av_d2q(ctx->vo_fps, ctx->vo_fps * 1001 + 2);
- mp_msg(
- MSGT_ENCODE, MSGL_INFO, "vo-lavc: option --ofps not specified "
- "but --oautofps is active, using guess of %u/%u\n",
- (unsigned)r.num, (unsigned)r.den);
- } else {
- // we want to handle:
- // 1/25
- // 1001/24000
- // 1001/30000
- // for this we would need 120000fps...
- // however, mpeg-4 only allows 16bit values
- // so let's take 1001/30000 out
- r.num = 24000;
- r.den = 1;
- mp_msg(
- MSGT_ENCODE, MSGL_INFO, "vo-lavc: option --ofps not specified "
- "and fps could not be inferred, using guess of %u/%u\n",
- (unsigned)r.num, (unsigned)r.den);
- }
-
- if (ctx->vc && ctx->vc->supported_framerates)
- r = ctx->vc->supported_framerates[av_find_nearest_q_idx(r,
- ctx->vc->supported_framerates)];
-
- ctx->timebase.num = r.den;
- ctx->timebase.den = r.num;
- }
-
- switch (mt) {
- case AVMEDIA_TYPE_VIDEO:
- if (!ctx->vc) {
- encode_lavc_fail(ctx, "vo-lavc: encoder not found\n");
- return NULL;
- }
- avcodec_get_context_defaults3(stream->codec, ctx->vc);
-
- // stream->time_base = ctx->timebase;
- // doing this breaks mpeg2ts in ffmpeg
- // which doesn't properly force the time base to be 90000
- // furthermore, ffmpeg.c doesn't do this either and works
-
- stream->codec->time_base = ctx->timebase;
-
- ctx->voptions = NULL;
-
- if (ctx->options->vopts)
- for (p = ctx->options->vopts; *p; ++p)
- if (!set_to_avdictionary(&ctx->voptions, NULL, *p))
- mp_msg(MSGT_ENCODE, MSGL_WARN,
- "vo-lavc: could not set option %s\n", *p);
-
- de = av_dict_get(ctx->voptions, "global_quality", NULL, 0);
- if (de)
- set_to_avdictionary(&ctx->voptions, "flags", "+qscale");
-
- if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
- set_to_avdictionary(&ctx->voptions, "flags", "+global_header");
-
- encode_2pass_prepare(ctx, &ctx->voptions, stream,
- &ctx->twopass_bytebuffer_v,
- "vo-lavc");
- break;
-
- case AVMEDIA_TYPE_AUDIO:
- if (!ctx->ac) {
- encode_lavc_fail(ctx, "ao-lavc: encoder not found\n");
- return NULL;
- }
- avcodec_get_context_defaults3(stream->codec, ctx->ac);
-
- stream->codec->time_base = ctx->timebase;
-
- ctx->aoptions = NULL;
-
- if (ctx->options->aopts)
- for (p = ctx->options->aopts; *p; ++p)
- if (!set_to_avdictionary(&ctx->aoptions, NULL, *p))
- mp_msg(MSGT_ENCODE, MSGL_WARN,
- "ao-lavc: could not set option %s\n", *p);
-
- de = av_dict_get(ctx->aoptions, "global_quality", NULL, 0);
- if (de)
- set_to_avdictionary(&ctx->aoptions, "flags", "+qscale");
-
- if (ctx->avc->oformat->flags & AVFMT_GLOBALHEADER)
- set_to_avdictionary(&ctx->aoptions, "flags", "+global_header");
-
- encode_2pass_prepare(ctx, &ctx->aoptions, stream,
- &ctx->twopass_bytebuffer_a,
- "ao-lavc");
- break;
-
- default:
- encode_lavc_fail(ctx, "encode-lavc: requested invalid stream type\n");
- return NULL;
- }
-
- return stream;
-}
-
-AVCodec *encode_lavc_get_codec(struct encode_lavc_context *ctx,
- AVStream *stream)
-{
- CHECK_FAIL(ctx, NULL);
-
- switch (stream->codec->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- return ctx->vc;
- case AVMEDIA_TYPE_AUDIO:
- return ctx->ac;
- default:
- break;
- }
- return NULL;
-}
-
-int encode_lavc_open_codec(struct encode_lavc_context *ctx, AVStream *stream)
-{
- AVDictionaryEntry *de;
- int ret;
-
- CHECK_FAIL(ctx, -1);
-
- switch (stream->codec->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Opening video encoder: %s [%s]\n",
- ctx->vc->long_name, ctx->vc->name);
-
- if (ctx->vc->capabilities & CODEC_CAP_EXPERIMENTAL) {
- stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
- mp_msg(MSGT_ENCODE, MSGL_WARN, _(
- "\n\n"
- " ********************************************\n"
- " **** Experimental VIDEO codec selected! ****\n"
- " ********************************************\n\n"
- "This means the output file may be broken or bad.\n"
- "Possible reasons, problems, workarounds:\n"
- "- Codec implementation in ffmpeg/libav is not finished yet.\n"
- " Try updating ffmpeg or libav.\n"
- "- Bad picture quality, blocks, blurriness.\n"
- " Experiment with codec settings (--ovcopts) to maybe still get the\n"
- " desired quality output at the expense of bitrate.\n"
- "- Slow compression.\n"
- " Bear with it.\n"
- "- Crashes.\n"
- " Happens. Try varying options to work around.\n"
- "If none of this helps you, try another codec in place of %s.\n\n"),
- ctx->vc->name);
- }
-
- ret = avcodec_open2(stream->codec, ctx->vc, &ctx->voptions);
-
- // complain about all remaining options, then free the dict
- for (de = NULL; (de = av_dict_get(ctx->voptions, "", de,
- AV_DICT_IGNORE_SUFFIX));)
- mp_msg(MSGT_ENCODE, MSGL_WARN, "ovcopts: key '%s' not found.\n",
- de->key);
- av_dict_free(&ctx->voptions);
-
- break;
- case AVMEDIA_TYPE_AUDIO:
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Opening audio encoder: %s [%s]\n",
- ctx->ac->long_name, ctx->ac->name);
-
- if (ctx->ac->capabilities & CODEC_CAP_EXPERIMENTAL) {
- stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
- mp_msg(MSGT_ENCODE, MSGL_WARN, _(
- "\n\n"
- " ********************************************\n"
- " **** Experimental AUDIO codec selected! ****\n"
- " ********************************************\n\n"
- "This means the output file may be broken or bad.\n"
- "Possible reasons, problems, workarounds:\n"
- "- Codec implementation in ffmpeg/libav is not finished yet.\n"
- " Try updating ffmpeg or libav.\n"
- "- Bad sound quality, noise, clicking, whistles, choppiness.\n"
- " Experiment with codec settings (--oacopts) to maybe still get the\n"
- " desired quality output at the expense of bitrate.\n"
- "- Slow compression.\n"
- " Bear with it.\n"
- "- Crashes.\n"
- " Happens. Try varying options to work around.\n"
- "If none of this helps you, try another codec in place of %s.\n\n"),
- ctx->ac->name);
- }
- ret = avcodec_open2(stream->codec, ctx->ac, &ctx->aoptions);
-
- // complain about all remaining options, then free the dict
- for (de = NULL; (de = av_dict_get(ctx->aoptions, "", de,
- AV_DICT_IGNORE_SUFFIX));)
- mp_msg(MSGT_ENCODE, MSGL_WARN, "oacopts: key '%s' not found.\n",
- de->key);
- av_dict_free(&ctx->aoptions);
-
- break;
- default:
- ret = -1;
- break;
- }
-
- if (ret < 0)
- encode_lavc_fail(ctx,
- "unable to open encoder (see above for the cause)");
-
- return ret;
-}
-
-void encode_lavc_write_stats(struct encode_lavc_context *ctx, AVStream *stream)
-{
- CHECK_FAIL(ctx, );
-
- switch (stream->codec->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- if (ctx->twopass_bytebuffer_v)
- if (stream->codec->stats_out)
- stream_write_buffer(ctx->twopass_bytebuffer_v,
- stream->codec->stats_out,
- strlen(stream->codec->stats_out));
- break;
- case AVMEDIA_TYPE_AUDIO:
- if (ctx->twopass_bytebuffer_a)
- if (stream->codec->stats_out)
- stream_write_buffer(ctx->twopass_bytebuffer_a,
- stream->codec->stats_out,
- strlen(stream->codec->stats_out));
- break;
- default:
- break;
- }
-}
-
-int encode_lavc_write_frame(struct encode_lavc_context *ctx, AVPacket *packet)
-{
- int r;
-
- CHECK_FAIL(ctx, -1);
-
- if (ctx->header_written <= 0)
- return -1;
-
- mp_msg(
- MSGT_ENCODE, MSGL_DBG2,
- "encode-lavc: write frame: stream %d ptsi %d (%f) dtsi %d (%f) size %d\n",
- (int)packet->stream_index,
- (int)packet->pts,
- packet->pts
- * (double)ctx->avc->streams[packet->stream_index]->time_base.num
- / (double)ctx->avc->streams[packet->stream_index]->time_base.den,
- (int)packet->dts,
- packet->dts
- * (double)ctx->avc->streams[packet->stream_index]->time_base.num
- / (double)ctx->avc->streams[packet->stream_index]->time_base.den,
- (int)packet->size);
-
- switch (ctx->avc->streams[packet->stream_index]->codec->codec_type) {
- case AVMEDIA_TYPE_VIDEO:
- ctx->vbytes += packet->size;
- ++ctx->frames;
- break;
- case AVMEDIA_TYPE_AUDIO:
- ctx->abytes += packet->size;
- ctx->audioseconds += packet->duration
- * (double)ctx->avc->streams[packet->stream_index]->time_base.num
- / (double)ctx->avc->streams[packet->stream_index]->time_base.den;
- break;
- default:
- break;
- }
-
- r = av_interleaved_write_frame(ctx->avc, packet);
-
- return r;
-}
-
-int encode_lavc_supports_pixfmt(struct encode_lavc_context *ctx,
- enum PixelFormat pix_fmt)
-{
- CHECK_FAIL(ctx, 0);
-
- if (!ctx->vc)
- return 0;
- if (pix_fmt == PIX_FMT_NONE)
- return 0;
-
- if (!ctx->vc->pix_fmts)
- return VFCAP_CSP_SUPPORTED;
- else {
- const enum PixelFormat *p;
- for (p = ctx->vc->pix_fmts; *p >= 0; ++p) {
- if (pix_fmt == *p)
- return VFCAP_CSP_SUPPORTED;
- }
- }
- return 0;
-}
-
-void encode_lavc_discontinuity(struct encode_lavc_context *ctx)
-{
- if (!ctx)
- return;
-
- CHECK_FAIL(ctx, );
-
- ctx->audio_pts_offset = MP_NOPTS_VALUE;
- ctx->last_video_in_pts = MP_NOPTS_VALUE;
- ctx->discontinuity_pts_offset = MP_NOPTS_VALUE;
-}
-
-static void encode_lavc_printoptions(void *obj, const char *indent,
- const char *subindent, const char *unit,
- int filter_and, int filter_eq)
-{
- const AVOption *opt = NULL;
- char optbuf[32];
- while ((opt = av_opt_next(obj, opt))) {
- // if flags are 0, it simply hasn't been filled in yet and may be
- // potentially useful
- if (opt->flags)
- if ((opt->flags & filter_and) != filter_eq)
- continue;
- /* Don't print CONST's on level one.
- * Don't print anything but CONST's on level two.
- * Only print items from the requested unit.
- */
- if (!unit && opt->type == AV_OPT_TYPE_CONST)
- continue;
- else if (unit && opt->type != AV_OPT_TYPE_CONST)
- continue;
- else if (unit && opt->type == AV_OPT_TYPE_CONST
- && strcmp(unit, opt->unit))
- continue;
- else if (unit && opt->type == AV_OPT_TYPE_CONST)
- mp_msg(MSGT_ENCODE, MSGL_INFO, "%s", subindent);
- else
- mp_msg(MSGT_ENCODE, MSGL_INFO, "%s", indent);
-
- switch (opt->type) {
- case AV_OPT_TYPE_FLAGS:
- snprintf(optbuf, sizeof(optbuf), "%s=<flags>", opt->name);
- break;
- case AV_OPT_TYPE_INT:
- snprintf(optbuf, sizeof(optbuf), "%s=<int>", opt->name);
- break;
- case AV_OPT_TYPE_INT64:
- snprintf(optbuf, sizeof(optbuf), "%s=<int64>", opt->name);
- break;
- case AV_OPT_TYPE_DOUBLE:
- snprintf(optbuf, sizeof(optbuf), "%s=<double>", opt->name);
- break;
- case AV_OPT_TYPE_FLOAT:
- snprintf(optbuf, sizeof(optbuf), "%s=<float>", opt->name);
- break;
- case AV_OPT_TYPE_STRING:
- snprintf(optbuf, sizeof(optbuf), "%s=<string>", opt->name);
- break;
- case AV_OPT_TYPE_RATIONAL:
- snprintf(optbuf, sizeof(optbuf), "%s=<rational>", opt->name);
- break;
- case AV_OPT_TYPE_BINARY:
- snprintf(optbuf, sizeof(optbuf), "%s=<binary>", opt->name);
- break;
- case AV_OPT_TYPE_CONST:
- snprintf(optbuf, sizeof(optbuf), " [+-]%s", opt->name);
- break;
- default:
- snprintf(optbuf, sizeof(optbuf), "%s", opt->name);
- break;
- }
- optbuf[sizeof(optbuf) - 1] = 0;
- mp_msg(MSGT_ENCODE, MSGL_INFO, "%-32s ", optbuf);
- if (opt->help)
- mp_msg(MSGT_ENCODE, MSGL_INFO, " %s", opt->help);
- mp_msg(MSGT_ENCODE, MSGL_INFO, "\n");
- if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
- encode_lavc_printoptions(obj, indent, subindent, opt->unit,
- filter_and, filter_eq);
- }
-}
-
-bool encode_lavc_showhelp(struct MPOpts *opts)
-{
- bool help_output = false;
- if (av_codec_next(NULL) == NULL)
- mp_msg(MSGT_ENCODE, MSGL_ERR, "NO CODECS\n");
-#define CHECKS(str) ((str) && \
- strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
-#define CHECKV(strv) ((strv) && (strv)[0] && \
- strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
- if (CHECKS(opts->encode_output.format)) {
- AVOutputFormat *c = NULL;
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Available output formats:\n");
- while ((c = av_oformat_next(c)))
- mp_msg(MSGT_ENCODE, MSGL_INFO, " --of=%-13s %s\n", c->name,
- c->long_name ? c->long_name : "");
- av_free(c);
- }
- if (CHECKV(opts->encode_output.fopts)) {
- AVFormatContext *c = avformat_alloc_context();
- AVOutputFormat *format = NULL;
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "Available output format ctx->options:\n");
- encode_lavc_printoptions(c, " --ofopts=", " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM);
- av_free(c);
- while ((format = av_oformat_next(format))) {
- if (format->priv_class) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Additionally, for --of=%s:\n",
- format->name);
- encode_lavc_printoptions(&format->priv_class, " --ofopts=",
- " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM);
- }
- }
- }
- if (CHECKV(opts->encode_output.vopts)) {
- AVCodecContext *c = avcodec_alloc_context3(NULL);
- AVCodec *codec = NULL;
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "Available output video codec ctx->options:\n");
- encode_lavc_printoptions(
- c, " --ovcopts=", " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_VIDEO_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_VIDEO_PARAM);
- av_free(c);
- while ((codec = av_codec_next(codec))) {
- if (!av_codec_is_encoder(codec))
- continue;
- if (codec->type != AVMEDIA_TYPE_VIDEO)
- continue;
- if (opts->encode_output.vcodec && opts->encode_output.vcodec[0] &&
- strcmp(opts->encode_output.vcodec, codec->name) != 0)
- continue;
- if (codec->priv_class) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Additionally, for --ovc=%s:\n",
- codec->name);
- encode_lavc_printoptions(
- &codec->priv_class, " --ovcopts=",
- " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_VIDEO_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_VIDEO_PARAM);
- }
- }
- }
- if (CHECKV(opts->encode_output.aopts)) {
- AVCodecContext *c = avcodec_alloc_context3(NULL);
- AVCodec *codec = NULL;
- mp_msg(MSGT_ENCODE, MSGL_INFO,
- "Available output audio codec ctx->options:\n");
- encode_lavc_printoptions(
- c, " --oacopts=", " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_AUDIO_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_AUDIO_PARAM);
- av_free(c);
- while ((codec = av_codec_next(codec))) {
- if (!av_codec_is_encoder(codec))
- continue;
- if (codec->type != AVMEDIA_TYPE_AUDIO)
- continue;
- if (opts->encode_output.acodec && opts->encode_output.acodec[0] &&
- strcmp(opts->encode_output.acodec, codec->name) != 0)
- continue;
- if (codec->priv_class) {
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Additionally, for --oac=%s:\n",
- codec->name);
- encode_lavc_printoptions(
- &codec->priv_class, " --oacopts=",
- " ", NULL,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_AUDIO_PARAM,
- AV_OPT_FLAG_ENCODING_PARAM |
- AV_OPT_FLAG_AUDIO_PARAM);
- }
- }
- }
- if (CHECKS(opts->encode_output.vcodec)) {
- AVCodec *c = NULL;
- mp_msg(MSGT_ENCODE, MSGL_INFO, "Available output video codecs:\n");
- while ((c