/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 |