mpv/video/decode/vd_lavc.c

1447 lines
47 KiB
C
Raw Normal View History

/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <libavcodec/avcodec.h>
#include <libavformat/version.h>
#include <libavutil/common.h>
#include <libavutil/hwcontext.h>
#include <libavutil/opt.h>
#include <libavutil/intreadwrite.h>
#include <libavutil/pixdesc.h>
#include "mpv_talloc.h"
#include "common/msg.h"
#include "options/m_config.h"
#include "options/options.h"
2023-10-21 02:55:41 +00:00
#include "osdep/threads.h"
#include "misc/bstr.h"
#include "common/av_common.h"
#include "common/codecs.h"
#include "video/fmt-conversion.h"
#include "filters/f_decoder_wrapper.h"
#include "filters/filter_internal.h"
#include "video/hwdec.h"
#include "video/img_format.h"
#include "video/mp_image.h"
#include "video/mp_image_pool.h"
#include "demux/demux.h"
#include "demux/stheader.h"
#include "demux/packet.h"
#include "video/csputils.h"
#include "video/sws_utils.h"
#include "video/out/vo.h"
#include "options/m_option.h"
static void init_avctx(struct mp_filter *vd);
static void uninit_avctx(struct mp_filter *vd);
static int get_buffer2_direct(AVCodecContext *avctx, AVFrame *pic, int flags);
static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
const enum AVPixelFormat *pix_fmt);
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
static int hwdec_opt_help(struct mp_log *log, const m_option_t *opt,
struct bstr name);
#define HWDEC_DELAY_QUEUE_COUNT 2
#define OPT_BASE_STRUCT struct vd_lavc_params
struct vd_lavc_params {
bool fast;
int film_grain;
bool show_all;
int skip_loop_filter;
int skip_idct;
int skip_frame;
int framedrop;
int threads;
bool bitexact;
bool old_x264;
bool apply_cropping;
bool check_hw_profile;
int software_fallback;
char **avopts;
int dr;
char **hwdec_api;
char *hwdec_codecs;
int hwdec_image_format;
int hwdec_extra_frames;
};
static const struct m_opt_choice_alternatives discard_names[] = {
{"none", AVDISCARD_NONE},
{"default", AVDISCARD_DEFAULT},
{"nonref", AVDISCARD_NONREF},
{"bidir", AVDISCARD_BIDIR},
{"nonkey", AVDISCARD_NONKEY},
{"all", AVDISCARD_ALL},
{0}
};
#define OPT_DISCARD(field) OPT_CHOICE_C(field, discard_names)
const struct m_sub_options vd_lavc_conf = {
.opts = (const m_option_t[]){
{"vd-lavc-fast", OPT_BOOL(fast)},
{"vd-lavc-film-grain", OPT_CHOICE(film_grain,
{"auto", -1}, {"cpu", 0}, {"gpu", 1})},
{"vd-lavc-show-all", OPT_BOOL(show_all)},
{"vd-lavc-skiploopfilter", OPT_DISCARD(skip_loop_filter)},
{"vd-lavc-skipidct", OPT_DISCARD(skip_idct)},
{"vd-lavc-skipframe", OPT_DISCARD(skip_frame)},
{"vd-lavc-framedrop", OPT_DISCARD(framedrop)},
{"vd-lavc-threads", OPT_INT(threads), M_RANGE(0, DBL_MAX)},
{"vd-lavc-bitexact", OPT_BOOL(bitexact)},
{"vd-lavc-assume-old-x264", OPT_BOOL(old_x264)},
{"vd-lavc-check-hw-profile", OPT_BOOL(check_hw_profile)},
{"vd-lavc-software-fallback", OPT_CHOICE(software_fallback,
{"no", INT_MAX}, {"yes", 1}), M_RANGE(1, INT_MAX)},
{"vd-lavc-o", OPT_KEYVALUELIST(avopts)},
{"vd-lavc-dr", OPT_CHOICE(dr,
{"auto", -1}, {"no", 0}, {"yes", 1})},
{"vd-apply-cropping", OPT_BOOL(apply_cropping)},
{"hwdec", OPT_STRINGLIST(hwdec_api),
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
.help = hwdec_opt_help,
.flags = M_OPT_OPTIONAL_PARAM | M_OPT_ALLOW_NO | UPDATE_HWDEC},
{"hwdec-codecs", OPT_STRING(hwdec_codecs)},
{"hwdec-image-format", OPT_IMAGEFORMAT(hwdec_image_format)},
{"hwdec-extra-frames", OPT_INT(hwdec_extra_frames), M_RANGE(0, 256)},
{0}
},
.size = sizeof(struct vd_lavc_params),
.defaults = &(const struct vd_lavc_params){
.film_grain = -1 /*auto*/,
.check_hw_profile = true,
.software_fallback = 3,
.skip_loop_filter = AVDISCARD_DEFAULT,
.skip_idct = AVDISCARD_DEFAULT,
.skip_frame = AVDISCARD_DEFAULT,
.framedrop = AVDISCARD_NONREF,
.dr = -1,
.hwdec_api = (char *[]){"no", NULL,},
.hwdec_codecs = "h264,vc1,hevc,vp8,vp9,av1,prores",
// Maximum number of surfaces the player wants to buffer. This number
// might require adjustment depending on whatever the player does;
// for example, if vo_gpu increases the number of reference surfaces for
// interpolation, this value has to be increased too.
.hwdec_extra_frames = 6,
.apply_cropping = true,
},
};
struct hwdec_info {
char name[64];
char method_name[24]; // non-unique name describing the hwdec method
const AVCodec *codec; // implemented by this codec
enum AVHWDeviceType lavc_device; // if not NONE, get a hwdevice
bool copying; // if true, outputs sw frames, or copy to sw ourselves
enum AVPixelFormat pix_fmt; // if not NONE, select in get_format
bool use_hw_frames; // set AVCodecContext.hw_frames_ctx
bool use_hw_device; // set AVCodecContext.hw_device_ctx
unsigned int flags; // HWDEC_FLAG_*
// for internal sorting
int auto_pos;
int rank;
};
typedef struct lavc_ctx {
struct mp_log *log;
struct m_config_cache *opts_cache;
struct vd_lavc_params *opts;
struct mp_codec_params *codec;
AVCodecContext *avctx;
AVFrame *pic;
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
AVPacket *avpkt;
bool use_hwdec;
struct hwdec_info hwdec; // valid only if use_hwdec==true
bstr *attempted_hwdecs;
int num_attempted_hwdecs;
AVRational codec_timebase;
enum AVDiscard skip_frame;
bool flushing;
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
struct lavc_state state;
const char *decoder;
bool hwdec_failed;
bool hwdec_notified;
bool force_eof;
bool intra_only;
int framedrop_flags;
bool hw_probing;
struct demux_packet **sent_packets;
int num_sent_packets;
struct demux_packet **requeue_packets;
int num_requeue_packets;
struct mp_image **delay_queue;
int num_delay_queue;
int max_delay_queue;
// From VO
struct vo *vo;
struct mp_hwdec_devices *hwdec_devs;
// Wrapped AVHWDeviceContext* used for decoding.
AVBufferRef *hwdec_dev;
bool hwdec_request_reinit;
int hwdec_fail_count;
struct mp_image_pool *hwdec_swpool;
AVBufferRef *cached_hw_frames_ctx;
// --- The following fields are protected by dr_lock.
2023-10-21 02:55:41 +00:00
mp_mutex dr_lock;
bool dr_failed;
struct mp_image_pool *dr_pool;
int dr_imgfmt, dr_w, dr_h, dr_stride_align;
struct mp_decoder public;
} vd_ffmpeg_ctx;
enum {
HWDEC_FLAG_AUTO = (1 << 0), // prioritize in autoprobe order
HWDEC_FLAG_WHITELIST = (1 << 1), // whitelist for auto-safe
};
struct autoprobe_info {
const char *method_name;
unsigned int flags; // HWDEC_FLAG_*
};
// Things not included in this list will be tried last, in random order.
const struct autoprobe_info hwdec_autoprobe_info[] = {
{"d3d11va", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"dxva2", HWDEC_FLAG_AUTO},
{"d3d11va-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"dxva2-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"nvdec", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"nvdec-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"vaapi", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"vaapi-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"vulkan", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"vulkan-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"vdpau", HWDEC_FLAG_AUTO},
{"vdpau-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"drm", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"drm-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"mmal", HWDEC_FLAG_AUTO},
{"mmal-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"mediacodec", HWDEC_FLAG_AUTO},
{"mediacodec-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"videotoolbox", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{"videotoolbox-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
{0}
};
static int hwdec_compare(const void *p1, const void *p2)
{
struct hwdec_info *h1 = (void *)p1;
struct hwdec_info *h2 = (void *)p2;
if (h1 == h2)
return 0;
// Strictly put non-preferred hwdecs to the end of the list.
if ((h1->auto_pos == INT_MAX) != (h2->auto_pos == INT_MAX))
return h1->auto_pos == INT_MAX ? 1 : -1;
// List non-copying entries first, so --hwdec=auto takes them.
if (h1->copying != h2->copying)
return h1->copying ? 1 : -1;
2022-04-25 11:27:18 +00:00
// Order by autoprobe preference order.
if (h1->auto_pos != h2->auto_pos)
return h1->auto_pos > h2->auto_pos ? 1 : -1;
// Put hwdecs without hw_device_ctx last
if ((!!h1->lavc_device) != (!!h2->lavc_device))
return h1->lavc_device ? -1 : 1;
// Fallback sort order to make sorting stable.
return h1->rank > h2->rank ? 1 :-1;
}
// (This takes care of some bookkeeping too, like setting info.name)
static void add_hwdec_item(struct hwdec_info **infos, int *num_infos,
struct hwdec_info info)
{
if (info.copying)
mp_snprintf_cat(info.method_name, sizeof(info.method_name), "-copy");
// (Including the codec name in case this is a wrapper looks pretty dumb,
// but better not have them clash with hwaccels and others.)
snprintf(info.name, sizeof(info.name), "%s-%s",
info.codec->name, info.method_name);
info.rank = *num_infos;
info.auto_pos = INT_MAX;
for (int x = 0; hwdec_autoprobe_info[x].method_name; x++) {
const struct autoprobe_info *entry = &hwdec_autoprobe_info[x];
if (strcmp(entry->method_name, info.method_name) == 0) {
info.flags |= entry->flags;
if (info.flags & HWDEC_FLAG_AUTO)
info.auto_pos = x;
}
}
MP_TARRAY_APPEND(NULL, *infos, *num_infos, info);
}
static void add_all_hwdec_methods(struct hwdec_info **infos, int *num_infos)
{
const AVCodec *codec = NULL;
void *iter = NULL;
while (1) {
codec = av_codec_iterate(&iter);
if (!codec)
break;
if (codec->type != AVMEDIA_TYPE_VIDEO || !av_codec_is_decoder(codec))
continue;
struct hwdec_info info_template = {
.pix_fmt = AV_PIX_FMT_NONE,
.codec = codec,
};
const char *wrapper = NULL;
if (codec->capabilities & (AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_HYBRID))
wrapper = codec->wrapper_name;
// A decoder can provide multiple methods. In particular, hwaccels
// provide various methods (e.g. native h264 with vaapi & d3d11), but
// even wrapper decoders could provide multiple methods.
bool found_any = false;
for (int n = 0; ; n++) {
const AVCodecHWConfig *cfg = avcodec_get_hw_config(codec, n);
if (!cfg)
break;
if ((cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) ||
(cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
{
struct hwdec_info info = info_template;
info.lavc_device = cfg->device_type;
info.pix_fmt = cfg->pix_fmt;
const char *name = av_hwdevice_get_type_name(cfg->device_type);
assert(name); // API violation by libavcodec
// nvdec hwaccels and the cuvid full decoder clash with their
// naming, so fix it here; we also prefer nvdec for the hwaccel.
if (strcmp(name, "cuda") == 0 && !wrapper)
name = "nvdec";
snprintf(info.method_name, sizeof(info.method_name), "%s", name);
// Usually we want to prefer using hw_frames_ctx for true
// hwaccels only, but we actually don't have any way to detect
// those, so always use hw_frames_ctx if offered.
if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
info.use_hw_frames = true;
} else {
info.use_hw_device = true;
}
// Direct variant.
add_hwdec_item(infos, num_infos, info);
// Copy variant.
info.copying = true;
if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) {
info.use_hw_frames = false;
info.use_hw_device = true;
}
add_hwdec_item(infos, num_infos, info);
found_any = true;
} else if (cfg->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) {
struct hwdec_info info = info_template;
info.pix_fmt = cfg->pix_fmt;
const char *name = wrapper;
if (!name)
name = av_get_pix_fmt_name(info.pix_fmt);
assert(name); // API violation by libavcodec
snprintf(info.method_name, sizeof(info.method_name), "%s", name);
// Direct variant.
add_hwdec_item(infos, num_infos, info);
// Copy variant.
info.copying = true;
info.pix_fmt = AV_PIX_FMT_NONE; // trust it can do sw output
add_hwdec_item(infos, num_infos, info);
found_any = true;
}
}
if (!found_any && wrapper) {
// We _know_ there's something supported here, usually outputting
// sw surfaces. E.g. mediacodec (before hw_device_ctx support).
struct hwdec_info info = info_template;
info.copying = true; // probably
snprintf(info.method_name, sizeof(info.method_name), "%s", wrapper);
add_hwdec_item(infos, num_infos, info);
}
}
qsort(*infos, *num_infos, sizeof(struct hwdec_info), hwdec_compare);
}
static bool hwdec_codec_allowed(struct mp_filter *vd, const char *codec)
{
vd_ffmpeg_ctx *ctx = vd->priv;
bstr s = bstr0(ctx->opts->hwdec_codecs);
while (s.len) {
bstr item;
bstr_split_tok(s, ",", &item, &s);
if (bstr_equals0(item, "all") || bstr_equals0(item, codec))
return true;
}
return false;
}
static AVBufferRef *hwdec_create_dev(struct mp_filter *vd,
struct hwdec_info *hwdec,
bool autoprobe)
{
vd_ffmpeg_ctx *ctx = vd->priv;
assert(hwdec->lavc_device);
if (hwdec->copying) {
const struct hwcontext_fns *fns =
hwdec_get_hwcontext_fns(hwdec->lavc_device);
if (fns && fns->create_dev) {
struct hwcontext_create_dev_params params = {
.probing = autoprobe,
};
return fns->create_dev(vd->global, vd->log, &params);
} else {
AVBufferRef* ref = NULL;
av_hwdevice_ctx_create(&ref, hwdec->lavc_device, NULL, NULL, 0);
return ref;
}
} else if (ctx->hwdec_devs) {
int imgfmt = pixfmt2imgfmt(hwdec->pix_fmt);
struct hwdec_imgfmt_request params = {
.imgfmt = imgfmt,
.probing = autoprobe,
};
hwdec_devices_request_for_img_fmt(ctx->hwdec_devs, &params);
const struct mp_hwdec_ctx *hw_ctx =
hwdec_devices_get_by_imgfmt_and_type(ctx->hwdec_devs, imgfmt,
hwdec->lavc_device);
if (hw_ctx && hw_ctx->av_device_ref)
return av_buffer_ref(hw_ctx->av_device_ref);
}
return NULL;
}
// Select if and which hwdec to use. Also makes sure to get the decode device.
static void select_and_set_hwdec(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
const char *codec = ctx->codec->codec;
m_config_cache_update(ctx->opts_cache);
struct hwdec_info *hwdecs = NULL;
int num_hwdecs = 0;
add_all_hwdec_methods(&hwdecs, &num_hwdecs);
char **hwdec_api = ctx->opts->hwdec_api;
for (int i = 0; hwdec_api && hwdec_api[i]; i++) {
bstr opt = bstr0(hwdec_api[i]);
bool hwdec_requested = !bstr_equals0(opt, "no");
bool hwdec_auto_all = bstr_equals0(opt, "auto") ||
bstr_equals0(opt, "");
bool hwdec_auto_safe = bstr_equals0(opt, "auto-safe") ||
bstr_equals0(opt, "auto-copy-safe") ||
bstr_equals0(opt, "yes");
bool hwdec_auto_copy = bstr_equals0(opt, "auto-copy") ||
bstr_equals0(opt, "auto-copy-safe");
bool hwdec_auto = hwdec_auto_all || hwdec_auto_copy || hwdec_auto_safe;
if (!hwdec_requested) {
MP_VERBOSE(vd, "No hardware decoding requested.\n");
break;
} else if (!hwdec_codec_allowed(vd, codec)) {
MP_VERBOSE(vd, "Not trying to use hardware decoding: codec %s is not "
"on whitelist.\n", codec);
break;
} else {
bool hwdec_name_supported = false; // relevant only if !hwdec_auto
for (int n = 0; n < num_hwdecs; n++) {
struct hwdec_info *hwdec = &hwdecs[n];
if (!hwdec_auto && !(bstr_equals0(opt, hwdec->method_name) ||
bstr_equals0(opt, hwdec->name)))
continue;
hwdec_name_supported = true;
bool already_attempted = false;
for (int j = 0; j < ctx->num_attempted_hwdecs; j++) {
if (bstr_equals0(ctx->attempted_hwdecs[j], hwdec->name)) {
MP_DBG(vd, "Skipping previously attempted hwdec: %s\n",
hwdec->name);
already_attempted = true;
break;
}
}
if (already_attempted)
continue;
const char *hw_codec = mp_codec_from_av_codec_id(hwdec->codec->id);
if (!hw_codec || strcmp(hw_codec, codec) != 0)
continue;
if (hwdec_auto_safe && !(hwdec->flags & HWDEC_FLAG_WHITELIST))
continue;
MP_VERBOSE(vd, "Looking at hwdec %s...\n", hwdec->name);
/*
* Past this point, any kind of failure that results in us
* looking for a new hwdec should not lead to use trying this
* hwdec again - so add it to the list, regardless of whether
* initialisation will succeed or not.
*/
MP_TARRAY_APPEND(ctx, ctx->attempted_hwdecs,
ctx->num_attempted_hwdecs,
bstrdup(ctx, bstr0(hwdec->name)));
if (hwdec_auto_copy && !hwdec->copying) {
MP_VERBOSE(vd, "Not using this for auto-copy.\n");
continue;
}
if (hwdec->lavc_device) {
ctx->hwdec_dev = hwdec_create_dev(vd, hwdec, hwdec_auto);
if (!ctx->hwdec_dev) {
MP_VERBOSE(vd, "Could not create device.\n");
continue;
}
const struct hwcontext_fns *fns =
hwdec_get_hwcontext_fns(hwdec->lavc_device);
if (fns && fns->is_emulated && fns->is_emulated(ctx->hwdec_dev)) {
if (hwdec_auto) {
MP_VERBOSE(vd, "Not using emulated API.\n");
av_buffer_unref(&ctx->hwdec_dev);
continue;
}
MP_WARN(vd, "Using emulated hardware decoding API.\n");
}
} else if (!hwdec->copying) {
// Most likely METHOD_INTERNAL, which often use delay-loaded
// VO support as well.
if (ctx->hwdec_devs) {
struct hwdec_imgfmt_request params = {
.imgfmt = pixfmt2imgfmt(hwdec->pix_fmt),
.probing = hwdec_auto,
};
hwdec_devices_request_for_img_fmt(
ctx->hwdec_devs, &params);
}
}
ctx->use_hwdec = true;
ctx->hwdec = *hwdec;
break;
}
if (ctx->use_hwdec)
break;
else if (!hwdec_auto && !hwdec_name_supported)
MP_WARN(vd, "Unsupported hwdec: %.*s\n", BSTR_P(opt));
}
}
talloc_free(hwdecs);
if (ctx->use_hwdec) {
MP_VERBOSE(vd, "Trying hardware decoding via %s.\n", ctx->hwdec.name);
if (strcmp(ctx->decoder, ctx->hwdec.codec->name) != 0)
MP_VERBOSE(vd, "Using underlying hw-decoder '%s'\n",
ctx->hwdec.codec->name);
} else {
// If software fallback is disabled and we get here, all hwdec must
// have failed. Tell the ctx to always force an eof.
if (ctx->opts->software_fallback == INT_MAX) {
MP_WARN(ctx, "Software decoding fallback is disabled.\n");
ctx->force_eof = true;
} else {
MP_VERBOSE(vd, "Using software decoding.\n");
}
}
}
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
static int hwdec_opt_help(struct mp_log *log, const m_option_t *opt,
struct bstr name)
{
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
struct hwdec_info *hwdecs = NULL;
int num_hwdecs = 0;
add_all_hwdec_methods(&hwdecs, &num_hwdecs);
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
mp_info(log, "Valid values (with alternative full names):\n");
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
for (int n = 0; n < num_hwdecs; n++) {
struct hwdec_info *hwdec = &hwdecs[n];
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
mp_info(log, " %s (%s)\n", hwdec->method_name, hwdec->name);
}
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
talloc_free(hwdecs);
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
mp_info(log, " auto (yes '')\n");
mp_info(log, " no\n");
mp_info(log, " auto-safe\n");
mp_info(log, " auto-copy\n");
mp_info(log, " auto-copy-safe\n");
options: Make validation and help possible for all option types Today, validation is only possible for string type options. But there's no particular reason why it needs to be restricted in this way, and there are potential uses, to allow other options to be validated without forcing the option to have to reimplement parsing from scratch. The first part, simply making the validation function an explicit field instead of overloading priv is simple enough. But if we only do that, then the validation function still needs to deal with the raw pre-parsed string. Instead, we want to allow the value to be parsed before it is validated. That in turn leads to us having validator functions that should be type aware. Unfortunately, that means we need to keep the explicit macro like OPT_STRING_VALIDATE() as a way to enforce the correct typing of the function. Otherwise, we'd have to have the validator take a void * and hope the implementation can cast it correctly. For help, we don't have this problem, as help doesn't look at the value. Then, we turn validators that are really help generators into explicit help functions and where a validator is help + validation, we split them into two parts. I have, however, left functions that need to query information for both help and validation as single functions to avoid code duplication. In this change, I have not added an other OPT_FOO_VALIDATE() macros as they are not needed, but I will add some in a separate change to illustrate the pattern.
2021-02-21 00:41:44 +00:00
return M_OPT_EXIT;
}
static void force_fallback(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
uninit_avctx(vd);
int lev = ctx->hwdec_notified ? MSGL_WARN : MSGL_V;
mp_msg(vd->log, lev, "Attempting next decoding method after failure of %.*s.\n",
BSTR_P(ctx->attempted_hwdecs[ctx->num_attempted_hwdecs - 1]));
select_and_set_hwdec(vd);
init_avctx(vd);
}
static void reinit(struct mp_filter *vd)
2011-10-22 00:51:37 +00:00
{
vd_ffmpeg_ctx *ctx = vd->priv;
uninit_avctx(vd);
vdpau: split off decoder parts, use "new" libavcodec vdpau hwaccel API Move the decoder parts from vo_vdpau.c to a new file vdpau_old.c. This file is named so because because it's written against the "old" libavcodec vdpau pseudo-decoder (e.g. "h264_vdpau"). Add support for the "new" libavcodec vdpau support. This was recently added and replaces the "old" vdpau parts. (In fact, Libav is about to deprecate and remove the "old" API without deprecation grace period, so we have to support it now. Moreover, there will probably be no Libav release which supports both, so the transition is even less smooth than we could hope, and we have to support both the old and new API.) Whether the old or new API is used is checked by a configure test: if the new API is found, it is used, otherwise the old API is assumed. Some details might be handled differently. Especially display preemption is a bit problematic with the "new" libavcodec vdpau support: it wants to keep a pointer to a specific vdpau API function (which can be driver specific, because preemption might switch drivers). Also, surface IDs are now directly stored in AVFrames (and mp_images), so they can't be forced to VDP_INVALID_HANDLE on preemption. (This changes even with older libavcodec versions, because mp_image always uses the newer representation to make vo_vdpau.c simpler.) Decoder initialization in the new code tries to deal with codec profiles, while the old code always uses the highest profile per codec. Surface allocation changes. Since the decoder won't call config() in vo_vdpau.c on video size change anymore, we allow allocating surfaces of arbitrary size instead of locking it to what the VO was configured. The non-hwdec code also has slightly different allocation behavior now. Enabling the old vdpau special decoders via e.g. --vd=lavc:h264_vdpau doesn't work anymore (a warning suggesting the --hwdec option is printed instead).
2013-07-27 23:49:45 +00:00
/*
* Reset attempted hwdecs so that if the hwdec list is reconfigured
* we attempt all of them from the beginning. The most practical
* reason for this is that ctrl+h toggles between `no` and
* `auto-safe`, and we want to reevaluate from a clean slate each time.
*/
TA_FREEP(&ctx->attempted_hwdecs);
ctx->num_attempted_hwdecs = 0;
ctx->hwdec_notified = false;
select_and_set_hwdec(vd);
bool use_hwdec = ctx->use_hwdec;
init_avctx(vd);
if (!ctx->avctx && use_hwdec) {
do {
force_fallback(vd);
} while (!ctx->avctx);
}
}
static void init_avctx(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
struct vd_lavc_params *lavc_param = ctx->opts;
struct mp_codec_params *c = ctx->codec;
core: redo how codecs are mapped, remove codecs.conf Use codec names instead of FourCCs to identify codecs. Rewrite how codecs are selected and initialized. Now each decoder exports a list of decoders (and the codec it supports) via add_decoders(). The order matters, and the first decoder for a given decoder is preferred over the other decoders. E.g. all ad_mpg123 decoders are preferred over ad_lavc, because it comes first in the mpcodecs_ad_drivers array. Likewise, decoders within ad_lavc that are enumerated first by libavcodec (using av_codec_next()) are preferred. (This is actually critical to select h264 software decoding by default instead of vdpau. libavcodec and ffmpeg/avconv use the same method to select decoders by default, so we hope this is sane.) The codec names follow libavcodec's codec names as defined by AVCodecDescriptor.name (see libavcodec/codec_desc.c). Some decoders have names different from the canonical codec name. The AVCodecDescriptor API is relatively new, so we need a compatibility layer for older libavcodec versions for codec names that are referenced internally, and which are different from the decoder name. (Add a configure check for that, because checking versions is getting way too messy.) demux/codec_tags.c is generated from the former codecs.conf (minus "special" decoders like vdpau, and excluding the mappings that are the same as the mappings libavformat's exported RIFF tables). It contains all the mappings from FourCCs to codec name. This is needed for demux_mkv, demux_mpg, demux_avi and demux_asf. demux_lavf will set the codec as determined by libavformat, while the other demuxers have to do this on their own, using the mp_set_audio/video_codec_from_tag() functions. Note that the sh_audio/video->format members don't uniquely identify the codec anymore, and sh->codec takes over this role. Replace the --ac/--vc/--afm/--vfm with new --vd/--ad options, which provide cover the functionality of the removed switched. Note: there's no CODECS_FLAG_FLIP flag anymore. This means some obscure container/video combinations (e.g. the sample Film_200_zygo_pro.mov) are played flipped. ffplay/avplay doesn't handle this properly either, so we don't care and blame ffmeg/libav instead.
2013-02-09 14:15:19 +00:00
m_config_cache_update(ctx->opts_cache);
assert(!ctx->avctx);
const AVCodec *lavc_codec = NULL;
if (ctx->use_hwdec) {
lavc_codec = ctx->hwdec.codec;
} else {
lavc_codec = avcodec_find_decoder_by_name(ctx->decoder);
}
core: redo how codecs are mapped, remove codecs.conf Use codec names instead of FourCCs to identify codecs. Rewrite how codecs are selected and initialized. Now each decoder exports a list of decoders (and the codec it supports) via add_decoders(). The order matters, and the first decoder for a given decoder is preferred over the other decoders. E.g. all ad_mpg123 decoders are preferred over ad_lavc, because it comes first in the mpcodecs_ad_drivers array. Likewise, decoders within ad_lavc that are enumerated first by libavcodec (using av_codec_next()) are preferred. (This is actually critical to select h264 software decoding by default instead of vdpau. libavcodec and ffmpeg/avconv use the same method to select decoders by default, so we hope this is sane.) The codec names follow libavcodec's codec names as defined by AVCodecDescriptor.name (see libavcodec/codec_desc.c). Some decoders have names different from the canonical codec name. The AVCodecDescriptor API is relatively new, so we need a compatibility layer for older libavcodec versions for codec names that are referenced internally, and which are different from the decoder name. (Add a configure check for that, because checking versions is getting way too messy.) demux/codec_tags.c is generated from the former codecs.conf (minus "special" decoders like vdpau, and excluding the mappings that are the same as the mappings libavformat's exported RIFF tables). It contains all the mappings from FourCCs to codec name. This is needed for demux_mkv, demux_mpg, demux_avi and demux_asf. demux_lavf will set the codec as determined by libavformat, while the other demuxers have to do this on their own, using the mp_set_audio/video_codec_from_tag() functions. Note that the sh_audio/video->format members don't uniquely identify the codec anymore, and sh->codec takes over this role. Replace the --ac/--vc/--afm/--vfm with new --vd/--ad options, which provide cover the functionality of the removed switched. Note: there's no CODECS_FLAG_FLIP flag anymore. This means some obscure container/video combinations (e.g. the sample Film_200_zygo_pro.mov) are played flipped. ffplay/avplay doesn't handle this properly either, so we don't care and blame ffmeg/libav instead.
2013-02-09 14:15:19 +00:00
if (!lavc_codec)
return;
video, audio: use lavc decoders without codecs.conf entries Add support for using libavcodec decoders that do not have entries in codecs.conf. This is currently only used with demux_lavf, and the codec selection is based on codec_id returned by libavformat. Also modify codec-related terminal output somewhat to make it use information from libavcodec and avoid excessively long default output. The new any-lavc-codec support is implemented with codecs.conf entries that invoke vd_ffmpeg/ad_ffmpeg without directly specifying any libavcodec codec name. In this mode, the decoders now instead select the libavcodec codec based on codec_id previously set by demux_lavf (if any). These new "generic" codecs.conf entries specify "status buggy", so that they're tried after any specific entries with higher-priority status. Add new directive "anyinput" to codecs.conf syntax. This means the entry will always match regardless of fourcc. This is used for the above new codecs.conf entries (so the driver always gets to decide whether to accept the input, and will fail init() if it can't find a suitable codec in libavcodec). Remove parsing support for the obsolete codecs.conf directive "cpuflags". This directive has not had any effect and has not been used in default codecs.conf since many years ago. Shorten codec-related terminal output. When using libavcodec decoders, show the libavcodec long_name field rather than codecs.conf "info" field as the name of the codec. Stop showing the codecs.conf entry name and "vfm/afm" name by default, as these are rarely needed; they're now in verbose output only. Show "VIDEO:" line at VO initialization rather than at demuxer open. This didn't really belong in demuxer code; the new location may show more accurate values (known after decoder has been opened) and works right if video track is changed after initial demuxer open. The vd.c changes (primarily done for terminal output changes) remove round-to-even behavior from code setting dimensions based on aspect ratio. I hope nothing depended on this; at least the even values were not consistently guaranteed anyway, as the rounding code did not run if the video file did not specify a nonzero aspect value.
2012-07-24 06:01:47 +00:00
const AVCodecDescriptor *desc = avcodec_descriptor_get(lavc_codec->id);
ctx->intra_only = desc && (desc->props & AV_CODEC_PROP_INTRA_ONLY);
ctx->codec_timebase = mp_get_codec_timebase(ctx->codec);
// This decoder does not read pkt_timebase correctly yet.
if (strstr(lavc_codec->name, "_mmal"))
ctx->codec_timebase = (AVRational){1, 1000000};
ctx->hwdec_failed = false;
ctx->hwdec_request_reinit = false;
ctx->avctx = avcodec_alloc_context3(lavc_codec);
AVCodecContext *avctx = ctx->avctx;
2014-12-12 16:28:22 +00:00
if (!ctx->avctx)
goto error;
avctx->codec_type = AVMEDIA_TYPE_VIDEO;
avctx->codec_id = lavc_codec->id;
avctx->pkt_timebase = ctx->codec_timebase;
ctx->pic = av_frame_alloc();
2014-12-12 16:28:22 +00:00
if (!ctx->pic)
goto error;
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
ctx->avpkt = av_packet_alloc();
if (!ctx->avpkt)
goto error;
if (ctx->use_hwdec) {
avctx->opaque = vd;
avctx->thread_count = 1;
avctx->hwaccel_flags |= AV_HWACCEL_FLAG_IGNORE_LEVEL;
if (!lavc_param->check_hw_profile)
avctx->hwaccel_flags |= AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH;
#ifdef AV_HWACCEL_FLAG_UNSAFE_OUTPUT
/*
* This flag primarily exists for nvdec which has a very limited
* output frame pool, which can get exhausted if consumers don't
* release frames quickly. However, as an implementation
* requirement, we have to copy the frames anyway, so we don't
* need this extra implicit copy.
*/
avctx->hwaccel_flags |= AV_HWACCEL_FLAG_UNSAFE_OUTPUT;
#endif
if (ctx->hwdec.use_hw_device) {
if (ctx->hwdec_dev)
avctx->hw_device_ctx = av_buffer_ref(ctx->hwdec_dev);
if (!avctx->hw_device_ctx)
goto error;
}
if (ctx->hwdec.use_hw_frames) {
if (!ctx->hwdec_dev)
goto error;
}
if (ctx->hwdec.pix_fmt != AV_PIX_FMT_NONE)
avctx->get_format = get_format_hwdec;
// Some APIs benefit from this, for others it's additional bloat.
if (ctx->hwdec.copying)
ctx->max_delay_queue = HWDEC_DELAY_QUEUE_COUNT;
ctx->hw_probing = true;
} else {
mp_set_avcodec_threads(vd->log, avctx, lavc_param->threads);
}
if (!ctx->use_hwdec && ctx->vo && lavc_param->dr) {
avctx->opaque = vd;
avctx->get_buffer2 = get_buffer2_direct;
}
avctx->flags |= lavc_param->bitexact ? AV_CODEC_FLAG_BITEXACT : 0;
avctx->flags2 |= lavc_param->fast ? AV_CODEC_FLAG2_FAST : 0;
if (lavc_param->show_all)
avctx->flags |= AV_CODEC_FLAG_OUTPUT_CORRUPT;
avctx->skip_loop_filter = lavc_param->skip_loop_filter;
avctx->skip_idct = lavc_param->skip_idct;
avctx->skip_frame = lavc_param->skip_frame;
avctx->apply_cropping = lavc_param->apply_cropping;
if (lavc_codec->id == AV_CODEC_ID_H264 && lavc_param->old_x264)
av_opt_set(avctx, "x264_build", "150", AV_OPT_SEARCH_CHILDREN);
switch(ctx->opts->film_grain) {
case 0: /*CPU*/
// default lavc flags handle film grain within the decoder.
break;
case 1: /*GPU*/
if (!ctx->vo ||
(ctx->vo && !(ctx->vo->driver->caps & VO_CAP_FILM_GRAIN))) {
MP_MSG(vd, ctx->vo ? MSGL_WARN : MSGL_V,
"GPU film grain requested, but VO %s, expect wrong output.\n",
ctx->vo ?
"does not support applying film grain" :
"is not available at decoder initialization to verify support");
}
avctx->export_side_data |= AV_CODEC_EXPORT_DATA_FILM_GRAIN;
break;
default:
if (ctx->vo && (ctx->vo->driver->caps & VO_CAP_FILM_GRAIN))
avctx->export_side_data |= AV_CODEC_EXPORT_DATA_FILM_GRAIN;
break;
}
mp_set_avopts(vd->log, avctx, lavc_param->avopts);
// Do this after the above avopt handling in case it changes values
ctx->skip_frame = avctx->skip_frame;
if (mp_set_avctx_codec_headers(avctx, c) < 0) {
MP_ERR(vd, "Could not set codec parameters.\n");
goto error;
core: redo how codecs are mapped, remove codecs.conf Use codec names instead of FourCCs to identify codecs. Rewrite how codecs are selected and initialized. Now each decoder exports a list of decoders (and the codec it supports) via add_decoders(). The order matters, and the first decoder for a given decoder is preferred over the other decoders. E.g. all ad_mpg123 decoders are preferred over ad_lavc, because it comes first in the mpcodecs_ad_drivers array. Likewise, decoders within ad_lavc that are enumerated first by libavcodec (using av_codec_next()) are preferred. (This is actually critical to select h264 software decoding by default instead of vdpau. libavcodec and ffmpeg/avconv use the same method to select decoders by default, so we hope this is sane.) The codec names follow libavcodec's codec names as defined by AVCodecDescriptor.name (see libavcodec/codec_desc.c). Some decoders have names different from the canonical codec name. The AVCodecDescriptor API is relatively new, so we need a compatibility layer for older libavcodec versions for codec names that are referenced internally, and which are different from the decoder name. (Add a configure check for that, because checking versions is getting way too messy.) demux/codec_tags.c is generated from the former codecs.conf (minus "special" decoders like vdpau, and excluding the mappings that are the same as the mappings libavformat's exported RIFF tables). It contains all the mappings from FourCCs to codec name. This is needed for demux_mkv, demux_mpg, demux_avi and demux_asf. demux_lavf will set the codec as determined by libavformat, while the other demuxers have to do this on their own, using the mp_set_audio/video_codec_from_tag() functions. Note that the sh_audio/video->format members don't uniquely identify the codec anymore, and sh->codec takes over this role. Replace the --ac/--vc/--afm/--vfm with new --vd/--ad options, which provide cover the functionality of the removed switched. Note: there's no CODECS_FLAG_FLIP flag anymore. This means some obscure container/video combinations (e.g. the sample Film_200_zygo_pro.mov) are played flipped. ffplay/avplay doesn't handle this properly either, so we don't care and blame ffmeg/libav instead.
2013-02-09 14:15:19 +00:00
}
/* open it */
if (avcodec_open2(avctx, lavc_codec, NULL) < 0)
goto error;
// Sometimes, the first packet contains information required for correct
// decoding of the rest of the stream. The only currently known case is the
// x264 build number (encoded in a SEI element), needed to enable a
// workaround for broken 4:4:4 streams produced by older x264 versions.
if (lavc_codec->id == AV_CODEC_ID_H264 && c->first_packet) {
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
mp_set_av_packet(ctx->avpkt, c->first_packet, &ctx->codec_timebase);
avcodec_send_packet(avctx, ctx->avpkt);
avcodec_receive_frame(avctx, ctx->pic);
av_frame_unref(ctx->pic);
avcodec_flush_buffers(ctx->avctx);
}
return;
error:
MP_ERR(vd, "Could not open codec.\n");
uninit_avctx(vd);
}
static void reset_avctx(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
if (ctx->avctx && avcodec_is_open(ctx->avctx))
avcodec_flush_buffers(ctx->avctx);
ctx->flushing = false;
ctx->hwdec_request_reinit = false;
}
static void flush_all(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
for (int n = 0; n < ctx->num_delay_queue; n++)
talloc_free(ctx->delay_queue[n]);
ctx->num_delay_queue = 0;
for (int n = 0; n < ctx->num_sent_packets; n++)
talloc_free(ctx->sent_packets[n]);
ctx->num_sent_packets = 0;
for (int n = 0; n < ctx->num_requeue_packets; n++)
talloc_free(ctx->requeue_packets[n]);
ctx->num_requeue_packets = 0;
reset_avctx(vd);
}
static void uninit_avctx(struct mp_filter *vd)
2011-10-22 00:51:37 +00:00
{
vd_ffmpeg_ctx *ctx = vd->priv;
flush_all(vd);
av_frame_free(&ctx->pic);
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
mp_free_av_packet(&ctx->avpkt);
av_buffer_unref(&ctx->cached_hw_frames_ctx);
avcodec_free_context(&ctx->avctx);
av_buffer_unref(&ctx->hwdec_dev);
2015-05-28 19:52:04 +00:00
ctx->hwdec_failed = false;
ctx->hwdec_fail_count = 0;
ctx->max_delay_queue = 0;
ctx->hw_probing = false;
ctx->hwdec = (struct hwdec_info){0};
ctx->use_hwdec = false;
}
static int init_generic_hwaccel(struct mp_filter *vd, enum AVPixelFormat hw_fmt)
{
struct lavc_ctx *ctx = vd->priv;
AVBufferRef *new_frames_ctx = NULL;
if (!ctx->hwdec.use_hw_frames)
return 0;
if (!ctx->hwdec_dev) {
MP_ERR(ctx, "Missing device context.\n");
goto error;
}
if (avcodec_get_hw_frames_parameters(ctx->avctx,
ctx->hwdec_dev, hw_fmt, &new_frames_ctx) < 0)
{
MP_VERBOSE(ctx, "Hardware decoding of this stream is unsupported?\n");
goto error;
}
AVHWFramesContext *new_fctx = (void *)new_frames_ctx->data;
if (ctx->opts->hwdec_image_format)
new_fctx->sw_format = imgfmt2pixfmt(ctx->opts->hwdec_image_format);
// 1 surface is already included by libavcodec. The field is 0 if the
// hwaccel supports dynamic surface allocation.
if (new_fctx->initial_pool_size)
new_fctx->initial_pool_size += ctx->opts->hwdec_extra_frames - 1;
const struct hwcontext_fns *fns =
hwdec_get_hwcontext_fns(new_fctx->device_ctx->type);
if (fns && fns->refine_hwframes)
fns->refine_hwframes(new_frames_ctx);
// We might be able to reuse a previously allocated frame pool.
if (ctx->cached_hw_frames_ctx) {
AVHWFramesContext *old_fctx = (void *)ctx->cached_hw_frames_ctx->data;
if (new_fctx->format != old_fctx->format ||
new_fctx->sw_format != old_fctx->sw_format ||
new_fctx->width != old_fctx->width ||
new_fctx->height != old_fctx->height ||
new_fctx->initial_pool_size != old_fctx->initial_pool_size)
av_buffer_unref(&ctx->cached_hw_frames_ctx);
}
if (!ctx->cached_hw_frames_ctx) {
if (av_hwframe_ctx_init(new_frames_ctx) < 0) {
MP_ERR(ctx, "Failed to allocate hw frames.\n");
goto error;
}
ctx->cached_hw_frames_ctx = new_frames_ctx;
new_frames_ctx = NULL;
}
ctx->avctx->hw_frames_ctx = av_buffer_ref(ctx->cached_hw_frames_ctx);
if (!ctx->avctx->hw_frames_ctx)
goto error;
av_buffer_unref(&new_frames_ctx);
return 0;
error:
av_buffer_unref(&new_frames_ctx);
av_buffer_unref(&ctx->cached_hw_frames_ctx);
return -1;
}
static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
const enum AVPixelFormat *fmt)
{
struct mp_filter *vd = avctx->opaque;
vd_ffmpeg_ctx *ctx = vd->priv;
MP_VERBOSE(vd, "Pixel formats supported by decoder:");
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++)
MP_VERBOSE(vd, " %s", av_get_pix_fmt_name(fmt[i]));
MP_VERBOSE(vd, "\n");
const char *profile = avcodec_profile_name(avctx->codec_id, avctx->profile);
MP_VERBOSE(vd, "Codec profile: %s (0x%x)\n", profile ? profile : "unknown",
avctx->profile);
assert(ctx->use_hwdec);
ctx->hwdec_request_reinit |= ctx->hwdec_failed;
ctx->hwdec_failed = false;
enum AVPixelFormat select = AV_PIX_FMT_NONE;
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
if (ctx->hwdec.pix_fmt == fmt[i]) {
if (init_generic_hwaccel(vd, fmt[i]) < 0)
break;
select = fmt[i];
break;
vdpau: split off decoder parts, use "new" libavcodec vdpau hwaccel API Move the decoder parts from vo_vdpau.c to a new file vdpau_old.c. This file is named so because because it's written against the "old" libavcodec vdpau pseudo-decoder (e.g. "h264_vdpau"). Add support for the "new" libavcodec vdpau support. This was recently added and replaces the "old" vdpau parts. (In fact, Libav is about to deprecate and remove the "old" API without deprecation grace period, so we have to support it now. Moreover, there will probably be no Libav release which supports both, so the transition is even less smooth than we could hope, and we have to support both the old and new API.) Whether the old or new API is used is checked by a configure test: if the new API is found, it is used, otherwise the old API is assumed. Some details might be handled differently. Especially display preemption is a bit problematic with the "new" libavcodec vdpau support: it wants to keep a pointer to a specific vdpau API function (which can be driver specific, because preemption might switch drivers). Also, surface IDs are now directly stored in AVFrames (and mp_images), so they can't be forced to VDP_INVALID_HANDLE on preemption. (This changes even with older libavcodec versions, because mp_image always uses the newer representation to make vo_vdpau.c simpler.) Decoder initialization in the new code tries to deal with codec profiles, while the old code always uses the highest profile per codec. Surface allocation changes. Since the decoder won't call config() in vo_vdpau.c on video size change anymore, we allow allocating surfaces of arbitrary size instead of locking it to what the VO was configured. The non-hwdec code also has slightly different allocation behavior now. Enabling the old vdpau special decoders via e.g. --vd=lavc:h264_vdpau doesn't work anymore (a warning suggesting the --hwdec option is printed instead).
2013-07-27 23:49:45 +00:00
}
}
if (select == AV_PIX_FMT_NONE) {
ctx->hwdec_failed = true;
select = avcodec_default_get_format(avctx, fmt);
}
const char *name = av_get_pix_fmt_name(select);
MP_VERBOSE(vd, "Requesting pixfmt '%s' from decoder.\n", name ? name : "-");
return select;
}
static int get_buffer2_direct(AVCodecContext *avctx, AVFrame *pic, int flags)
{
struct mp_filter *vd = avctx->opaque;
vd_ffmpeg_ctx *p = vd->priv;
2023-10-21 02:55:41 +00:00
mp_mutex_lock(&p->dr_lock);
int w = pic->width;
int h = pic->height;
int linesize_align[AV_NUM_DATA_POINTERS] = {0};
avcodec_align_dimensions2(avctx, &w, &h, linesize_align);
// We assume that different alignments are just different power-of-2s.
// Thus, a higher alignment always satisfies a lower alignment.
video: generally try to align image data on 64 bytes Generally, using x86 SIMD efficiently (or crash-free) requires aligning all data on boundaries of 16, 32, or 64 (depending on instruction set used). 64 bytes is needed or AVX-512, 32 for old AVX, 16 for SSE. Both FFmpeg and zimg usually require aligned data for this reason. FFmpeg is very unclear about alignment. Yes, it requires you to align data pointers and strides. No, it doesn't tell you how much, except sometimes (libavcodec has a legacy-looking avcodec_align_dimensions2() API function, that requires a heavy-weight AVCodecContext as argument). Sometimes, FFmpeg will take a shit on YOUR and ITS OWN alignment. For example, vf_crop will randomly reduce alignment of data pointers, depending on the crop parameters. On the other hand, some libavfilter filters or libavcodec encoders may randomly crash if they get the wrong alignment. I have no idea how this thing works at all. FFmpeg usually doesn't seem to signal alignment internal anywhere, and usually leaves it to av_malloc() etc. to allocate with proper alignment. libavutil/mem.c currently has a ALIGN define, which is set to 64 if FFmpeg is built with AVX-512 support, or as low as 16 if built without any AVX support. The really funny thing is that a normal FFmpeg build will e.g. align tiny string allocations to 64 bytes, even if the machine does not support AVX at all. For zimg use (in a later commit), we also want guaranteed alignment. Modern x86 should actually not be much slower at unaligned accesses, but that doesn't help. zimg's dumb intrinsic code apparently randomly chooses between aligned or unaligned accesses (depending on compiler, I guess), and on some CPUs these can even cause crashes. So just treat the requirement to align as a fact of life. All this means that we should probably make sure our own allocations are 64 bit aligned. This still doesn't guarantee alignment in all cases, but it's slightly better than before. This also makes me wonder whether we should always override libavcodec's buffer pool, just so we have a guaranteed alignment. Currently, we only do that if --vd-lavc-dr is used (and if that actually works). On the other hand, it always uses DR on my machine, so who cares.
2019-07-15 01:06:47 +00:00
int stride_align = MP_IMAGE_BYTE_ALIGN;
for (int n = 0; n < AV_NUM_DATA_POINTERS; n++)
stride_align = MPMAX(stride_align, linesize_align[n]);
// Note: texel sizes may be NPOT, so use full lcm instead of max
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
if (!(desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)) {
for (int n = 0; n < desc->nb_components; n++)
stride_align = mp_lcm(stride_align, desc->comp[n].step);
}
int imgfmt = pixfmt2imgfmt(pic->format);
if (!imgfmt)
goto fallback;
if (p->dr_failed)
goto fallback;
// (For simplicity, we realloc on any parameter change, instead of trying
// to be clever.)
if (stride_align != p->dr_stride_align || w != p->dr_w || h != p->dr_h ||
imgfmt != p->dr_imgfmt)
{
mp_image_pool_clear(p->dr_pool);
p->dr_imgfmt = imgfmt;
p->dr_w = w;
p->dr_h = h;
p->dr_stride_align = stride_align;
MP_DBG(p, "DR parameter change to %dx%d %s align=%d\n", w, h,
mp_imgfmt_to_name(imgfmt), stride_align);
}
struct mp_image *img = mp_image_pool_get_no_alloc(p->dr_pool, imgfmt, w, h);
if (!img) {
bool host_cached = p->opts->dr == -1; // auto
int dr_flags = host_cached ? VO_DR_FLAG_HOST_CACHED : 0;
MP_DBG(p, "Allocating new%s DR image...\n", host_cached ? " (host-cached)" : "");
img = vo_get_image(p->vo, imgfmt, w, h, stride_align, dr_flags);
if (!img) {
MP_DBG(p, "...failed..\n");
goto fallback;
}
// Now make the mp_image part of the pool. This requires doing magic to
// the image, so just add it to the pool and get it back to avoid
// dealing with magic ourselves. (Normally this never fails.)
mp_image_pool_add(p->dr_pool, img);
img = mp_image_pool_get_no_alloc(p->dr_pool, imgfmt, w, h);
if (!img)
goto fallback;
}
// get_buffer2 callers seem very unappreciative of overwriting pic with a
// new reference. The AVCodecContext.get_buffer2 comments tell us exactly
// what we should do, so follow that.
for (int n = 0; n < 4; n++) {
pic->data[n] = img->planes[n];
pic->linesize[n] = img->stride[n];
pic->buf[n] = img->bufs[n];
img->bufs[n] = NULL;
}
talloc_free(img);
2023-10-21 02:55:41 +00:00
mp_mutex_unlock(&p->dr_lock);
return 0;
fallback:
if (!p->dr_failed)
MP_VERBOSE(p, "DR failed - disabling.\n");
p->dr_failed = true;
2023-10-21 02:55:41 +00:00
mp_mutex_unlock(&p->dr_lock);
return avcodec_default_get_buffer2(avctx, pic, flags);
}
static void prepare_decoding(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx;
struct vd_lavc_params *opts = ctx->opts;
if (!avctx)
return;
int drop = ctx->framedrop_flags;
if (drop == 1) {
avctx->skip_frame = opts->framedrop; // normal framedrop
} else if (drop == 2) {
avctx->skip_frame = AVDISCARD_NONREF; // hr-seek framedrop
// Can be much more aggressive for true intra codecs.
if (ctx->intra_only)
avctx->skip_frame = AVDISCARD_ALL;
} else {
avctx->skip_frame = ctx->skip_frame; // normal playback
}
if (ctx->hwdec_request_reinit)
reset_avctx(vd);
}
static void handle_err(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
struct vd_lavc_params *opts = ctx->opts;
MP_WARN(vd, "Error while decoding frame%s!\n",
ctx->use_hwdec ? " (hardware decoding)" : "");
if (ctx->use_hwdec) {
ctx->hwdec_fail_count += 1;
if (ctx->hwdec_fail_count >= opts->software_fallback)
ctx->hwdec_failed = true;
}
}
static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx;
if (ctx->num_requeue_packets && ctx->requeue_packets[0] != pkt)
return AVERROR(EAGAIN); // cannot consume the packet
if (ctx->hwdec_failed)
return AVERROR(EAGAIN);
if (!ctx->avctx)
return AVERROR_EOF;
prepare_decoding(vd);
if (avctx->skip_frame == AVDISCARD_ALL)
return 0;
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
mp_set_av_packet(ctx->avpkt, pkt, &ctx->codec_timebase);
ffmpeg: update to handle deprecation of `av_init_packet` This has been a long standing annoyance - ffmpeg is removing sizeof(AVPacket) from the API which means you cannot stack-allocate AVPacket anymore. However, that is something we take advantage of because we use short-lived AVPackets to bridge from native mpv packets in our main decoding paths. We don't think that switching these to `av_packet_alloc` is desirable, given the cost of heap allocation, so this change takes a different approach - allocating a single packet in the relevant context and reusing it over and over. That's fairly straight-forward, with the main caveat being that re-initialising the packet is unintuitive. There is no function that does exactly what we need (what `av_init_packet` did). The closest is `av_packet_unref`, which additionally frees buffers and side-data. However, we don't copy those things - we just assign them in from our own packet, so we have to explicitly clear the pointers before calling `av_packet_unref`. But at least we can make a wrapper function for that. The weirdest part of the change is the handling of the vtt subtitle conversion. This requires two packets, so I had to pre-allocate two in the context struct. That sounds excessive, but if allocating the primary packet is too expensive, then allocating the secondary one for vtt subtitles must also be too expensive. This change is not conditional as heap allocated AVPackets were available for years and years before the deprecation.
2022-11-29 19:15:16 +00:00
int ret = avcodec_send_packet(avctx, pkt ? ctx->avpkt : NULL);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
if (ctx->hw_probing && ctx->num_sent_packets < 32 &&
ctx->opts->software_fallback <= 32)
{
pkt = pkt ? demux_copy_packet(pkt) : NULL;
MP_TARRAY_APPEND(ctx, ctx->sent_packets, ctx->num_sent_packets, pkt);
}
if (ret < 0)
handle_err(vd);
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
}
static void send_queued_packet(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
assert(ctx->num_requeue_packets);
if (send_packet(vd, ctx->requeue_packets[0]) != AVERROR(EAGAIN)) {
talloc_free(ctx->requeue_packets[0]);
MP_TARRAY_REMOVE_AT(ctx->requeue_packets, ctx->num_requeue_packets, 0);
}
}
// Returns whether decoder is still active (!EOF state).
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
static int decode_frame(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx;
if (!avctx || ctx->force_eof)
return AVERROR_EOF;
prepare_decoding(vd);
// Re-send old packets (typically after a hwdec fallback during init).
if (ctx->num_requeue_packets)
send_queued_packet(vd);
int ret = avcodec_receive_frame(avctx, ctx->pic);
if (ret < 0) {
if (ret == AVERROR_EOF) {
// If flushing was initialized earlier and has ended now, make it
// start over in case we get new packets at some point in the future.
// This must take the delay queue into account, so avctx returns EOF
// until the delay queue has been drained.
if (!ctx->num_delay_queue)
reset_avctx(vd);
} else if (ret == AVERROR(EAGAIN)) {
// just retry after caller writes a packet
} else {
handle_err(vd);
}
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
}
mp_codec_info_from_av(avctx, ctx->codec);
// If something was decoded successfully, it must return a frame with valid
// data.
assert(ctx->pic->buf[0]);
struct mp_image *mpi = mp_image_from_av_frame(ctx->pic);
if (!mpi) {
av_frame_unref(ctx->pic);
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
}
if (mpi->imgfmt == IMGFMT_CUDA && !mpi->planes[0]) {
MP_ERR(vd, "CUDA frame without data. This is a FFmpeg bug.\n");
talloc_free(mpi);
handle_err(vd);
return AVERROR_BUG;
}
ctx->hwdec_fail_count = 0;
mpi->pts = mp_pts_from_av(ctx->pic->pts, &ctx->codec_timebase);
mpi->dts = mp_pts_from_av(ctx->pic->pkt_dts, &ctx->codec_timebase);
mpi->pkt_duration = mp_pts_from_av(ctx->pic->duration, &ctx->codec_timebase);
av_frame_unref(ctx->pic);
MP_TARRAY_APPEND(ctx, ctx->delay_queue, ctx->num_delay_queue, mpi);
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
}
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
static int receive_frame(struct mp_filter *vd, struct mp_frame *out_frame)
{
vd_ffmpeg_ctx *ctx = vd->priv;
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
int ret = decode_frame(vd);
if (ctx->hwdec_failed) {
// Failed hardware decoding? Try the next one, and eventually software.
struct demux_packet **pkts = ctx->sent_packets;
int num_pkts = ctx->num_sent_packets;
ctx->sent_packets = NULL;
ctx->num_sent_packets = 0;
/*
* We repeatedly force_fallback until we get an avctx, because there are
* certain hwdecs that are really full decoders, and so if these fail,
* they also fail to give us a valid avctx, and the early return path
* here will simply give up on decoding completely if there is no
* decoder. We should never hit an infinite loop as the hwdec list is
* finite and we will eventually exhaust it and fall back to software
* decoding (and in practice, most hwdecs are hwaccels and so the
* decoder will successfully init even if the hwaccel fails later.)
*/
do {
force_fallback(vd);
} while (!ctx->avctx);
ctx->requeue_packets = pkts;
ctx->num_requeue_packets = num_pkts;
return 0; // force retry
}
if (ret == AVERROR(EAGAIN) && ctx->num_requeue_packets)
return 0; // force retry, so send_queued_packet() gets called
if (ctx->num_delay_queue <= ctx->max_delay_queue && ret != AVERROR_EOF)
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
return ret;
if (!ctx->num_delay_queue)
return ret;
struct mp_image *res = ctx->delay_queue[0];
MP_TARRAY_REMOVE_AT(ctx->delay_queue, ctx->num_delay_queue, 0);
res = res ? mp_img_swap_to_native(res) : NULL;
if (!res)
return AVERROR_UNKNOWN;
if (ctx->use_hwdec && ctx->hwdec.copying && res->hwctx) {
struct mp_image *sw = mp_image_hw_download(res, ctx->hwdec_swpool);
mp_image_unrefp(&res);
res = sw;
if (!res) {
MP_ERR(vd, "Could not copy back hardware decoded frame.\n");
ctx->hwdec_fail_count = INT_MAX - 1; // force fallback
handle_err(vd);
return AVERROR_UNKNOWN;
}
}
if (!ctx->hwdec_notified) {
if (ctx->use_hwdec) {
MP_INFO(vd, "Using hardware decoding (%s).\n",
ctx->hwdec.method_name);
} else {
MP_VERBOSE(vd, "Using software decoding.\n");
}
ctx->hwdec_notified = true;
}
if (ctx->hw_probing) {
for (int n = 0; n < ctx->num_sent_packets; n++)
talloc_free(ctx->sent_packets[n]);
ctx->num_sent_packets = 0;
ctx->hw_probing = false;
}
*out_frame = MAKE_FRAME(MP_FRAME_VIDEO, res);
return 0;
}
static int control(struct mp_filter *vd, enum dec_ctrl cmd, void *arg)
{
vd_ffmpeg_ctx *ctx = vd->priv;
switch (cmd) {
case VDCTRL_SET_FRAMEDROP:
ctx->framedrop_flags = *(int *)arg;
return CONTROL_TRUE;
case VDCTRL_CHECK_FORCED_EOF: {
*(bool *)arg = ctx->force_eof;
return CONTROL_TRUE;
}
video: approximate AVI timestamps via DTS handling Until now (and in mplayer traditionally), avi timestamps were handled with a timestamp FIFO. AVI timestamps are essentially just strictly increasing frame numbers and are not reordered like normal timestamps. Limiting the FIFO is required because frames can be dropped. To make it worse, frame dropping can't be distinguished from the decoder not returning output due to increasing the buffering required for B-frames. ("Measuring" the buffering at playback start seems like an interesting idea, but won't work as the buffering could be increased mid-playback.) Another problem are skipped frames (packets with data, but which do not contain a video frame). Besides dropped and skipped frames, there is the problem that we can't always know the delay. External decoders like MMAL are not going to tell us. (And later perhaps others, like direct VideoToolbox usage.) In general, this works not-well enough that I prefer the solution of passing through AVI timestamps as DTS. This is slightly incorrect, because most decoders treat DTS as mpeg-style timestamps, which already include a b-frame delay, and thus will be shifted by a few frames. This means there will be a problem with A/V sync in some situations. Note that the FFmpeg AVI demuxer shifts timestamps by an additional amount (which increases after the first seek!?!?), which makes the situation worse. It works well with VfW-muxed Matroska files, though. On RPI, the first X timestamps are broken until the MMAL decoder "locks on".
2016-02-11 15:01:11 +00:00
case VDCTRL_GET_BFRAMES: {
AVCodecContext *avctx = ctx->avctx;
if (!avctx)
break;
2018-03-01 22:56:56 +00:00
if (ctx->use_hwdec && strcmp(ctx->hwdec.method_name, "mmal") == 0)
break; // MMAL has arbitrary buffering, thus unknown
video: approximate AVI timestamps via DTS handling Until now (and in mplayer traditionally), avi timestamps were handled with a timestamp FIFO. AVI timestamps are essentially just strictly increasing frame numbers and are not reordered like normal timestamps. Limiting the FIFO is required because frames can be dropped. To make it worse, frame dropping can't be distinguished from the decoder not returning output due to increasing the buffering required for B-frames. ("Measuring" the buffering at playback start seems like an interesting idea, but won't work as the buffering could be increased mid-playback.) Another problem are skipped frames (packets with data, but which do not contain a video frame). Besides dropped and skipped frames, there is the problem that we can't always know the delay. External decoders like MMAL are not going to tell us. (And later perhaps others, like direct VideoToolbox usage.) In general, this works not-well enough that I prefer the solution of passing through AVI timestamps as DTS. This is slightly incorrect, because most decoders treat DTS as mpeg-style timestamps, which already include a b-frame delay, and thus will be shifted by a few frames. This means there will be a problem with A/V sync in some situations. Note that the FFmpeg AVI demuxer shifts timestamps by an additional amount (which increases after the first seek!?!?), which makes the situation worse. It works well with VfW-muxed Matroska files, though. On RPI, the first X timestamps are broken until the MMAL decoder "locks on".
2016-02-11 15:01:11 +00:00
*(int *)arg = avctx->has_b_frames;
return CONTROL_TRUE;
}
case VDCTRL_GET_HWDEC: {
*(char **)arg = ctx->use_hwdec ? ctx->hwdec.method_name : NULL;
return CONTROL_TRUE;
}
case VDCTRL_FORCE_HWDEC_FALLBACK:
if (ctx->use_hwdec) {
force_fallback(vd);
return ctx->avctx ? CONTROL_OK : CONTROL_ERROR;
}
return CONTROL_FALSE;
case VDCTRL_REINIT:
reinit(vd);
return CONTROL_TRUE;
}
return CONTROL_UNKNOWN;
}
static void vd_lavc_process(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
lavc_process(vd, &ctx->state, send_packet, receive_frame);
}
static void vd_lavc_reset(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
flush_all(vd);
ad_lavc, vd_lavc: return full error codes to shared decoder loop ad_lavc and vd_lavc use the lavc_process() helper to translate the FFmpeg push/pull API to the internal filter API (which completely mismatch, even though I'm responsible for both, just fucking kill me). This interface was "slightly" too tight. It returned only a bool indicating "progress", which was not enough to handle some cases (see following commit). While we're at it, move all state into a struct. This is only a single bool, but we get the chance to add more if needed. This fixes mpv falling asleep if decoding returns an error during draining. If decoding fails when we already sent EOF, the state machine stopped making progress. This left mpv just sitting around and doing nothing. A test case can be created with: echo $RANDOM >> image.png This makes libavformat read a proper packet plus a packet of garbage. libavcodec will decode a frame, and then return an error code. The lavc_process() wrapper could not deal with this, because there was no way to differentiate between "retry" and "send new packet". Normally, it would send a new packet, so decoding would make progress anyway. If there was "progress", we couldn't just retry, because it'd retry forever. This is made worse by the fact that it tries to decode at least two frames before starting display, meaning it will "sit around and do nothing" before the picture is displayed. Change it so that on error return, "receiving" a frame is retried. This will make it return the EOF, so everything works properly. This is a high-risk change, because all these funny bullshit exceptions for hardware decoding are in the way, and I didn't retest them. For example, if hardware decoding is enabled, it keeps a list of packets, that are fed into the decoder again if hardware decoding fails, and a software fallback is performed. Another case of horrifying accidental complexity. Fixes: #6618
2019-10-24 16:40:46 +00:00
ctx->state = (struct lavc_state){0};
ctx->framedrop_flags = 0;
}
static void vd_lavc_destroy(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
uninit_avctx(vd);
2023-10-21 02:55:41 +00:00
mp_mutex_destroy(&ctx->dr_lock);
}
static const struct mp_filter_info vd_lavc_filter = {
.name = "vd_lavc",
.priv_size = sizeof(vd_ffmpeg_ctx),
.process = vd_lavc_process,
.reset = vd_lavc_reset,
.destroy = vd_lavc_destroy,
};
static struct mp_decoder *create(struct mp_filter *parent,
struct mp_codec_params *codec,
const char *decoder)
{
struct mp_filter *vd = mp_filter_create(parent, &vd_lavc_filter);
if (!vd)
return NULL;
mp_filter_add_pin(vd, MP_PIN_IN, "in");
mp_filter_add_pin(vd, MP_PIN_OUT, "out");
vd->log = mp_log_new(vd, parent->log, NULL);
vd_ffmpeg_ctx *ctx = vd->priv;
ctx->log = vd->log;
ctx->opts_cache = m_config_cache_alloc(ctx, vd->global, &vd_lavc_conf);
ctx->opts = ctx->opts_cache->opts;
ctx->codec = codec;
ctx->decoder = talloc_strdup(ctx, decoder);
ctx->hwdec_swpool = mp_image_pool_new(ctx);
ctx->dr_pool = mp_image_pool_new(ctx);
ctx->public.f = vd;
ctx->public.control = control;
2023-10-21 02:55:41 +00:00
mp_mutex_init(&ctx->dr_lock);
// hwdec/DR
struct mp_stream_info *info = mp_filter_find_stream_info(vd);
if (info) {
ctx->hwdec_devs = info->hwdec_devs;
ctx->vo = info->dr_vo;
}
reinit(vd);
if (!ctx->avctx) {
talloc_free(vd);
return NULL;
}
codec->codec_desc = ctx->avctx->codec_descriptor->long_name;
return &ctx->public;
}
core: redo how codecs are mapped, remove codecs.conf Use codec names instead of FourCCs to identify codecs. Rewrite how codecs are selected and initialized. Now each decoder exports a list of decoders (and the codec it supports) via add_decoders(). The order matters, and the first decoder for a given decoder is preferred over the other decoders. E.g. all ad_mpg123 decoders are preferred over ad_lavc, because it comes first in the mpcodecs_ad_drivers array. Likewise, decoders within ad_lavc that are enumerated first by libavcodec (using av_codec_next()) are preferred. (This is actually critical to select h264 software decoding by default instead of vdpau. libavcodec and ffmpeg/avconv use the same method to select decoders by default, so we hope this is sane.) The codec names follow libavcodec's codec names as defined by AVCodecDescriptor.name (see libavcodec/codec_desc.c). Some decoders have names different from the canonical codec name. The AVCodecDescriptor API is relatively new, so we need a compatibility layer for older libavcodec versions for codec names that are referenced internally, and which are different from the decoder name. (Add a configure check for that, because checking versions is getting way too messy.) demux/codec_tags.c is generated from the former codecs.conf (minus "special" decoders like vdpau, and excluding the mappings that are the same as the mappings libavformat's exported RIFF tables). It contains all the mappings from FourCCs to codec name. This is needed for demux_mkv, demux_mpg, demux_avi and demux_asf. demux_lavf will set the codec as determined by libavformat, while the other demuxers have to do this on their own, using the mp_set_audio/video_codec_from_tag() functions. Note that the sh_audio/video->format members don't uniquely identify the codec anymore, and sh->codec takes over this role. Replace the --ac/--vc/--afm/--vfm with new --vd/--ad options, which provide cover the functionality of the removed switched. Note: there's no CODECS_FLAG_FLIP flag anymore. This means some obscure container/video combinations (e.g. the sample Film_200_zygo_pro.mov) are played flipped. ffplay/avplay doesn't handle this properly either, so we don't care and blame ffmeg/libav instead.
2013-02-09 14:15:19 +00:00
static void add_decoders(struct mp_decoder_list *list)
{
mp_add_lavc_decoders(list, AVMEDIA_TYPE_VIDEO);
}
const struct mp_decoder_fns vd_lavc = {
.create = create,
core: redo how codecs are mapped, remove codecs.conf Use codec names instead of FourCCs to identify codecs. Rewrite how codecs are selected and initialized. Now each decoder exports a list of decoders (and the codec it supports) via add_decoders(). The order matters, and the first decoder for a given decoder is preferred over the other decoders. E.g. all ad_mpg123 decoders are preferred over ad_lavc, because it comes first in the mpcodecs_ad_drivers array. Likewise, decoders within ad_lavc that are enumerated first by libavcodec (using av_codec_next()) are preferred. (This is actually critical to select h264 software decoding by default instead of vdpau. libavcodec and ffmpeg/avconv use the same method to select decoders by default, so we hope this is sane.) The codec names follow libavcodec's codec names as defined by AVCodecDescriptor.name (see libavcodec/codec_desc.c). Some decoders have names different from the canonical codec name. The AVCodecDescriptor API is relatively new, so we need a compatibility layer for older libavcodec versions for codec names that are referenced internally, and which are different from the decoder name. (Add a configure check for that, because checking versions is getting way too messy.) demux/codec_tags.c is generated from the former codecs.conf (minus "special" decoders like vdpau, and excluding the mappings that are the same as the mappings libavformat's exported RIFF tables). It contains all the mappings from FourCCs to codec name. This is needed for demux_mkv, demux_mpg, demux_avi and demux_asf. demux_lavf will set the codec as determined by libavformat, while the other demuxers have to do this on their own, using the mp_set_audio/video_codec_from_tag() functions. Note that the sh_audio/video->format members don't uniquely identify the codec anymore, and sh->codec takes over this role. Replace the --ac/--vc/--afm/--vfm with new --vd/--ad options, which provide cover the functionality of the removed switched. Note: there's no CODECS_FLAG_FLIP flag anymore. This means some obscure container/video combinations (e.g. the sample Film_200_zygo_pro.mov) are played flipped. ffplay/avplay doesn't handle this properly either, so we don't care and blame ffmeg/libav instead.
2013-02-09 14:15:19 +00:00
.add_decoders = add_decoders,
};