Coverage Report

Created: 2026-08-14 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mpv/common/encode_lavc.c
Line
Count
Source
1
/*
2
 * muxing using libavformat
3
 *
4
 * Copyright (C) 2010 Nicolas George <george@nsup.org>
5
 * Copyright (C) 2011-2012 Rudolf Polzer <divVerent@xonotic.org>
6
 *
7
 * This file is part of mpv.
8
 *
9
 * mpv is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * mpv is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with mpv.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include <libavutil/avutil.h>
24
#include <libavutil/timestamp.h>
25
26
#include "encode_lavc.h"
27
#include "common/av_common.h"
28
#include "common/global.h"
29
#include "common/msg.h"
30
#include "common/msg_control.h"
31
#include "options/m_config.h"
32
#include "options/m_option.h"
33
#include "options/options.h"
34
#include "options/path.h"
35
#include "osdep/timer.h"
36
#include "video/out/vo.h"
37
#include "mpv_talloc.h"
38
#include "stream/stream.h"
39
40
struct encode_priv {
41
    struct mp_log *log;
42
43
    // --- All fields are protected by encode_lavc_context.lock
44
45
    bool failed;
46
47
    struct mp_tags *metadata;
48
49
    AVFormatContext *muxer;
50
51
    bool header_written; // muxer was initialized
52
53
    struct mux_stream **streams;
54
    int num_streams;
55
56
    // Statistics
57
    double t0;
58
59
    long long abytes;
60
    long long vbytes;
61
62
    unsigned int frames;
63
    double audioseconds;
64
};
65
66
struct mux_stream {
67
    int index;                      // index of this into p->streams[]
68
    char name[80];
69
    struct encode_lavc_context *ctx;
70
    enum AVMediaType codec_type;
71
    AVRational encoder_timebase;    // packet timestamps from encoder
72
    AVStream *st;
73
};
74
75
#define OPT_BASE_STRUCT struct encode_opts
76
const struct m_sub_options encode_config = {
77
    .opts = (const m_option_t[]) {
78
        {"o", OPT_STRING(file), .flags = M_OPT_NOCFG | M_OPT_PRE_PARSE | M_OPT_FILE},
79
        {"of", OPT_STRING(format)},
80
        {"ofopts", OPT_KEYVALUELIST(fopts), .flags = M_OPT_HAVE_HELP},
81
        {"ovc", OPT_STRING(vcodec)},
82
        {"ovcopts", OPT_KEYVALUELIST(vopts), .flags = M_OPT_HAVE_HELP},
83
        {"oac", OPT_STRING(acodec)},
84
        {"oacopts", OPT_KEYVALUELIST(aopts), .flags = M_OPT_HAVE_HELP},
85
        {"orawts", OPT_BOOL(rawts)},
86
        {"ocopy-metadata", OPT_BOOL(copy_metadata)},
87
        {"oset-metadata", OPT_KEYVALUELIST(set_metadata)},
88
        {"oremove-metadata", OPT_STRINGLIST(remove_metadata)},
89
        {0}
90
    },
91
    .size = sizeof(struct encode_opts),
92
    .defaults = &(const struct encode_opts){
93
        .copy_metadata = true,
94
    },
95
};
96
97
struct encode_lavc_context *encode_lavc_init(struct mpv_global *global)
98
42
{
99
42
    struct encode_lavc_context *ctx = talloc_ptrtype(NULL, ctx);
100
42
    *ctx = (struct encode_lavc_context){
101
42
        .global = global,
102
42
        .options = mp_get_config_group(ctx, global, &encode_config),
103
42
        .priv = talloc_zero(ctx, struct encode_priv),
104
42
        .log = mp_log_new(ctx, global->log, "encode"),
105
42
    };
106
42
    mp_mutex_init(&ctx->lock);
107
108
42
    struct encode_priv *p = ctx->priv;
109
42
    p->log = ctx->log;
110
111
42
    const char *filename = ctx->options->file;
112
113
    // STUPID STUPID STUPID STUPID avio
114
    // does not support "-" as file name to mean stdin/stdout
115
    // ffmpeg.c works around this too, the same way
116
42
    if (!strcmp(filename, "-"))
117
2
        filename = "pipe:1";
118
119
42
    encode_lavc_discontinuity(ctx);
120
121
42
    p->muxer = avformat_alloc_context();
122
42
    MP_HANDLE_OOM(p->muxer);
123
124
42
    if (ctx->options->format && ctx->options->format[0]) {
125
1
        ctx->oformat = av_guess_format(ctx->options->format, filename, NULL);
126
41
    } else {
127
41
        ctx->oformat = av_guess_format(NULL, filename, NULL);
128
41
    }
129
130
42
    if (!ctx->oformat) {
131
41
        MP_FATAL(ctx, "format not found\n");
132
41
        goto fail;
133
41
    }
134
135
1
    p->muxer->oformat = ctx->oformat;
136
137
1
    char *path = mp_get_user_path(NULL, global, filename);
138
1
    p->muxer->url = av_strdup(path);
139
1
    talloc_free(path);
140
1
    MP_HANDLE_OOM(p->muxer->url);
141
142
1
    return ctx;
143
144
41
fail:
145
41
    p->failed = true;
146
41
    encode_lavc_free(ctx);
147
41
    return NULL;
148
1
}
149
150
void encode_lavc_set_metadata(struct encode_lavc_context *ctx,
151
                              struct mp_tags *metadata)
152
0
{
153
0
    struct encode_priv *p = ctx->priv;
154
155
0
    mp_mutex_lock(&ctx->lock);
156
157
0
    if (ctx->options->copy_metadata) {
158
0
        p->metadata = mp_tags_dup(ctx, metadata);
159
0
    } else {
160
0
        p->metadata = talloc_zero(ctx, struct mp_tags);
161
0
    }
162
163
0
    if (ctx->options->set_metadata) {
164
0
        char **kv = ctx->options->set_metadata;
165
        // Set all user-provided metadata tags
166
0
        for (int n = 0; kv[n * 2]; n++) {
167
0
            MP_VERBOSE(ctx, "setting metadata value '%s' for key '%s'\n",
168
0
                       kv[n*2 + 0], kv[n*2 +1]);
169
0
            mp_tags_set_str(p->metadata, kv[n*2 + 0], kv[n*2 +1]);
170
0
        }
171
0
    }
172
173
0
    if (ctx->options->remove_metadata) {
174
0
        char **k = ctx->options->remove_metadata;
175
        // Remove all user-provided metadata tags
176
0
        for (int n = 0; k[n]; n++) {
177
0
            MP_VERBOSE(ctx, "removing metadata key '%s'\n", k[n]);
178
0
            mp_tags_remove_str(p->metadata, k[n]);
179
0
        }
180
0
    }
181
182
0
    mp_mutex_unlock(&ctx->lock);
183
0
}
184
185
bool encode_lavc_free(struct encode_lavc_context *ctx)
186
143k
{
187
143k
    bool res = true;
188
143k
    if (!ctx)
189
143k
        return res;
190
191
42
    struct encode_priv *p = ctx->priv;
192
193
42
    if (!p->failed && !p->header_written) {
194
1
        MP_FATAL(p, "no data written to target file\n");
195
1
        p->failed = true;
196
1
    }
197
198
42
    if (!p->failed && p->header_written) {
199
0
        if (av_write_trailer(p->muxer) < 0)
200
0
            MP_ERR(p, "error writing trailer\n");
201
202
0
        MP_INFO(p, "video: encoded %lld bytes\n", p->vbytes);
203
0
        MP_INFO(p, "audio: encoded %lld bytes\n", p->abytes);
204
205
0
        MP_INFO(p, "muxing overhead %lld bytes\n",
206
0
                (long long)(avio_size(p->muxer->pb) - p->vbytes - p->abytes));
207
0
    }
208
209
42
    if (avio_closep(&p->muxer->pb) < 0 && !p->failed) {
210
0
        MP_ERR(p, "Closing file failed\n");
211
0
        p->failed = true;
212
0
    }
213
214
42
    avformat_free_context(p->muxer);
215
216
42
    res = !p->failed;
217
218
42
    mp_mutex_destroy(&ctx->lock);
219
42
    talloc_free(ctx);
220
221
42
    return res;
222
143k
}
223
224
// called locked
225
static void maybe_init_muxer(struct encode_lavc_context *ctx)
226
0
{
227
0
    struct encode_priv *p = ctx->priv;
228
229
0
    if (p->header_written || p->failed)
230
0
        return;
231
232
    // Check if all streams were initialized yet. We need data to know the
233
    // AVStream parameters, so we wait for data from _all_ streams before
234
    // starting.
235
0
    for (int n = 0; n < p->num_streams; n++) {
236
0
        if (!p->streams[n]->st)
237
0
            return;
238
0
    }
239
240
0
    if (!(p->muxer->oformat->flags & AVFMT_NOFILE)) {
241
0
        MP_INFO(p, "Opening output file: %s\n", p->muxer->url);
242
243
0
        if (avio_open(&p->muxer->pb, p->muxer->url, AVIO_FLAG_WRITE) < 0) {
244
0
            MP_FATAL(p, "could not open '%s'\n", p->muxer->url);
245
0
            goto failed;
246
0
        }
247
0
    }
248
249
0
    p->t0 = mp_time_sec();
250
251
0
    MP_INFO(p, "Opening muxer: %s [%s]\n",
252
0
            p->muxer->oformat->long_name, p->muxer->oformat->name);
253
254
0
    if (p->metadata) {
255
0
        for (int i = 0; i < p->metadata->num_keys; i++) {
256
0
            av_dict_set(&p->muxer->metadata,
257
0
                p->metadata->keys[i], p->metadata->values[i], 0);
258
0
        }
259
0
    }
260
261
0
    AVDictionary *opts = NULL;
262
0
    mp_set_avdict(&opts, ctx->options->fopts);
263
264
0
    if (avformat_write_header(p->muxer, &opts) < 0) {
265
0
        MP_FATAL(p, "Failed to initialize muxer.\n");
266
0
        p->failed = true;
267
0
    } else {
268
0
        mp_avdict_print_unset(p->log, MSGL_WARN, opts);
269
0
    }
270
271
0
    av_dict_free(&opts);
272
273
0
    if (p->failed)
274
0
        goto failed;
275
276
0
    p->header_written = true;
277
278
0
    return;
279
280
0
failed:
281
0
    p->failed = true;
282
0
}
283
284
// called locked
285
static struct mux_stream *find_mux_stream(struct encode_lavc_context *ctx,
286
                                          enum AVMediaType codec_type)
287
0
{
288
0
    struct encode_priv *p = ctx->priv;
289
290
0
    for (int n = 0; n < p->num_streams; n++) {
291
0
        struct mux_stream *s = p->streams[n];
292
0
        if (s->codec_type == codec_type)
293
0
            return s;
294
0
    }
295
296
0
    return NULL;
297
0
}
298
299
void encode_lavc_expect_stream(struct encode_lavc_context *ctx,
300
                               enum stream_type type)
301
0
{
302
0
    struct encode_priv *p = ctx->priv;
303
304
0
    mp_mutex_lock(&ctx->lock);
305
306
0
    enum AVMediaType codec_type = mp_to_av_stream_type(type);
307
308
    // These calls are idempotent.
309
0
    if (find_mux_stream(ctx, codec_type))
310
0
        goto done;
311
312
0
    if (p->header_written) {
313
0
        MP_ERR(p, "Cannot add a stream during encoding.\n");
314
0
        p->failed = true;
315
0
        goto done;
316
0
    }
317
318
0
    struct mux_stream *dst = talloc_ptrtype(p, dst);
319
0
    *dst = (struct mux_stream){
320
0
        .index = p->num_streams,
321
0
        .ctx = ctx,
322
0
        .codec_type = mp_to_av_stream_type(type),
323
0
    };
324
0
    snprintf(dst->name, sizeof(dst->name), "%s", stream_type_name(type));
325
0
    MP_TARRAY_APPEND(p, p->streams, p->num_streams, dst);
326
327
0
done:
328
0
    mp_mutex_unlock(&ctx->lock);
329
0
}
330
331
// Signal that you are ready to encode (you provide the codec params etc. too).
332
// This returns a muxing handle which you can use to add encodec packets.
333
// Can be called only once per stream. info is copied by callee as needed.
334
static void encode_lavc_add_stream(struct encoder_context *enc,
335
                                   struct encode_lavc_context *ctx,
336
                                   struct encoder_stream_info *info)
337
0
{
338
0
    struct encode_priv *p = ctx->priv;
339
340
0
    mp_mutex_lock(&ctx->lock);
341
342
0
    struct mux_stream *dst = find_mux_stream(ctx, info->codecpar->codec_type);
343
0
    if (!dst) {
344
0
        MP_ERR(p, "Cannot add a stream at runtime.\n");
345
0
        p->failed = true;
346
0
        goto done;
347
0
    }
348
0
    if (dst->st) {
349
        // Possibly via --gapless-audio, or explicitly recreating AO/VO.
350
0
        MP_ERR(p, "Encoder was reinitialized; this is not allowed.\n");
351
0
        p->failed = true;
352
0
        dst = NULL;
353
0
        goto done;
354
0
    }
355
356
0
    dst->st = avformat_new_stream(p->muxer, NULL);
357
0
    MP_HANDLE_OOM(dst->st);
358
359
0
    dst->encoder_timebase = info->timebase;
360
0
    dst->st->time_base = info->timebase; // lavf will change this on muxer init
361
    // Some muxers (e.g. Matroska one) expect the sample_aspect_ratio to be
362
    // set on the AVStream.
363
0
    if (info->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
364
0
        dst->st->sample_aspect_ratio = info->codecpar->sample_aspect_ratio;
365
366
0
    if (avcodec_parameters_copy(dst->st->codecpar, info->codecpar) < 0)
367
0
        MP_HANDLE_OOM(NULL);
368
369
0
    enc->mux_stream = dst;
370
371
0
    maybe_init_muxer(ctx);
372
373
0
done:
374
0
    mp_mutex_unlock(&ctx->lock);
375
0
}
376
377
// Write a packet. This will take over ownership of `pkt`
378
static void encode_lavc_add_packet(struct mux_stream *dst, AVPacket *pkt)
379
0
{
380
0
    struct encode_lavc_context *ctx = dst->ctx;
381
0
    struct encode_priv *p = ctx->priv;
382
383
0
    mp_assert(dst->st);
384
385
0
    mp_mutex_lock(&ctx->lock);
386
387
0
    if (p->failed)
388
0
        goto done;
389
390
0
    if (!p->header_written) {
391
0
        MP_ERR(p, "Encoder trying to write packet before muxer was initialized.\n");
392
0
        p->failed = true;
393
0
        goto done;
394
0
    }
395
396
0
    pkt->stream_index = dst->st->index;
397
0
    mp_assert(dst->st == p->muxer->streams[pkt->stream_index]);
398
399
0
    av_packet_rescale_ts(pkt, dst->encoder_timebase, dst->st->time_base);
400
401
0
    switch (dst->st->codecpar->codec_type) {
402
0
    case AVMEDIA_TYPE_VIDEO:
403
0
        p->vbytes += pkt->size;
404
0
        p->frames += 1;
405
0
        break;
406
0
    case AVMEDIA_TYPE_AUDIO:
407
0
        p->abytes += pkt->size;
408
0
        p->audioseconds += pkt->duration
409
0
            * (double)dst->st->time_base.num
410
0
            / (double)dst->st->time_base.den;
411
0
        break;
412
0
    }
413
414
0
    if (av_interleaved_write_frame(p->muxer, pkt) < 0) {
415
0
        MP_ERR(p, "Writing packet failed.\n");
416
0
        p->failed = true;
417
0
    }
418
419
0
    pkt = NULL;
420
421
0
done:
422
0
    mp_mutex_unlock(&ctx->lock);
423
0
    if (pkt)
424
0
        av_packet_unref(pkt);
425
0
}
426
427
AVRational encoder_get_mux_timebase_unlocked(struct encoder_context *p)
428
0
{
429
0
    return p->mux_stream->st->time_base;
430
0
}
431
432
void encode_lavc_discontinuity(struct encode_lavc_context *ctx)
433
529k
{
434
529k
    if (!ctx)
435
529k
        return;
436
437
42
    mp_mutex_lock(&ctx->lock);
438
42
    ctx->discontinuity_pts_offset = MP_NOPTS_VALUE;
439
42
    mp_mutex_unlock(&ctx->lock);
440
42
}
441
442
static void encode_lavc_printoptions(struct mp_log *log, const void *obj,
443
                                     const char *indent, const char *subindent,
444
                                     const char *unit, int filter_and,
445
                                     int filter_eq)
446
13
{
447
13
    const AVOption *opt = NULL;
448
13
    char optbuf[32];
449
4.65k
    while ((opt = av_opt_next(obj, opt))) {
450
        // if flags are 0, it simply hasn't been filled in yet and may be
451
        // potentially useful
452
4.64k
        if (opt->flags)
453
4.38k
            if ((opt->flags & filter_and) != filter_eq)
454
3.66k
                continue;
455
        /* Don't print CONST's on level one.
456
         * Don't print anything but CONST's on level two.
457
         * Only print items from the requested unit.
458
         */
459
975
        if (!unit && opt->type == AV_OPT_TYPE_CONST) {
460
34
            continue;
461
941
        } else if (unit && opt->type != AV_OPT_TYPE_CONST) {
462
492
            continue;
463
492
        } else if (unit && opt->type == AV_OPT_TYPE_CONST
464
408
                 && strcmp(unit, opt->unit))
465
374
        {
466
374
            continue;
467
374
        } else if (unit && opt->type == AV_OPT_TYPE_CONST) {
468
34
            mp_info(log, "%s", subindent);
469
41
        } else {
470
41
            mp_info(log, "%s", indent);
471
41
        }
472
473
75
        switch (opt->type) {
474
6
        case AV_OPT_TYPE_FLAGS:
475
6
            snprintf(optbuf, sizeof(optbuf), "%s=<flags>", opt->name);
476
6
            break;
477
22
        case AV_OPT_TYPE_INT:
478
22
            snprintf(optbuf, sizeof(optbuf), "%s=<int>", opt->name);
479
22
            break;
480
7
        case AV_OPT_TYPE_INT64:
481
7
            snprintf(optbuf, sizeof(optbuf), "%s=<int64>", opt->name);
482
7
            break;
483
0
        case AV_OPT_TYPE_DOUBLE:
484
0
            snprintf(optbuf, sizeof(optbuf), "%s=<double>", opt->name);
485
0
            break;
486
0
        case AV_OPT_TYPE_FLOAT:
487
0
            snprintf(optbuf, sizeof(optbuf), "%s=<float>", opt->name);
488
0
            break;
489
1
        case AV_OPT_TYPE_STRING:
490
1
            snprintf(optbuf, sizeof(optbuf), "%s=<string>", opt->name);
491
1
            break;
492
2
        case AV_OPT_TYPE_RATIONAL:
493
2
            snprintf(optbuf, sizeof(optbuf), "%s=<rational>", opt->name);
494
2
            break;
495
0
        case AV_OPT_TYPE_BINARY:
496
0
            snprintf(optbuf, sizeof(optbuf), "%s=<binary>", opt->name);
497
0
            break;
498
34
        case AV_OPT_TYPE_CONST:
499
34
            snprintf(optbuf, sizeof(optbuf), "  [+-]%s", opt->name);
500
34
            break;
501
3
        default:
502
3
            snprintf(optbuf, sizeof(optbuf), "%s", opt->name);
503
3
            break;
504
75
        }
505
75
        optbuf[sizeof(optbuf) - 1] = 0;
506
75
        mp_info(log, "%-32s ", optbuf);
507
75
        if (opt->help)
508
54
            mp_info(log, " %s", opt->help);
509
75
        mp_info(log, "\n");
510
75
        if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
511
12
            encode_lavc_printoptions(log, obj, indent, subindent, opt->unit,
512
12
                                     filter_and, filter_eq);
513
75
    }
514
13
}
515
516
bool encode_lavc_showhelp(struct mp_log *log, struct encode_opts *opts)
517
130k
{
518
130k
    bool help_output = false;
519
392k
#define CHECKS(str) ((str) && \
520
392k
                     strcmp((str), "help") == 0 ? (help_output |= 1) : 0)
521
392k
#define CHECKV(strv) ((strv) && (strv)[0] && \
522
392k
                      strcmp((strv)[0], "help") == 0 ? (help_output |= 1) : 0)
523
130k
    if (CHECKS(opts->format)) {
524
0
        const AVOutputFormat *c = NULL;
525
0
        void *iter = NULL;
526
0
        mp_info(log, "Available output formats:\n");
527
0
        while ((c = av_muxer_iterate(&iter))) {
528
0
            mp_info(log, "  --of=%-13s %s\n", c->name,
529
0
                   c->long_name ? c->long_name : "");
530
0
        }
531
0
    }
532
130k
    if (CHECKV(opts->fopts)) {
533
0
        AVFormatContext *c = avformat_alloc_context();
534
0
        const AVOutputFormat *format = NULL;
535
0
        mp_info(log, "Available output format ctx->options:\n");
536
0
        encode_lavc_printoptions(log, c, "  --ofopts=", "           ", NULL,
537
0
                                 AV_OPT_FLAG_ENCODING_PARAM,
538
0
                                 AV_OPT_FLAG_ENCODING_PARAM);
539
0
        avformat_free_context(c);
540
0
        void *iter = NULL;
541
0
        while ((format = av_muxer_iterate(&iter))) {
542
0
            if (format->priv_class) {
543
0
                mp_info(log, "Additionally, for --of=%s:\n",
544
0
                       format->name);
545
0
                encode_lavc_printoptions(log, &format->priv_class, "  --ofopts=",
546
0
                                         "           ", NULL,
547
0
                                         AV_OPT_FLAG_ENCODING_PARAM,
548
0
                                         AV_OPT_FLAG_ENCODING_PARAM);
549
0
            }
550
0
        }
551
0
    }
552
130k
    if (CHECKV(opts->vopts)) {
553
0
        AVCodecContext *c = avcodec_alloc_context3(NULL);
554
0
        const AVCodec *codec = NULL;
555
0
        mp_info(log, "Available output video codec ctx->options:\n");
556
0
        encode_lavc_printoptions(log,
557
0
            c, "  --ovcopts=", "            ", NULL,
558
0
            AV_OPT_FLAG_ENCODING_PARAM |
559
0
            AV_OPT_FLAG_VIDEO_PARAM,
560
0
            AV_OPT_FLAG_ENCODING_PARAM |
561
0
            AV_OPT_FLAG_VIDEO_PARAM);
562
0
        av_free(c);
563
0
        void *iter = NULL;
564
0
        while ((codec = av_codec_iterate(&iter))) {
565
0
            if (!av_codec_is_encoder(codec))
566
0
                continue;
567
0
            if (codec->type != AVMEDIA_TYPE_VIDEO)
568
0
                continue;
569
0
            if (opts->vcodec && opts->vcodec[0] &&
570
0
                strcmp(opts->vcodec, codec->name) != 0)
571
0
                continue;
572
0
            if (codec->priv_class) {
573
0
                mp_info(log, "Additionally, for --ovc=%s:\n",
574
0
                       codec->name);
575
0
                encode_lavc_printoptions(log,
576
0
                    &codec->priv_class, "  --ovcopts=",
577
0
                    "            ", NULL,
578
0
                    AV_OPT_FLAG_ENCODING_PARAM |
579
0
                    AV_OPT_FLAG_VIDEO_PARAM,
580
0
                    AV_OPT_FLAG_ENCODING_PARAM |
581
0
                    AV_OPT_FLAG_VIDEO_PARAM);
582
0
            }
583
0
        }
584
0
    }
585
130k
    if (CHECKV(opts->aopts)) {
586
1
        AVCodecContext *c = avcodec_alloc_context3(NULL);
587
1
        const AVCodec *codec = NULL;
588
1
        mp_info(log, "Available output audio codec ctx->options:\n");
589
1
        encode_lavc_printoptions(log,
590
1
            c, "  --oacopts=", "            ", NULL,
591
1
            AV_OPT_FLAG_ENCODING_PARAM |
592
1
            AV_OPT_FLAG_AUDIO_PARAM,
593
1
            AV_OPT_FLAG_ENCODING_PARAM |
594
1
            AV_OPT_FLAG_AUDIO_PARAM);
595
1
        av_free(c);
596
1
        void *iter = NULL;
597
497
        while ((codec = av_codec_iterate(&iter))) {
598
496
            if (!av_codec_is_encoder(codec))
599
496
                continue;
600
0
            if (codec->type != AVMEDIA_TYPE_AUDIO)
601
0
                continue;
602
0
            if (opts->acodec && opts->acodec[0] &&
603
0
                strcmp(opts->acodec, codec->name) != 0)
604
0
                continue;
605
0
            if (codec->priv_class) {
606
0
                mp_info(log, "Additionally, for --oac=%s:\n",
607
0
                       codec->name);
608
0
                encode_lavc_printoptions(log,
609
0
                    &codec->priv_class, "  --oacopts=",
610
0
                    "           ", NULL,
611
0
                    AV_OPT_FLAG_ENCODING_PARAM |
612
0
                    AV_OPT_FLAG_AUDIO_PARAM,
613
0
                    AV_OPT_FLAG_ENCODING_PARAM |
614
0
                    AV_OPT_FLAG_AUDIO_PARAM);
615
0
            }
616
0
        }
617
1
    }
618
130k
    if (CHECKS(opts->vcodec)) {
619
0
        const AVCodec *c = NULL;
620
0
        void *iter = NULL;
621
0
        mp_info(log, "Available output video codecs:\n");
622
0
        while ((c = av_codec_iterate(&iter))) {
623
0
            if (!av_codec_is_encoder(c))
624
0
                continue;
625
0
            if (c->type != AVMEDIA_TYPE_VIDEO)
626
0
                continue;
627
0
            mp_info(log, "  --ovc=%-12s %s\n", c->name,
628
0
                   c->long_name ? c->long_name : "");
629
0
        }
630
0
    }
631
130k
    if (CHECKS(opts->acodec)) {
632
0
        const AVCodec *c = NULL;
633
0
        void *iter = NULL;
634
0
        mp_info(log, "Available output audio codecs:\n");
635
0
        while ((c = av_codec_iterate(&iter))) {
636
0
            if (!av_codec_is_encoder(c))
637
0
                continue;
638
0
            if (c->type != AVMEDIA_TYPE_AUDIO)
639
0
                continue;
640
0
            mp_info(log, "  --oac=%-12s %s\n", c->name,
641
0
                   c->long_name ? c->long_name : "");
642
0
        }
643
0
    }
644
130k
    return help_output;
645
130k
}
646
647
int encode_lavc_getstatus(struct encode_lavc_context *ctx,
648
                          char *buf, int bufsize,
649
                          float relative_position)
650
87
{
651
87
    if (!ctx)
652
87
        return -1;
653
654
0
    struct encode_priv *p = ctx->priv;
655
656
0
    double now = mp_time_sec();
657
0
    float minutes, megabytes, fps, x;
658
0
    float f = MPMAX(0.0001, relative_position);
659
660
0
    mp_mutex_lock(&ctx->lock);
661
662
0
    if (p->failed) {
663
0
        snprintf(buf, bufsize, "(failed)\n");
664
0
        goto done;
665
0
    }
666
667
0
    minutes = (now - p->t0) / 60.0 * (1 - f) / f;
668
0
    megabytes = p->muxer->pb ? (avio_size(p->muxer->pb) / 1048576.0 / f) : 0;
669
0
    fps = p->frames / (now - p->t0);
670
0
    x = p->audioseconds / (now - p->t0);
671
0
    if (p->frames) {
672
0
        snprintf(buf, bufsize, "{%.1fmin %.1ffps %.1fMB}",
673
0
                 minutes, fps, megabytes);
674
0
    } else if (p->audioseconds) {
675
0
        snprintf(buf, bufsize, "{%.1fmin %.2fx %.1fMB}",
676
0
                 minutes, x, megabytes);
677
0
    } else {
678
0
        snprintf(buf, bufsize, "{%.1fmin %.1fMB}",
679
0
                 minutes, megabytes);
680
0
    }
681
0
    buf[bufsize - 1] = 0;
682
683
0
done:
684
0
    mp_mutex_unlock(&ctx->lock);
685
0
    return 0;
686
0
}
687
688
bool encode_lavc_didfail(struct encode_lavc_context *ctx)
689
1.52M
{
690
1.52M
    if (!ctx)
691
1.52M
        return false;
692
0
    mp_mutex_lock(&ctx->lock);
693
0
    bool fail = ctx->priv->failed;
694
0
    mp_mutex_unlock(&ctx->lock);
695
0
    return fail;
696
1.52M
}
697
698
static void encoder_destroy(void *ptr)
699
0
{
700
0
    struct encoder_context *p = ptr;
701
702
0
    av_packet_free(&p->pkt);
703
0
    avcodec_parameters_free(&p->info.codecpar);
704
0
    avcodec_free_context(&p->encoder);
705
0
    free_stream(p->twopass_bytebuffer);
706
0
}
707
708
static const AVCodec *find_codec_for(struct encode_lavc_context *ctx,
709
                               enum stream_type type, bool *used_auto)
710
0
{
711
0
    char *codec_name = type == STREAM_VIDEO
712
0
        ? ctx->options->vcodec
713
0
        : ctx->options->acodec;
714
0
    enum AVMediaType codec_type = mp_to_av_stream_type(type);
715
0
    const char *tname = stream_type_name(type);
716
717
0
    *used_auto = !(codec_name && codec_name[0]);
718
719
0
    const AVCodec *codec;
720
0
    if (*used_auto) {
721
0
        codec = avcodec_find_encoder(av_guess_codec(ctx->oformat, NULL,
722
0
                                     ctx->options->file, NULL,
723
0
                                     codec_type));
724
0
    } else {
725
0
        codec = avcodec_find_encoder_by_name(codec_name);
726
0
        if (!codec)
727
0
            MP_FATAL(ctx, "codec '%s' not found.\n", codec_name);
728
0
    }
729
730
0
    if (codec && codec->type != codec_type) {
731
0
        MP_FATAL(ctx, "codec for %s has wrong media type\n", tname);
732
0
        codec = NULL;
733
0
    }
734
735
0
    return codec;
736
0
}
737
738
// Return whether the stream type is "supposed" to work.
739
bool encode_lavc_stream_type_ok(struct encode_lavc_context *ctx,
740
                                enum stream_type type)
741
0
{
742
    // If a codec was forced, let it proceed to actual encoding, and then error
743
    // if it doesn't work. (Worried that av_guess_codec() may return NULL for
744
    // some formats where a specific codec works anyway.)
745
0
    bool auto_codec;
746
0
    return !!find_codec_for(ctx, type, &auto_codec) || !auto_codec;
747
0
}
748
749
struct encoder_context *encoder_context_alloc(struct encode_lavc_context *ctx,
750
                                              enum stream_type type,
751
                                              struct mp_log *log)
752
0
{
753
0
    if (!ctx) {
754
0
        mp_err(log, "the option --o (output file) must be specified\n");
755
0
        return NULL;
756
0
    }
757
758
0
    struct encoder_context *p = talloc_ptrtype(NULL, p);
759
0
    talloc_set_destructor(p, encoder_destroy);
760
0
    *p = (struct encoder_context){
761
0
        .global = ctx->global,
762
0
        .options = ctx->options,
763
0
        .oformat = ctx->oformat,
764
0
        .type = type,
765
0
        .log = log,
766
0
        .encode_lavc_ctx = ctx,
767
0
    };
768
769
0
    bool auto_codec;
770
0
    const AVCodec *codec = find_codec_for(ctx, type, &auto_codec);
771
0
    const char *tname = stream_type_name(type);
772
773
0
    if (!codec) {
774
0
        if (auto_codec)
775
0
            MP_FATAL(p, "codec for %s not found\n", tname);
776
0
        goto fail;
777
0
    }
778
779
0
    p->encoder = avcodec_alloc_context3(codec);
780
0
    MP_HANDLE_OOM(p->encoder);
781
782
0
    return p;
783
784
0
fail:
785
0
    talloc_free(p);
786
0
    return NULL;
787
0
}
788
789
static void encoder_2pass_prepare(struct encoder_context *p)
790
0
{
791
0
    char *filename = talloc_asprintf(NULL, "%s-%s-pass1.log",
792
0
                                     p->options->file,
793
0
                                     stream_type_name(p->type));
794
795
0
    if (p->encoder->flags & AV_CODEC_FLAG_PASS2) {
796
0
        MP_INFO(p, "Reading 2-pass log: %s\n", filename);
797
0
        struct stream *s = stream_create(filename,
798
0
                                         STREAM_ORIGIN_DIRECT | STREAM_READ,
799
0
                                         NULL, p->global);
800
0
        if (s) {
801
0
            struct bstr content = stream_read_complete(s, p, 1000000000);
802
0
            if (content.start) {
803
0
                p->encoder->stats_in = content.start;
804
0
            } else {
805
0
                MP_WARN(p, "could not read '%s', "
806
0
                        "disabling 2-pass encoding at pass 1\n", filename);
807
0
            }
808
0
            free_stream(s);
809
0
        } else {
810
0
            MP_WARN(p, "could not open '%s', "
811
0
                    "disabling 2-pass encoding at pass 2\n", filename);
812
0
            p->encoder->flags &= ~(unsigned)AV_CODEC_FLAG_PASS2;
813
0
        }
814
0
    }
815
816
0
    if (p->encoder->flags & AV_CODEC_FLAG_PASS1) {
817
0
        MP_INFO(p, "Writing to 2-pass log: %s\n", filename);
818
0
        p->twopass_bytebuffer = open_output_stream(filename, p->global);
819
0
        if (!p->twopass_bytebuffer) {
820
0
            MP_WARN(p, "could not open '%s', "
821
0
                    "disabling 2-pass encoding at pass 1\n", filename);
822
0
            p->encoder->flags &= ~(unsigned)AV_CODEC_FLAG_PASS1;
823
0
        }
824
0
    }
825
826
0
    talloc_free(filename);
827
0
}
828
829
bool encoder_init_codec_and_muxer(struct encoder_context *p)
830
0
{
831
0
    mp_assert(!avcodec_is_open(p->encoder));
832
833
0
    char **copts = p->type == STREAM_VIDEO
834
0
        ? p->options->vopts
835
0
        : p->options->aopts;
836
837
    // Set these now, so the code below can read back parsed settings from it.
838
0
    mp_set_avopts(p->log, p->encoder, copts);
839
840
0
    encoder_2pass_prepare(p);
841
842
0
    if (p->oformat->flags & AVFMT_GLOBALHEADER)
843
0
        p->encoder->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
844
845
0
    MP_INFO(p, "Opening encoder: %s [%s]\n",
846
0
            p->encoder->codec->long_name, p->encoder->codec->name);
847
848
0
    if (p->encoder->codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) {
849
0
        p->encoder->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
850
0
        MP_WARN(p, "\n\n"
851
0
                   "           ********************************************\n"
852
0
                   "           ****    Experimental codec selected!     ****\n"
853
0
                   "           ********************************************\n\n"
854
0
                   "This means the output file may be broken or bad.\n"
855
0
                   "Possible reasons, problems, workarounds:\n"
856
0
                   "- Codec implementation in ffmpeg is not finished yet.\n"
857
0
                   "     Try updating ffmpeg.\n"
858
0
                   "- Bad picture quality, blocks, blurriness.\n"
859
0
                   "     Experiment with codec settings to maybe still get the\n"
860
0
                   "     desired quality output at the expense of bitrate.\n"
861
0
                   "- Broken files.\n"
862
0
                   "     May not work at all, or break with other software.\n"
863
0
                   "- Slow compression.\n"
864
0
                   "     Bear with it.\n"
865
0
                   "- Crashes.\n"
866
0
                   "     Happens. Try varying options to work around.\n"
867
0
                   "If none of this helps you, try another codec in place of %s.\n\n",
868
0
                p->encoder->codec->name);
869
0
    }
870
871
0
    if (avcodec_open2(p->encoder, p->encoder->codec, NULL) < 0) {
872
0
        MP_FATAL(p, "Could not initialize encoder.\n");
873
0
        goto fail;
874
0
    }
875
876
0
    p->info.timebase = p->encoder->time_base; // (_not_ changed by enc. init)
877
0
    p->info.codecpar = avcodec_parameters_alloc();
878
0
    MP_HANDLE_OOM(p->info.codecpar);
879
0
    if (avcodec_parameters_from_context(p->info.codecpar, p->encoder) < 0)
880
0
        goto fail;
881
882
0
    p->pkt = av_packet_alloc();
883
0
    MP_HANDLE_OOM(p->pkt);
884
885
0
    encode_lavc_add_stream(p, p->encode_lavc_ctx, &p->info);
886
0
    if (!p->mux_stream)
887
0
        goto fail;
888
889
0
    return true;
890
891
0
fail:
892
0
    avcodec_free_context(&p->encoder);
893
0
    return false;
894
0
}
895
896
bool encoder_encode(struct encoder_context *p, AVFrame *frame)
897
0
{
898
0
    int status = avcodec_send_frame(p->encoder, frame);
899
0
    if (status < 0) {
900
0
        if (frame && status == AVERROR_EOF)
901
0
            MP_ERR(p, "new data after sending EOF to encoder\n");
902
0
        goto fail;
903
0
    }
904
905
0
    AVPacket *packet = p->pkt;
906
0
    for (;;) {
907
0
        status = avcodec_receive_packet(p->encoder, packet);
908
0
        if (status == AVERROR(EAGAIN))
909
0
            break;
910
0
        if (status < 0 && status != AVERROR_EOF)
911
0
            goto fail;
912
913
0
        if (p->twopass_bytebuffer && p->encoder->stats_out) {
914
0
            stream_write_buffer(p->twopass_bytebuffer, p->encoder->stats_out,
915
0
                                strlen(p->encoder->stats_out));
916
0
        }
917
918
0
        if (status == AVERROR_EOF)
919
0
            break;
920
921
0
        encode_lavc_add_packet(p->mux_stream, packet);
922
0
    }
923
924
0
    return true;
925
926
0
fail:
927
0
    MP_ERR(p, "error encoding at %s\n",
928
0
           frame ? av_ts2timestr(frame->pts, &p->encoder->time_base) : "EOF");
929
0
    return false;
930
0
}
931
932
void encoder_update_log(struct mpv_global *global)
933
5.00k
{
934
5.00k
    struct encode_opts *options = mp_get_config_group(NULL, global, &encode_config);
935
5.00k
    if (options->file && (!strcmp(options->file, "-") ||
936
48
                          !strcmp(options->file, "/dev/stdout") ||
937
48
                          !strcmp(options->file, "pipe:") ||
938
48
                          !strcmp(options->file, "pipe:1")))
939
0
    {
940
0
        mp_msg_force_stderr(global, true);
941
0
    }
942
5.00k
    talloc_free(options);
943
5.00k
}
944
945
// vim: ts=4 sw=4 et