diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/av_common.c | 92 | ||||
-rw-r--r-- | common/av_common.h | 9 | ||||
-rw-r--r-- | common/av_log.c | 62 | ||||
-rw-r--r-- | common/common.c | 59 | ||||
-rw-r--r-- | common/common.h | 62 | ||||
-rw-r--r-- | common/encode.h | 8 | ||||
-rw-r--r-- | common/encode_lavc.c | 99 | ||||
-rw-r--r-- | common/encode_lavc.h | 12 | ||||
-rw-r--r-- | common/meson.build | 11 | ||||
-rw-r--r-- | common/msg.c | 657 | ||||
-rw-r--r-- | common/msg_control.h | 4 | ||||
-rw-r--r-- | common/playlist.c | 118 | ||||
-rw-r--r-- | common/playlist.h | 31 | ||||
-rw-r--r-- | common/recorder.c | 108 | ||||
-rw-r--r-- | common/recorder.h | 5 | ||||
-rw-r--r-- | common/stats.c | 88 | ||||
-rw-r--r-- | common/stats.h | 2 | ||||
-rw-r--r-- | common/tags.c | 9 | ||||
-rw-r--r-- | common/tags.h | 2 | ||||
-rw-r--r-- | common/version.c | 6 | ||||
-rw-r--r-- | common/version.h.in | 9 |
21 files changed, 989 insertions, 464 deletions
diff --git a/common/av_common.c b/common/av_common.c index 01428ff2f4..1a23d766b3 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -30,6 +30,7 @@ #include "config.h" +#include "audio/chmap_avchannel.h" #include "common/common.h" #include "common/msg.h" #include "demux/packet.h" @@ -39,20 +40,6 @@ #include "av_common.h" #include "codecs.h" -int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size) -{ - if (size) { - av_free(avctx->extradata); - avctx->extradata_size = 0; - avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return -1; - avctx->extradata_size = size; - memcpy(avctx->extradata, ptr, size); - } - return 0; -} - enum AVMediaType mp_to_av_stream_type(int type) { switch (type) { @@ -63,7 +50,7 @@ enum AVMediaType mp_to_av_stream_type(int type) } } -AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) +AVCodecParameters *mp_codec_params_to_av(const struct mp_codec_params *c) { AVCodecParameters *avp = avcodec_parameters_alloc(); if (!avp) @@ -80,12 +67,23 @@ AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) avp->codec_id = mp_codec_to_av_codec_id(c->codec); avp->codec_tag = c->codec_tag; if (c->extradata_size) { - avp->extradata = - av_mallocz(c->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); + uint8_t *extradata = c->extradata; + int size = c->extradata_size; + + if (avp->codec_id == AV_CODEC_ID_FLAC) { + // ffmpeg expects FLAC extradata to be just the STREAMINFO, + // so grab only that (and assume it'll be the first block) + if (size >= 8 && !memcmp(c->extradata, "fLaC", 4)) { + extradata += 8; + size = MPMIN(34, size - 8); // FLAC_STREAMINFO_SIZE + } + } + + avp->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avp->extradata) goto error; - avp->extradata_size = c->extradata_size; - memcpy(avp->extradata, c->extradata, avp->extradata_size); + avp->extradata_size = size; + memcpy(avp->extradata, extradata, size); } avp->bits_per_coded_sample = c->bits_per_coded_sample; @@ -97,9 +95,14 @@ AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c) avp->sample_rate = c->samplerate; avp->bit_rate = c->bitrate; avp->block_align = c->block_align; + +#if !HAVE_AV_CHANNEL_LAYOUT avp->channels = c->channels.num; if (!mp_chmap_is_unknown(&c->channels)) avp->channel_layout = mp_chmap_to_lavc(&c->channels); +#else + mp_chmap_to_av_layout(&avp->ch_layout, &c->channels); +#endif return avp; error: @@ -108,7 +111,7 @@ error: } // Set avctx codec headers for decoding. Returns <0 on failure. -int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c) +int mp_set_avctx_codec_headers(AVCodecContext *avctx, const struct mp_codec_params *c) { enum AVMediaType codec_type = avctx->codec_type; enum AVCodecID codec_id = avctx->codec_id; @@ -128,7 +131,7 @@ int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c) // Pick a "good" timebase, which will be used to convert double timestamps // back to fractions for passing them through libavcodec. -AVRational mp_get_codec_timebase(struct mp_codec_params *c) +AVRational mp_get_codec_timebase(const struct mp_codec_params *c) { AVRational tb = {c->native_tb_num, c->native_tb_den}; if (tb.num < 1 || tb.den < 1) { @@ -140,12 +143,14 @@ AVRational mp_get_codec_timebase(struct mp_codec_params *c) // If the timebase is too coarse, raise its precision, or small adjustments // to timestamps done between decoder and demuxer could be lost. + int64_t den = tb.den; if (av_q2d(tb) > 0.001) { - AVRational r = av_div_q(tb, (AVRational){1, 1000}); - tb.den *= (r.num + r.den - 1) / r.den; + int64_t scaling_num = tb.num * INT64_C(1000); + int64_t scaling_den = tb.den; + den *= (scaling_num + scaling_den - 1) / scaling_den; } - av_reduce(&tb.num, &tb.den, tb.num, tb.den, INT_MAX); + av_reduce(&tb.num, &tb.den, tb.num, den, INT_MAX); if (tb.num < 1 || tb.den < 1) tb = AV_TIME_BASE_Q; @@ -179,7 +184,11 @@ double mp_pts_from_av(int64_t av_pts, AVRational *tb) // Set duration field only if tb is set. void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb) { - av_init_packet(dst); + dst->side_data = NULL; + dst->side_data_elems = 0; + dst->buf = NULL; + av_packet_unref(dst); + dst->data = mpkt ? mpkt->buffer : NULL; dst->size = mpkt ? mpkt->len : 0; /* Some codecs (ZeroCodec, some cases of PNG) may want keyframe info @@ -270,7 +279,7 @@ int mp_codec_to_av_codec_id(const char *codec) if (desc) id = desc->id; if (id == AV_CODEC_ID_NONE) { - AVCodec *avcodec = avcodec_find_decoder_by_name(codec); + const AVCodec *avcodec = avcodec_find_decoder_by_name(codec); if (avcodec) id = avcodec->id; } @@ -285,7 +294,7 @@ const char *mp_codec_from_av_codec_id(int codec_id) if (desc) name = desc->name; if (!name) { - AVCodec *avcodec = avcodec_find_decoder(codec_id); + const AVCodec *avcodec = avcodec_find_decoder(codec_id); if (avcodec) name = avcodec->name; } @@ -377,3 +386,32 @@ int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv) } return success; } + +/** + * Must be used to free an AVPacket that was used with mp_set_av_packet(). + * + * We have a particular pattern where we "borrow" buffers and set them + * into an AVPacket to pass data to ffmpeg without extra copies. + * This applies to buf and side_data, so this function clears them before + * freeing. + */ +void mp_free_av_packet(AVPacket **pkt) +{ + if (*pkt) { + (*pkt)->side_data = NULL; + (*pkt)->side_data_elems = 0; + (*pkt)->buf = NULL; + } + av_packet_free(pkt); +} + +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c) +{ + c->codec_profile = av_get_profile_name(avctx->codec, avctx->profile); + if (!c->codec_profile) + c->codec_profile = avcodec_profile_name(avctx->codec_id, avctx->profile); + c->codec = avctx->codec_descriptor->name; + c->codec_desc = avctx->codec_descriptor->long_name; + c->decoder = avctx->codec->name; + c->decoder_desc = avctx->codec->long_name; +} diff --git a/common/av_common.h b/common/av_common.h index 1b3e468884..c584085890 100644 --- a/common/av_common.h +++ b/common/av_common.h @@ -31,11 +31,10 @@ struct mp_codec_params; struct AVDictionary; struct mp_log; -int mp_lavc_set_extradata(AVCodecContext *avctx, void *ptr, int size); enum AVMediaType mp_to_av_stream_type(int type); -AVCodecParameters *mp_codec_params_to_av(struct mp_codec_params *c); -int mp_set_avctx_codec_headers(AVCodecContext *avctx, struct mp_codec_params *c); -AVRational mp_get_codec_timebase(struct mp_codec_params *c); +AVCodecParameters *mp_codec_params_to_av(const struct mp_codec_params *c); +int mp_set_avctx_codec_headers(AVCodecContext *avctx, const struct mp_codec_params *c); +AVRational mp_get_codec_timebase(const struct mp_codec_params *c); void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb); int64_t mp_pts_to_av(double mp_pts, AVRational *tb); double mp_pts_from_av(int64_t av_pts, AVRational *tb); @@ -50,5 +49,7 @@ void mp_set_avdict(struct AVDictionary **dict, char **kv); void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d); int mp_set_avopts(struct mp_log *log, void *avobj, char **kv); int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv); +void mp_free_av_packet(AVPacket **pkt); +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c); #endif diff --git a/common/av_log.c b/common/av_log.c index 8122d3a65b..54b78a617d 100644 --- a/common/av_log.c +++ b/common/av_log.c @@ -22,22 +22,29 @@ #include <stdlib.h> #include <stdio.h> #include <stdbool.h> -#include <pthread.h> #include "av_log.h" -#include "config.h" #include "common/common.h" #include "common/global.h" #include "common/msg.h" +#include "config.h" +#include "misc/bstr.h" +#include "osdep/threads.h" #include <libavutil/avutil.h> #include <libavutil/log.h> +#include <libavutil/version.h> #include <libavcodec/avcodec.h> +#include <libavcodec/version.h> #include <libavformat/avformat.h> +#include <libavformat/version.h> #include <libswresample/swresample.h> +#include <libswresample/version.h> #include <libswscale/swscale.h> +#include <libswscale/version.h> #include <libavfilter/avfilter.h> +#include <libavfilter/version.h> #if HAVE_LIBAVDEVICE #include <libavdevice/avdevice.h> @@ -45,10 +52,11 @@ // Needed because the av_log callback does not provide a library-safe message // callback. -static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER; +static mp_static_mutex log_lock = MP_STATIC_MUTEX_INITIALIZER; static struct mpv_global *log_mpv_instance; static struct mp_log *log_root, *log_decaudio, *log_decvideo, *log_demuxer; static bool log_print_prefix = true; +static bstr log_buffer; static int av_log_level_to_mp_level(int av_level) { @@ -74,7 +82,7 @@ static struct mp_log *get_av_log(void *ptr) if (!avc) { mp_warn(log_root, "av_log callback called with bad parameters (NULL AVClass).\n" - "This is a bug in one of Libav/FFmpeg libraries used.\n"); + "This is a bug in one of FFmpeg libraries used.\n"); return log_root; } @@ -100,6 +108,11 @@ static struct mp_log *get_av_log(void *ptr) return log_root; } +static const char *avclass_item_name(void *obj, const AVClass *avc) +{ + return (avc->item_name ? avc->item_name : av_default_item_name)(obj); +} + static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, va_list vl) { @@ -107,10 +120,10 @@ static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, int mp_level = av_log_level_to_mp_level(level); // Note: mp_log is thread-safe, but destruction of the log instances is not. - pthread_mutex_lock(&log_lock); + mp_mutex_lock(&log_lock); if (!log_mpv_instance) { - pthread_mutex_unlock(&log_lock); + mp_mutex_unlock(&log_lock); // Fallback to stderr vfprintf(stderr, fmt, vl); return; @@ -119,34 +132,36 @@ static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, struct mp_log *log = get_av_log(ptr); if (mp_msg_test(log, mp_level)) { - char buffer[4096] = ""; - int pos = 0; - const char *prefix = avc ? avc->item_name(ptr) : NULL; - if (log_print_prefix && prefix) - pos = snprintf(buffer, sizeof(buffer), "%s: ", prefix); - log_print_prefix = fmt[strlen(fmt) - 1] == '\n'; - - pos = MPMIN(MPMAX(pos, 0), sizeof(buffer)); - vsnprintf(buffer + pos, sizeof(buffer) - pos, fmt, vl); - - mp_msg(log, mp_level, "%s", buffer); + log_buffer.len = 0; + bstr_xappend_vasprintf(log_root, &log_buffer, fmt, vl); + if (!log_buffer.len) + goto done; + const char *prefix = avc ? avclass_item_name(ptr, avc) : NULL; + if (log_print_prefix && prefix) { + mp_msg(log, mp_level, "%s: %.*s", prefix, BSTR_P(log_buffer)); + } else { + mp_msg(log, mp_level, "%.*s", BSTR_P(log_buffer)); + } + log_print_prefix = log_buffer.start[log_buffer.len - 1] == '\n'; } - pthread_mutex_unlock(&log_lock); +done: + mp_mutex_unlock(&log_lock); } void init_libav(struct mpv_global *global) { - pthread_mutex_lock(&log_lock); + mp_mutex_lock(&log_lock); if (!log_mpv_instance) { log_mpv_instance = global; log_root = mp_log_new(NULL, global->log, "ffmpeg"); log_decaudio = mp_log_new(log_root, log_root, "audio"); log_decvideo = mp_log_new(log_root, log_root, "video"); log_demuxer = mp_log_new(log_root, log_root, "demuxer"); + log_buffer = (bstr){0}; av_log_set_callback(mp_msg_av_log_callback); } - pthread_mutex_unlock(&log_lock); + mp_mutex_unlock(&log_lock); avformat_network_init(); @@ -157,13 +172,13 @@ void init_libav(struct mpv_global *global) void uninit_libav(struct mpv_global *global) { - pthread_mutex_lock(&log_lock); + mp_mutex_lock(&log_lock); if (log_mpv_instance == global) { av_log_set_callback(av_log_default_callback); log_mpv_instance = NULL; talloc_free(log_root); } - pthread_mutex_unlock(&log_lock); + mp_mutex_unlock(&log_lock); } #define V(x) AV_VERSION_MAJOR(x), \ @@ -187,6 +202,7 @@ void check_library_versions(struct mp_log *log, int v) {"libswresample", LIBSWRESAMPLE_VERSION_INT, swresample_version()}, }; + mp_msg(log, v, "FFmpeg version: %s\n", av_version_info()); mp_msg(log, v, "FFmpeg library versions:\n"); for (int n = 0; n < MP_ARRAY_SIZE(libs); n++) { @@ -203,8 +219,6 @@ void check_library_versions(struct mp_log *log, int v) abort(); } } - - mp_msg(log, v, "FFmpeg version: %s\n", av_version_info()); } #undef V diff --git a/common/common.c b/common/common.c index 6607f95c3c..7089a6674b 100644 --- a/common/common.c +++ b/common/common.c @@ -21,6 +21,7 @@ #include <libavutil/common.h> #include <libavutil/error.h> +#include <libavutil/mathematics.h> #include "mpv_talloc.h" #include "misc/bstr.h" @@ -93,6 +94,25 @@ char *mp_format_time(double time, bool fractions) return mp_format_time_fmt(fractions ? "%H:%M:%S.%T" : "%H:%M:%S", time); } +char *mp_format_double(void *talloc_ctx, double val, int precision, + bool plus_sign, bool percent_sign, bool trim) +{ + bstr str = {0}; + const char *fmt = plus_sign ? "%+.*f" : "%.*f"; + bstr_xappend_asprintf(talloc_ctx, &str, fmt, precision, val); + size_t pos = str.len; + if (trim) { + while (--pos && str.start[pos] == '0') + str.len--; + if (str.start[pos] == '.') + str.len--; + } + if (percent_sign) + bstr_xappend(talloc_ctx, &str, bstr0("%")); + str.start[str.len] = '\0'; + return str.start; +} + // Set rc to the union of rc and rc2 void mp_rect_union(struct mp_rect *rc, const struct mp_rect *rc2) { @@ -120,12 +140,43 @@ bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2) return rc->x1 > rc->x0 && rc->y1 > rc->y0; } -bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2) +bool mp_rect_equals(const struct mp_rect *rc1, const struct mp_rect *rc2) { return rc1->x0 == rc2->x0 && rc1->y0 == rc2->y0 && rc1->x1 == rc2->x1 && rc1->y1 == rc2->y1; } +// Rotate mp_rect by 90 degrees increments +void mp_rect_rotate(struct mp_rect *rc, int w, int h, int rotation) +{ + rotation %= 360; + + if (rotation >= 180) { + rotation -= 180; + MPSWAP(int, rc->x0, rc->x1); + MPSWAP(int, rc->y0, rc->y1); + } + + if (rotation == 90) { + *rc = (struct mp_rect) { + .x0 = rc->y1, + .y0 = rc->x0, + .x1 = rc->y0, + .y1 = rc->x1, + }; + } + + if (rc->x1 < rc->x0) { + rc->x0 = w - rc->x0; + rc->x1 = w - rc->x1; + } + + if (rc->y1 < rc->y0) { + rc->y0 = h - rc->y0; + rc->y1 = h - rc->y1; + } +} + // Compute rc1-rc2, put result in res_array, return number of rectangles in // res_array. In the worst case, there are 4 rectangles, so res_array must // provide that much storage space. @@ -373,3 +424,9 @@ uint32_t mp_round_next_power_of_2(uint32_t v) int l = mp_log2(v) + 1; return l == 32 ? 0 : (uint32_t)1 << l; } + +int mp_lcm(int x, int y) +{ + assert(x && y); + return x * (y / av_gcd(x, y)); +} diff --git a/common/common.h b/common/common.h index af01e38e10..7466ea2d61 100644 --- a/common/common.h +++ b/common/common.h @@ -24,6 +24,13 @@ #include <stdbool.h> #include <stdint.h> +#include "config.h" + +#if HAVE_POSIX || defined(__MINGW32__) +#include <strings.h> +#include <unistd.h> +#endif + #include "osdep/compiler.h" #include "mpv_talloc.h" @@ -39,6 +46,7 @@ #define MPSWAP(type, a, b) \ do { type SWAP_tmp = b; b = a; a = SWAP_tmp; } while (0) #define MP_ARRAY_SIZE(s) (sizeof(s) / sizeof((s)[0])) +#define MP_DIV_UP(x, y) (((x) + (y) - 1) / (y)) // align must be a power of two (align >= 1), x >= 0 #define MP_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) @@ -46,6 +54,9 @@ #define MP_IS_ALIGNED(x, align) (!((x) & ((align) - 1))) #define MP_IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1))) +// align to non power of two +#define MP_ALIGN_NPOT(x, align) ((align) ? MP_DIV_UP(x, align) * (align) : (x)) + // Return "a", or if that is NOPTS, return "def". #define MP_PTS_OR_DEF(a, def) ((a) == MP_NOPTS_VALUE ? (def) : (a)) // If one of the values is NOPTS, always pick the other one. @@ -68,6 +79,26 @@ enum stream_type { STREAM_TYPE_COUNT, }; +enum video_sync { + VS_DEFAULT = 0, + VS_DISP_RESAMPLE, + VS_DISP_RESAMPLE_VDROP, + VS_DISP_RESAMPLE_NONE, + VS_DISP_TEMPO, + VS_DISP_ADROP, + VS_DISP_VDROP, + VS_DISP_NONE, + VS_NONE, +}; + +#define VS_IS_DISP(x) ((x) == VS_DISP_RESAMPLE || \ + (x) == VS_DISP_RESAMPLE_VDROP || \ + (x) == VS_DISP_RESAMPLE_NONE || \ + (x) == VS_DISP_TEMPO || \ + (x) == VS_DISP_ADROP || \ + (x) == VS_DISP_VDROP || \ + (x) == VS_DISP_NONE) + extern const char mpv_version[]; extern const char mpv_builddate[]; extern const char mpv_copyright[]; @@ -75,6 +106,12 @@ extern const char mpv_copyright[]; char *mp_format_time(double time, bool fractions); char *mp_format_time_fmt(const char *fmt, double time); +// Formats a double value to a string with the specified precision. +// Trailing zeros (and the dot) can be trimmed. +// Optionally, a plus sign and a percent sign can be added. +char *mp_format_double(void *talloc_ctx, double val, int precision, + bool plus_sign, bool percent_sign, bool trim); + struct mp_rect { int x0, y0; int x1, y1; @@ -86,12 +123,14 @@ struct mp_rect { void mp_rect_union(struct mp_rect *rc, const struct mp_rect *src); bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2); bool mp_rect_contains(struct mp_rect *rc, int x, int y); -bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2); +bool mp_rect_equals(const struct mp_rect *rc1, const struct mp_rect *rc2); int mp_rect_subtract(const struct mp_rect *rc1, const struct mp_rect *rc2, struct mp_rect res_array[4]); +void mp_rect_rotate(struct mp_rect *rc, int w, int h, int rotation); unsigned int mp_log2(uint32_t v); uint32_t mp_round_next_power_of_2(uint32_t v); +int mp_lcm(int x, int y); int mp_snprintf_cat(char *str, size_t size, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); @@ -132,4 +171,25 @@ char **mp_dup_str_array(void *tctx, char **s); abort(); \ } while (0) +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#define strcasecmp _stricmp + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif +#ifndef O_NONBLOCK +#define O_NONBLOCK 0 +#endif + +typedef long long ssize_t; +typedef unsigned short mode_t; +#endif + #endif /* MPLAYER_MPCOMMON_H */ diff --git a/common/encode.h b/common/encode.h index c951e95d51..33d778cd67 100644 --- a/common/encode.h +++ b/common/encode.h @@ -38,12 +38,8 @@ struct encode_opts { char **vopts; char *acodec; char **aopts; - float voffset; - float aoffset; - int rawts; - int video_first; - int audio_first; - int copy_metadata; + bool rawts; + bool copy_metadata; char **set_metadata; char **remove_metadata; }; diff --git a/common/encode_lavc.c b/common/encode_lavc.c index 2af93d239f..33743007dd 100644 --- a/common/encode_lavc.c +++ b/common/encode_lavc.c @@ -23,7 +23,6 @@ #include <libavutil/avutil.h> #include <libavutil/timestamp.h> -#include "config.h" #include "encode_lavc.h" #include "common/av_common.h" #include "common/global.h" @@ -84,30 +83,15 @@ const struct m_sub_options encode_config = { {"ovcopts", OPT_KEYVALUELIST(vopts), .flags = M_OPT_HAVE_HELP}, {"oac", OPT_STRING(acodec)}, {"oacopts", OPT_KEYVALUELIST(aopts), .flags = M_OPT_HAVE_HELP}, - {"ovoffset", OPT_FLOAT(voffset), M_RANGE(-1000000.0, 1000000.0), - .deprecation_message = "--audio-delay (once unbroken)"}, - {"oaoffset", OPT_FLOAT(aoffset), M_RANGE(-1000000.0, 1000000.0), - .deprecation_message = "--audio-delay (once unbroken)"}, - {"orawts", OPT_FLAG(rawts)}, - {"ovfirst", OPT_FLAG(video_first), - .deprecation_message = "no replacement"}, - {"oafirst", OPT_FLAG(audio_first), - .deprecation_message = "no replacement"}, - {"ocopy-metadata", OPT_FLAG(copy_metadata)}, + {"orawts", OPT_BOOL(rawts)}, + {"ocopy-metadata", OPT_BOOL(copy_metadata)}, {"oset-metadata", OPT_KEYVALUELIST(set_metadata)}, {"oremove-metadata", OPT_STRINGLIST(remove_metadata)}, - - {"ocopyts", OPT_REMOVED("ocopyts is now the default")}, - {"oneverdrop", OPT_REMOVED("no replacement")}, - {"oharddup", OPT_REMOVED("use --vf-add=fps=VALUE")}, - {"ofps", OPT_REMOVED("no replacement (use --vf-add=fps=VALUE for CFR)")}, - {"oautofps", OPT_REMOVED("no replacement")}, - {"omaxfps", OPT_REMOVED("no replacement")}, {0} }, .size = sizeof(struct encode_opts), .defaults = &(const struct encode_opts){ - .copy_metadata = 1, + .copy_metadata = true, }, }; @@ -120,7 +104,7 @@ struct encode_lavc_context *encode_lavc_init(struct mpv_global *global) .priv = talloc_zero(ctx, struct encode_priv), .log = mp_log_new(ctx, global->log, "encode"), }; - pthread_mutex_init(&ctx->lock, NULL); + mp_mutex_init(&ctx->lock); struct encode_priv *p = ctx->priv; p->log = ctx->log; @@ -133,12 +117,6 @@ struct encode_lavc_context *encode_lavc_init(struct mpv_global *global) if (!strcmp(filename, "-")) filename = "pipe:1"; - if (filename && ( - !strcmp(filename, "/dev/stdout") || - !strcmp(filename, "pipe:") || - !strcmp(filename, "pipe:1"))) - mp_msg_force_stderr(global, true); - encode_lavc_discontinuity(ctx); p->muxer = avformat_alloc_context(); @@ -173,7 +151,7 @@ void encode_lavc_set_metadata(struct encode_lavc_context *ctx, { struct encode_priv *p = ctx->priv; - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); if (ctx->options->copy_metadata) { p->metadata = mp_tags_dup(ctx, metadata); @@ -200,7 +178,7 @@ void encode_lavc_set_metadata(struct encode_lavc_context *ctx, } } - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); } bool encode_lavc_free(struct encode_lavc_context *ctx) @@ -236,7 +214,7 @@ bool encode_lavc_free(struct encode_lavc_context *ctx) res = !p->failed; - pthread_mutex_destroy(&ctx->lock); + mp_mutex_destroy(&ctx->lock); talloc_free(ctx); return res; @@ -329,7 +307,7 @@ void encode_lavc_expect_stream(struct encode_lavc_context *ctx, { struct encode_priv *p = ctx->priv; - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); enum AVMediaType codec_type = mp_to_av_stream_type(type); @@ -353,7 +331,7 @@ void encode_lavc_expect_stream(struct encode_lavc_context *ctx, MP_TARRAY_APPEND(p, p->streams, p->num_streams, dst); done: - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); } // Signal that you are ready to encode (you provide the codec params etc. too). @@ -367,7 +345,7 @@ static void encode_lavc_add_stream(struct encoder_context *enc, { struct encode_priv *p = ctx->priv; - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); struct mux_stream *dst = find_mux_stream(ctx, info->codecpar->codec_type); if (!dst) { @@ -403,7 +381,7 @@ static void encode_lavc_add_stream(struct encoder_context *enc, maybe_init_muxer(ctx); done: - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); } // Write a packet. This will take over ownership of `pkt` @@ -414,7 +392,7 @@ static void encode_lavc_add_packet(struct mux_stream *dst, AVPacket *pkt) assert(dst->st); - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); if (p->failed) goto done; @@ -451,7 +429,7 @@ static void encode_lavc_add_packet(struct mux_stream *dst, AVPacket *pkt) pkt = NULL; done: - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); if (pkt) av_packet_unref(pkt); } @@ -466,9 +444,9 @@ void encode_lavc_discontinuity(struct encode_lavc_context *ctx) if (!ctx) return; - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); ctx->discontinuity_pts_offset = MP_NOPTS_VALUE; - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); } static void encode_lavc_printoptions(struct mp_log *log, const void *obj, @@ -689,7 +667,7 @@ int encode_lavc_getstatus(struct encode_lavc_context *ctx, float minutes, megabytes, fps, x; float f = MPMAX(0.0001, relative_position); - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); if (p->failed) { snprintf(buf, bufsize, "(failed)\n"); @@ -713,7 +691,7 @@ int encode_lavc_getstatus(struct encode_lavc_context *ctx, buf[bufsize - 1] = 0; done: - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); return 0; } @@ -721,9 +699,9 @@ bool encode_lavc_didfail(struct encode_lavc_context *ctx) { if (!ctx) return false; - pthread_mutex_lock(&ctx->lock); + mp_mutex_lock(&ctx->lock); bool fail = ctx->priv->failed; - pthread_mutex_unlock(&ctx->lock); + mp_mutex_unlock(&ctx->lock); return fail; } @@ -731,11 +709,13 @@ static void encoder_destroy(void *ptr) { struct encoder_context *p = ptr; + av_packet_free(&p->pkt); + avcodec_parameters_free(&p->info.codecpar); avcodec_free_context(&p->encoder); free_stream(p->twopass_bytebuffer); } -static AVCodec *find_codec_for(struct encode_lavc_context *ctx, +static const AVCodec *find_codec_for(struct encode_lavc_context *ctx, enum stream_type type, bool *used_auto) { char *codec_name = type == STREAM_VIDEO @@ -746,7 +726,7 @@ static AVCodec *find_codec_for(struct encode_lavc_context *ctx, *used_auto = !(codec_name && codec_name[0]); - AVCodec *codec; + const AVCodec *codec; if (*used_auto) { codec = avcodec_find_encoder(av_guess_codec(ctx->oformat, NULL, ctx->options->file, NULL, @@ -797,7 +777,7 @@ struct encoder_context *encoder_context_alloc(struct encode_lavc_context *ctx, }; bool auto_codec; - AVCodec *codec = find_codec_for(ctx, type, &auto_codec); + const AVCodec *codec = find_codec_for(ctx, type, &auto_codec); const char *tname = stream_type_name(type); if (!codec) { @@ -884,8 +864,8 @@ bool encoder_init_codec_and_muxer(struct encoder_context *p, " ********************************************\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" + "- Codec implementation in ffmpeg is not finished yet.\n" + " Try updating ffmpeg.\n" "- Bad picture quality, blocks, blurriness.\n" " Experiment with codec settings to maybe still get the\n" " desired quality output at the expense of bitrate.\n" @@ -910,6 +890,9 @@ bool encoder_init_codec_and_muxer(struct encoder_context *p, if (avcodec_parameters_from_context(p->info.codecpar, p->encoder) < 0) goto fail; + p->pkt = av_packet_alloc(); + MP_HANDLE_OOM(p->pkt); + encode_lavc_add_stream(p, p->encode_lavc_ctx, &p->info, on_ready, ctx); if (!p->mux_stream) goto fail; @@ -917,7 +900,7 @@ bool encoder_init_codec_and_muxer(struct encoder_context *p, return true; fail: - avcodec_close(p->encoder); + avcodec_free_context(&p->encoder); return false; } @@ -930,11 +913,9 @@ bool encoder_encode(struct encoder_context *p, AVFrame *frame) goto fail; } + AVPacket *packet = p->pkt; for (;;) { - AVPacket packet = {0}; - av_init_packet(&packet); - - status = avcodec_receive_packet(p->encoder, &packet); + status = avcodec_receive_packet(p->encoder, packet); if (status == AVERROR(EAGAIN)) break; if (status < 0 && status != AVERROR_EOF) @@ -948,7 +929,7 @@ bool encoder_en |