2010-01-30 16:57:40 +00:00
|
|
|
/*
|
2015-04-13 07:36:54 +00:00
|
|
|
* This file is part of mpv.
|
2010-01-30 16:57:40 +00:00
|
|
|
*
|
2017-09-21 11:50:18 +00:00
|
|
|
* 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
|
2017-10-05 13:54:10 +00:00
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2010-01-30 16:57:40 +00:00
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2010-01-30 16:57:40 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2017-09-21 11:50:18 +00:00
|
|
|
* GNU Lesser General Public License for more details.
|
2010-01-30 16:57:40 +00:00
|
|
|
*
|
2017-09-21 11:50:18 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2010-01-30 16:57:40 +00:00
|
|
|
*/
|
|
|
|
|
2020-03-13 15:49:39 +00:00
|
|
|
#include <float.h>
|
2002-03-06 20:54:43 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
2010-01-20 14:31:13 +00:00
|
|
|
#include <stdbool.h>
|
2002-03-06 20:54:43 +00:00
|
|
|
|
2017-12-01 21:01:54 +00:00
|
|
|
#include <libavcodec/avcodec.h>
|
2022-11-29 19:18:12 +00:00
|
|
|
#include <libavformat/version.h>
|
2012-01-28 11:41:36 +00:00
|
|
|
#include <libavutil/common.h>
|
2017-12-01 21:01:54 +00:00
|
|
|
#include <libavutil/hwcontext.h>
|
2012-01-28 11:41:36 +00:00
|
|
|
#include <libavutil/opt.h>
|
2012-02-01 18:01:16 +00:00
|
|
|
#include <libavutil/intreadwrite.h>
|
2012-12-11 17:16:42 +00:00
|
|
|
#include <libavutil/pixdesc.h>
|
2012-01-28 11:41:36 +00:00
|
|
|
|
2016-01-11 18:03:40 +00:00
|
|
|
#include "mpv_talloc.h"
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/msg.h"
|
2018-05-21 14:05:03 +00:00
|
|
|
#include "options/m_config.h"
|
2013-12-17 01:02:25 +00:00
|
|
|
#include "options/options.h"
|
2023-10-21 02:55:41 +00:00
|
|
|
#include "osdep/threads.h"
|
2014-08-29 10:09:04 +00:00
|
|
|
#include "misc/bstr.h"
|
2013-12-17 01:39:45 +00:00
|
|
|
#include "common/av_common.h"
|
|
|
|
#include "common/codecs.h"
|
2002-03-06 20:54:43 +00:00
|
|
|
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "video/fmt-conversion.h"
|
2002-03-06 20:54:43 +00:00
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
#include "filters/f_decoder_wrapper.h"
|
|
|
|
#include "filters/filter_internal.h"
|
2017-12-01 21:01:54 +00:00
|
|
|
#include "video/hwdec.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "video/img_format.h"
|
2017-12-01 21:01:54 +00:00
|
|
|
#include "video/mp_image.h"
|
|
|
|
#include "video/mp_image_pool.h"
|
2015-12-22 01:35:15 +00:00
|
|
|
#include "demux/demux.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "demux/stheader.h"
|
2013-11-18 17:46:44 +00:00
|
|
|
#include "demux/packet.h"
|
2012-11-09 00:06:43 +00:00
|
|
|
#include "video/csputils.h"
|
2015-02-06 22:20:41 +00:00
|
|
|
#include "video/sws_utils.h"
|
2017-07-23 07:41:51 +00:00
|
|
|
#include "video/out/vo.h"
|
2002-03-06 20:54:43 +00:00
|
|
|
|
2013-12-17 01:02:25 +00:00
|
|
|
#include "options/m_option.h"
|
2002-06-02 12:48:55 +00:00
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void init_avctx(struct mp_filter *vd);
|
|
|
|
static void uninit_avctx(struct mp_filter *vd);
|
2002-07-16 00:56:12 +00:00
|
|
|
|
2017-07-23 07:41:51 +00:00
|
|
|
static int get_buffer2_direct(AVCodecContext *avctx, AVFrame *pic, int flags);
|
2013-11-29 16:39:57 +00:00
|
|
|
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);
|
2012-11-06 14:27:44 +00:00
|
|
|
|
2017-12-01 21:01:54 +00:00
|
|
|
#define HWDEC_DELAY_QUEUE_COUNT 2
|
|
|
|
|
2014-06-10 23:35:39 +00:00
|
|
|
#define OPT_BASE_STRUCT struct vd_lavc_params
|
|
|
|
|
|
|
|
struct vd_lavc_params {
|
2023-02-20 03:32:50 +00:00
|
|
|
bool fast;
|
2022-04-03 12:17:43 +00:00
|
|
|
int film_grain;
|
2023-02-20 03:32:50 +00:00
|
|
|
bool show_all;
|
2014-06-13 00:03:45 +00:00
|
|
|
int skip_loop_filter;
|
|
|
|
int skip_idct;
|
|
|
|
int skip_frame;
|
2014-08-08 22:35:25 +00:00
|
|
|
int framedrop;
|
2014-06-10 23:35:39 +00:00
|
|
|
int threads;
|
2023-02-20 03:32:50 +00:00
|
|
|
bool bitexact;
|
|
|
|
bool old_x264;
|
2023-09-01 10:26:38 +00:00
|
|
|
bool apply_cropping;
|
2023-02-20 03:32:50 +00:00
|
|
|
bool check_hw_profile;
|
2015-10-25 09:45:44 +00:00
|
|
|
int software_fallback;
|
2014-08-02 01:12:09 +00:00
|
|
|
char **avopts;
|
2017-07-23 07:41:51 +00:00
|
|
|
int dr;
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
char **hwdec_api;
|
2018-05-21 14:05:03 +00:00
|
|
|
char *hwdec_codecs;
|
|
|
|
int hwdec_image_format;
|
2019-05-31 18:11:32 +00:00
|
|
|
int hwdec_extra_frames;
|
2014-06-10 23:35:39 +00:00
|
|
|
};
|
|
|
|
|
2014-06-13 00:03:45 +00:00
|
|
|
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}
|
|
|
|
};
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
#define OPT_DISCARD(field) OPT_CHOICE_C(field, discard_names)
|
2014-06-13 00:03:45 +00:00
|
|
|
|
2014-06-10 23:35:39 +00:00
|
|
|
const struct m_sub_options vd_lavc_conf = {
|
|
|
|
.opts = (const m_option_t[]){
|
2023-02-20 03:32:50 +00:00
|
|
|
{"vd-lavc-fast", OPT_BOOL(fast)},
|
2022-04-03 12:17:43 +00:00
|
|
|
{"vd-lavc-film-grain", OPT_CHOICE(film_grain,
|
|
|
|
{"auto", -1}, {"cpu", 0}, {"gpu", 1})},
|
2023-02-20 03:32:50 +00:00
|
|
|
{"vd-lavc-show-all", OPT_BOOL(show_all)},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"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)},
|
2023-02-20 03:32:50 +00:00
|
|
|
{"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)},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"vd-lavc-software-fallback", OPT_CHOICE(software_fallback,
|
|
|
|
{"no", INT_MAX}, {"yes", 1}), M_RANGE(1, INT_MAX)},
|
|
|
|
{"vd-lavc-o", OPT_KEYVALUELIST(avopts)},
|
2023-01-21 14:45:11 +00:00
|
|
|
{"vd-lavc-dr", OPT_CHOICE(dr,
|
|
|
|
{"auto", -1}, {"no", 0}, {"yes", 1})},
|
2023-09-01 10:26:38 +00:00
|
|
|
{"vd-apply-cropping", OPT_BOOL(apply_cropping)},
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
{"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,
|
2024-09-29 13:19:52 +00:00
|
|
|
.flags = M_OPT_OPTIONAL_PARAM | M_OPT_ALLOW_NO | UPDATE_HWDEC},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"hwdec-codecs", OPT_STRING(hwdec_codecs)},
|
2020-04-09 09:20:45 +00:00
|
|
|
{"hwdec-image-format", OPT_IMAGEFORMAT(hwdec_image_format)},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"hwdec-extra-frames", OPT_INT(hwdec_extra_frames), M_RANGE(0, 256)},
|
2014-06-10 23:35:39 +00:00
|
|
|
{0}
|
|
|
|
},
|
|
|
|
.size = sizeof(struct vd_lavc_params),
|
|
|
|
.defaults = &(const struct vd_lavc_params){
|
2022-04-03 12:17:43 +00:00
|
|
|
.film_grain = -1 /*auto*/,
|
2023-02-20 03:32:50 +00:00
|
|
|
.check_hw_profile = true,
|
2015-11-03 13:03:02 +00:00
|
|
|
.software_fallback = 3,
|
2014-06-13 00:03:45 +00:00
|
|
|
.skip_loop_filter = AVDISCARD_DEFAULT,
|
|
|
|
.skip_idct = AVDISCARD_DEFAULT,
|
|
|
|
.skip_frame = AVDISCARD_DEFAULT,
|
2014-08-08 22:35:25 +00:00
|
|
|
.framedrop = AVDISCARD_NONREF,
|
2023-01-21 14:45:11 +00:00
|
|
|
.dr = -1,
|
2023-06-29 22:01:54 +00:00
|
|
|
.hwdec_api = (char *[]){"no", NULL,},
|
2021-11-13 23:32:51 +00:00
|
|
|
.hwdec_codecs = "h264,vc1,hevc,vp8,vp9,av1,prores",
|
2019-05-31 18:11:32 +00:00
|
|
|
// 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,
|
2023-09-09 15:42:45 +00:00
|
|
|
.apply_cropping = true,
|
2014-06-10 23:35:39 +00:00
|
|
|
},
|
2002-06-02 12:48:55 +00:00
|
|
|
};
|
|
|
|
|
2017-12-01 21:01:54 +00:00
|
|
|
struct hwdec_info {
|
|
|
|
char name[64];
|
2018-12-16 12:07:11 +00:00
|
|
|
char method_name[24]; // non-unique name describing the hwdec method
|
2017-12-01 21:01:54 +00:00
|
|
|
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
|
2019-12-24 08:24:22 +00:00
|
|
|
unsigned int flags; // HWDEC_FLAG_*
|
2017-12-01 21:01:54 +00:00
|
|
|
|
|
|
|
// for internal sorting
|
|
|
|
int auto_pos;
|
|
|
|
int rank;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct lavc_ctx {
|
|
|
|
struct mp_log *log;
|
2018-05-21 14:05:03 +00:00
|
|
|
struct m_config_cache *opts_cache;
|
|
|
|
struct vd_lavc_params *opts;
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
struct mp_codec_params *codec;
|
2017-12-01 21:01:54 +00:00
|
|
|
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;
|
2017-12-01 21:01:54 +00:00
|
|
|
bool use_hwdec;
|
|
|
|
struct hwdec_info hwdec; // valid only if use_hwdec==true
|
vd_lavc: try other hwdecs when falling back after an hwdec failure
Today, if hwdec initialisation succeeds, we move on to attempting
decoding, and if decoding fails, we enter a fallback path that will
only do software decoding.
This is suboptimal because some hwdecs and codec combinations can
pass hwdec init, but then fail at hwaccel init, or even frame decoding.
In these situations, we will never attempt other hwdecs in the `auto`
or manually specified lists which might work.
One good example is someone tries to use `vulkan,auto` and tries to
play av1 content. The vulkan decoding will fail at hwaccel init time,
and then fallback to software instead of going through the auto list
which would allow vaapi, nvdec, etc to play the file.
Instead, let's not give up immediately, and try the next hwdec after
a failure, just like we do if hwdec init fails.
The key part of this change is to keep track of the hwdecs we have
tried, so that each time we run through hwdec selection, we don't try
the same one over and over again. If we really get through the whole
list with no success, we will then fall back to software decoding.
Fixes #11865
2023-07-01 17:16:16 +00:00
|
|
|
bstr *attempted_hwdecs;
|
|
|
|
int num_attempted_hwdecs;
|
2017-12-01 21:01:54 +00:00
|
|
|
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;
|
2017-12-01 21:01:54 +00:00
|
|
|
const char *decoder;
|
|
|
|
bool hwdec_failed;
|
|
|
|
bool hwdec_notified;
|
2023-07-12 23:06:33 +00:00
|
|
|
bool force_eof;
|
2017-12-01 21:01:54 +00:00
|
|
|
|
|
|
|
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
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
struct vo *vo;
|
2017-12-01 21:01:54 +00:00
|
|
|
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;
|
2017-12-01 21:01:54 +00:00
|
|
|
bool dr_failed;
|
|
|
|
struct mp_image_pool *dr_pool;
|
|
|
|
int dr_imgfmt, dr_w, dr_h, dr_stride_align;
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
|
|
|
|
struct mp_decoder public;
|
2017-12-01 21:01:54 +00:00
|
|
|
} vd_ffmpeg_ctx;
|
|
|
|
|
2019-12-24 08:24:22 +00:00
|
|
|
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_*
|
|
|
|
};
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
// Things not included in this list will be tried last, in random order.
|
2019-12-24 08:24:22 +00:00
|
|
|
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},
|
2023-06-30 17:09:49 +00:00
|
|
|
{"dxva2-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2019-12-24 08:24:22 +00:00
|
|
|
{"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},
|
2024-06-22 13:41:14 +00:00
|
|
|
{"vulkan", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
|
|
|
{"vulkan-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2019-12-24 08:24:22 +00:00
|
|
|
{"vdpau", HWDEC_FLAG_AUTO},
|
|
|
|
{"vdpau-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2023-07-02 03:15:53 +00:00
|
|
|
{"drm", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
|
|
|
{"drm-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2019-12-24 08:24:22 +00:00
|
|
|
{"mmal", HWDEC_FLAG_AUTO},
|
|
|
|
{"mmal-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2023-02-24 21:59:03 +00:00
|
|
|
{"mediacodec", HWDEC_FLAG_AUTO},
|
|
|
|
{"mediacodec-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
2019-12-24 08:24:22 +00:00
|
|
|
{"videotoolbox", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
|
|
|
{"videotoolbox-copy", HWDEC_FLAG_AUTO | HWDEC_FLAG_WHITELIST},
|
|
|
|
{0}
|
2016-04-25 10:09:09 +00:00
|
|
|
};
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
static int hwdec_compare(const void *p1, const void *p2)
|
|
|
|
{
|
|
|
|
struct hwdec_info *h1 = (void *)p1;
|
|
|
|
struct hwdec_info *h2 = (void *)p2;
|
2016-09-11 03:12:27 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (h1 == h2)
|
|
|
|
return 0;
|
2016-10-09 16:18:14 +00:00
|
|
|
|
2017-12-02 01:32:41 +00:00
|
|
|
// 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.
|
2017-12-02 01:32:41 +00:00
|
|
|
if (h1->auto_pos != h2->auto_pos)
|
|
|
|
return h1->auto_pos > h2->auto_pos ? 1 : -1;
|
2023-02-24 22:12:22 +00:00
|
|
|
// Put hwdecs without hw_device_ctx last
|
|
|
|
if ((!!h1->lavc_device) != (!!h2->lavc_device))
|
|
|
|
return h1->lavc_device ? -1 : 1;
|
2017-12-02 01:32:41 +00:00
|
|
|
// Fallback sort order to make sorting stable.
|
|
|
|
return h1->rank > h2->rank ? 1 :-1;
|
2017-12-01 20:05:54 +00:00
|
|
|
}
|
2017-02-20 07:39:55 +00:00
|
|
|
|
2017-12-01 23:54:42 +00:00
|
|
|
// (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;
|
2017-12-02 01:32:41 +00:00
|
|
|
info.auto_pos = INT_MAX;
|
2019-12-24 08:24:22 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2017-12-01 23:54:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MP_TARRAY_APPEND(NULL, *infos, *num_infos, info);
|
|
|
|
}
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
static void add_all_hwdec_methods(struct hwdec_info **infos, int *num_infos)
|
|
|
|
{
|
2018-02-12 18:28:30 +00:00
|
|
|
const AVCodec *codec = NULL;
|
|
|
|
void *iter = NULL;
|
2017-12-01 20:05:54 +00:00
|
|
|
while (1) {
|
2018-02-12 18:28:30 +00:00
|
|
|
codec = av_codec_iterate(&iter);
|
2017-12-01 20:05:54 +00:00
|
|
|
if (!codec)
|
|
|
|
break;
|
2017-12-14 18:28:07 +00:00
|
|
|
if (codec->type != AVMEDIA_TYPE_VIDEO || !av_codec_is_decoder(codec))
|
|
|
|
continue;
|
2017-02-20 07:39:55 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
struct hwdec_info info_template = {
|
|
|
|
.pix_fmt = AV_PIX_FMT_NONE,
|
|
|
|
.codec = codec,
|
|
|
|
};
|
2017-03-23 10:06:28 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
const char *wrapper = NULL;
|
2017-12-14 18:28:07 +00:00
|
|
|
if (codec->capabilities & (AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_HYBRID))
|
|
|
|
wrapper = codec->wrapper_name;
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
// 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;
|
2017-03-23 10:06:28 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-12-01 07:13:24 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
// Direct variant.
|
2017-12-01 23:54:42 +00:00
|
|
|
add_hwdec_item(infos, num_infos, info);
|
2017-12-01 07:13:24 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
// 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;
|
|
|
|
}
|
2017-12-01 23:54:42 +00:00
|
|
|
add_hwdec_item(infos, num_infos, info);
|
2017-12-01 20:05:54 +00:00
|
|
|
|
|
|
|
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.
|
2017-12-01 23:54:42 +00:00
|
|
|
add_hwdec_item(infos, num_infos, info);
|
2017-12-01 20:05:54 +00:00
|
|
|
|
|
|
|
// Copy variant.
|
2017-12-01 23:54:42 +00:00
|
|
|
info.copying = true;
|
2017-12-02 20:08:38 +00:00
|
|
|
info.pix_fmt = AV_PIX_FMT_NONE; // trust it can do sw output
|
2017-12-01 23:54:42 +00:00
|
|
|
add_hwdec_item(infos, num_infos, info);
|
2017-12-01 20:05:54 +00:00
|
|
|
|
|
|
|
found_any = true;
|
|
|
|
}
|
|
|
|
}
|
2017-10-31 14:18:57 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (!found_any && wrapper) {
|
|
|
|
// We _know_ there's something supported here, usually outputting
|
|
|
|
// sw surfaces. E.g. mediacodec (before hw_device_ctx support).
|
2017-12-01 17:01:15 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
struct hwdec_info info = info_template;
|
|
|
|
info.copying = true; // probably
|
2017-11-30 20:54:13 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
snprintf(info.method_name, sizeof(info.method_name), "%s", wrapper);
|
2017-12-01 23:54:42 +00:00
|
|
|
add_hwdec_item(infos, num_infos, info);
|
2017-12-01 20:05:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qsort(*infos, *num_infos, sizeof(struct hwdec_info), hwdec_compare);
|
2012-12-11 17:16:42 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static bool hwdec_codec_allowed(struct mp_filter *vd, const char *codec)
|
2013-05-03 19:00:05 +00:00
|
|
|
{
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
bstr s = bstr0(ctx->opts->hwdec_codecs);
|
2013-05-03 19:00:05 +00:00
|
|
|
while (s.len) {
|
|
|
|
bstr item;
|
|
|
|
bstr_split_tok(s, ",", &item, &s);
|
2013-08-11 21:23:12 +00:00
|
|
|
if (bstr_equals0(item, "all") || bstr_equals0(item, codec))
|
2013-05-03 19:00:05 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static AVBufferRef *hwdec_create_dev(struct mp_filter *vd,
|
2017-12-01 20:05:54 +00:00
|
|
|
struct hwdec_info *hwdec,
|
|
|
|
bool autoprobe)
|
2016-04-25 09:28:25 +00:00
|
|
|
{
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2017-12-01 20:05:54 +00:00
|
|
|
assert(hwdec->lavc_device);
|
2016-04-25 09:28:25 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (hwdec->copying) {
|
2017-12-01 07:01:08 +00:00
|
|
|
const struct hwcontext_fns *fns =
|
2017-12-01 20:05:54 +00:00
|
|
|
hwdec_get_hwcontext_fns(hwdec->lavc_device);
|
2017-12-01 07:01:08 +00:00
|
|
|
if (fns && fns->create_dev) {
|
|
|
|
struct hwcontext_create_dev_params params = {
|
|
|
|
.probing = autoprobe,
|
|
|
|
};
|
2017-12-01 20:05:54 +00:00
|
|
|
return fns->create_dev(vd->global, vd->log, ¶ms);
|
2017-12-01 07:01:08 +00:00
|
|
|
} else {
|
2017-12-01 20:05:54 +00:00
|
|
|
AVBufferRef* ref = NULL;
|
|
|
|
av_hwdevice_ctx_create(&ref, hwdec->lavc_device, NULL, NULL, 0);
|
|
|
|
return ref;
|
2017-10-30 17:33:18 +00:00
|
|
|
}
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
} else if (ctx->hwdec_devs) {
|
2022-03-24 21:18:59 +00:00
|
|
|
int imgfmt = pixfmt2imgfmt(hwdec->pix_fmt);
|
2022-03-20 19:31:38 +00:00
|
|
|
struct hwdec_imgfmt_request params = {
|
2022-03-24 21:18:59 +00:00
|
|
|
.imgfmt = imgfmt,
|
2022-03-20 19:31:38 +00:00
|
|
|
.probing = autoprobe,
|
|
|
|
};
|
|
|
|
hwdec_devices_request_for_img_fmt(ctx->hwdec_devs, ¶ms);
|
2022-03-24 21:18:59 +00:00
|
|
|
|
|
|
|
const struct mp_hwdec_ctx *hw_ctx =
|
2024-08-06 03:35:31 +00:00
|
|
|
hwdec_devices_get_by_imgfmt_and_type(ctx->hwdec_devs, imgfmt,
|
|
|
|
hwdec->lavc_device);
|
2023-06-19 18:29:57 +00:00
|
|
|
|
|
|
|
if (hw_ctx && hw_ctx->av_device_ref)
|
|
|
|
return av_buffer_ref(hw_ctx->av_device_ref);
|
2017-02-20 07:39:55 +00:00
|
|
|
}
|
2017-12-01 20:05:54 +00:00
|
|
|
|
2017-02-20 07:39:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
// Select if and which hwdec to use. Also makes sure to get the decode device.
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void select_and_set_hwdec(struct mp_filter *vd)
|
2013-08-11 21:23:12 +00:00
|
|
|
{
|
2016-05-09 17:42:03 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
const char *codec = ctx->codec->codec;
|
2017-12-01 20:05:54 +00:00
|
|
|
|
2018-05-21 14:05:03 +00:00
|
|
|
m_config_cache_update(ctx->opts_cache);
|
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
struct hwdec_info *hwdecs = NULL;
|
|
|
|
int num_hwdecs = 0;
|
|
|
|
add_all_hwdec_methods(&hwdecs, &num_hwdecs);
|
|
|
|
|
|
|
|
char **hwdec_api = ctx->opts->hwdec_api;
|
2024-09-29 19:01:51 +00:00
|
|
|
for (int i = 0; hwdec_api && hwdec_api[i]; i++) {
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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") ||
|
2023-07-02 17:13:42 +00:00
|
|
|
bstr_equals0(opt, "auto-copy-safe") ||
|
|
|
|
bstr_equals0(opt, "yes");
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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;
|
2017-12-01 20:05:54 +00:00
|
|
|
|
vd_lavc: try other hwdecs when falling back after an hwdec failure
Today, if hwdec initialisation succeeds, we move on to attempting
decoding, and if decoding fails, we enter a fallback path that will
only do software decoding.
This is suboptimal because some hwdecs and codec combinations can
pass hwdec init, but then fail at hwaccel init, or even frame decoding.
In these situations, we will never attempt other hwdecs in the `auto`
or manually specified lists which might work.
One good example is someone tries to use `vulkan,auto` and tries to
play av1 content. The vulkan decoding will fail at hwaccel init time,
and then fallback to software instead of going through the auto list
which would allow vaapi, nvdec, etc to play the file.
Instead, let's not give up immediately, and try the next hwdec after
a failure, just like we do if hwdec init fails.
The key part of this change is to keep track of the hwdecs we have
tried, so that each time we run through hwdec selection, we don't try
the same one over and over again. If we really get through the whole
list with no success, we will then fall back to software decoding.
Fixes #11865
2023-07-01 17:16:16 +00:00
|
|
|
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;
|
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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);
|
|
|
|
|
vd_lavc: try other hwdecs when falling back after an hwdec failure
Today, if hwdec initialisation succeeds, we move on to attempting
decoding, and if decoding fails, we enter a fallback path that will
only do software decoding.
This is suboptimal because some hwdecs and codec combinations can
pass hwdec init, but then fail at hwaccel init, or even frame decoding.
In these situations, we will never attempt other hwdecs in the `auto`
or manually specified lists which might work.
One good example is someone tries to use `vulkan,auto` and tries to
play av1 content. The vulkan decoding will fail at hwaccel init time,
and then fallback to software instead of going through the auto list
which would allow vaapi, nvdec, etc to play the file.
Instead, let's not give up immediately, and try the next hwdec after
a failure, just like we do if hwdec init fails.
The key part of this change is to keep track of the hwdecs we have
tried, so that each time we run through hwdec selection, we don't try
the same one over and over again. If we really get through the whole
list with no success, we will then fall back to software decoding.
Fixes #11865
2023-07-01 17:16:16 +00:00
|
|
|
/*
|
|
|
|
* 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)));
|
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
if (hwdec_auto_copy && !hwdec->copying) {
|
|
|
|
MP_VERBOSE(vd, "Not using this for auto-copy.\n");
|
2017-12-01 20:05:54 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-12-02 03:27:02 +00:00
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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");
|
2017-12-02 03:27:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
2017-12-01 20:05:54 +00:00
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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, ¶ms);
|
|
|
|
}
|
|
|
|
}
|
2018-03-07 21:39:51 +00:00
|
|
|
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
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));
|
hwdec: warn on unsupported hwdec option value
Previously, when mpv was invoked with unsupported hwdec value, such
as --hwdec=foobar, there was no indication that it doesn't exist.
The reason it's not validated during options parsing is that the name
is only evaluated when selecting hwdec for actual decoding, by
matching it against runtime list of names from ffmpeg.
Additionally, when selecting hwdec for decoding, matching the name
came after filtering by codec, hence overall never-matched-name did
not necessarily indicate it's unsupported (doesn't exist at all).
Now we check the name before filtering by codec, and when done,
warn if no hwdec with that name exists at all.
This means that an unsupported name will now generate such warning
whenever we try to choose a hwdec, i.e. possibly more than once.
It's much better than no notification at all, and arguably adequate
for a sort of configuration error (linked ffmpeg has no such hwdec
name) which we don't validate during option parsing.
2022-03-06 11:06:21 +00:00
|
|
|
}
|
2017-02-20 07:39:55 +00:00
|
|
|
}
|
vd_lavc: let the user provide a priority list of hwdecs to consider
Today, the only way to make mpv consider multiple hwdecs and pick the
first one that works is to use one of the `auto` modes. But the list
that is considered in those cases is hard-coded. If the user wants to
provide their own list, they are out of luck.
And I think that there is now a significant reason to support this -
the new Vulkan hwdec is definitely not ready to be in the auto list,
but if you want to use it by default, it will not work with many codecs
that are normally hardware decodable (only h.264, hevc and av1 if you
are very lucky). Everything else will fall back to software decoding.
Instead, what you really want to say is: use Vulkan for whatever it
supports, and fall back to my old hwdec for everything else.
One side-effect of this implementation is that you can freely mix
hwdec names and special values like `auto` and `no`. The behaviour will
be correct, so I didn't try and prohibit any combinations. However,
some combinations will be silly - eg: sticking any further values after
`no` will result in them being ignored. On the other hand, a
combination like `vulkan,auto` could be very useful as that will use
Vulkan if possible, and if not, run the normal auto routine.
Fixes #11797
2023-06-18 19:07:30 +00:00
|
|
|
talloc_free(hwdecs);
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
|
|
|
|
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 {
|
2023-07-12 23:06:33 +00:00
|
|
|
// 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");
|
|
|
|
}
|
2016-04-25 09:28:25 +00:00
|
|
|
}
|
2013-08-11 21:23:12 +00:00
|
|
|
}
|
|
|
|
|
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)
|
2013-08-11 21:23:12 +00:00
|
|
|
{
|
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);
|
2017-12-01 20:05:54 +00:00
|
|
|
|
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");
|
2017-12-01 20:05:54 +00:00
|
|
|
|
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];
|
2017-12-01 20:05:54 +00:00
|
|
|
|
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);
|
|
|
|
}
|
2017-12-01 20:05:54 +00:00
|
|
|
|
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);
|
2017-12-01 20:05:54 +00:00
|
|
|
|
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");
|
2019-12-24 08:24:22 +00:00
|
|
|
|
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;
|
2013-08-11 21:23:12 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void force_fallback(struct mp_filter *vd)
|
2015-09-02 21:10:39 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
|
|
|
|
uninit_avctx(vd);
|
2015-09-02 21:31:01 +00:00
|
|
|
int lev = ctx->hwdec_notified ? MSGL_WARN : MSGL_V;
|
vd_lavc: try other hwdecs when falling back after an hwdec failure
Today, if hwdec initialisation succeeds, we move on to attempting
decoding, and if decoding fails, we enter a fallback path that will
only do software decoding.
This is suboptimal because some hwdecs and codec combinations can
pass hwdec init, but then fail at hwaccel init, or even frame decoding.
In these situations, we will never attempt other hwdecs in the `auto`
or manually specified lists which might work.
One good example is someone tries to use `vulkan,auto` and tries to
play av1 content. The vulkan decoding will fail at hwaccel init time,
and then fallback to software instead of going through the auto list
which would allow vaapi, nvdec, etc to play the file.
Instead, let's not give up immediately, and try the next hwdec after
a failure, just like we do if hwdec init fails.
The key part of this change is to keep track of the hwdecs we have
tried, so that each time we run through hwdec selection, we don't try
the same one over and over again. If we really get through the whole
list with no success, we will then fall back to software decoding.
Fixes #11865
2023-07-01 17:16:16 +00:00
|
|
|
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);
|
2017-12-01 20:05:54 +00:00
|
|
|
init_avctx(vd);
|
2015-09-02 21:10:39 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void reinit(struct mp_filter *vd)
|
2011-10-22 00:51:37 +00:00
|
|
|
{
|
2016-01-29 21:47:27 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2009-02-12 15:41:59 +00:00
|
|
|
|
2016-01-29 21:47:27 +00:00
|
|
|
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
|
|
|
|
vd_lavc: try other hwdecs when falling back after an hwdec failure
Today, if hwdec initialisation succeeds, we move on to attempting
decoding, and if decoding fails, we enter a fallback path that will
only do software decoding.
This is suboptimal because some hwdecs and codec combinations can
pass hwdec init, but then fail at hwaccel init, or even frame decoding.
In these situations, we will never attempt other hwdecs in the `auto`
or manually specified lists which might work.
One good example is someone tries to use `vulkan,auto` and tries to
play av1 content. The vulkan decoding will fail at hwaccel init time,
and then fallback to software instead of going through the auto list
which would allow vaapi, nvdec, etc to play the file.
Instead, let's not give up immediately, and try the next hwdec after
a failure, just like we do if hwdec init fails.
The key part of this change is to keep track of the hwdecs we have
tried, so that each time we run through hwdec selection, we don't try
the same one over and over again. If we really get through the whole
list with no success, we will then fall back to software decoding.
Fixes #11865
2023-07-01 17:16:16 +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;
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
select_and_set_hwdec(vd);
|
2012-12-11 17:16:42 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
bool use_hwdec = ctx->use_hwdec;
|
|
|
|
init_avctx(vd);
|
2023-08-06 03:41:14 +00:00
|
|
|
if (!ctx->avctx && use_hwdec) {
|
|
|
|
do {
|
|
|
|
force_fallback(vd);
|
|
|
|
} while (!ctx->avctx);
|
|
|
|
}
|
2016-01-29 21:47:27 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void init_avctx(struct mp_filter *vd)
|
2012-12-11 17:16:42 +00:00
|
|
|
{
|
2013-11-23 20:36:20 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2018-05-21 14:05:03 +00:00
|
|
|
struct vd_lavc_params *lavc_param = ctx->opts;
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
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
|
|
|
|
2018-05-21 14:05:03 +00:00
|
|
|
m_config_cache_update(ctx->opts_cache);
|
|
|
|
|
2013-04-27 11:36:09 +00:00
|
|
|
assert(!ctx->avctx);
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
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)
|
2013-04-27 11:36:09 +00:00
|
|
|
return;
|
2012-07-24 06:01:47 +00:00
|
|
|
|
2017-10-26 17:44:26 +00:00
|
|
|
const AVCodecDescriptor *desc = avcodec_descriptor_get(lavc_codec->id);
|
|
|
|
ctx->intra_only = desc && (desc->props & AV_CODEC_PROP_INTRA_ONLY);
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
ctx->codec_timebase = mp_get_codec_timebase(ctx->codec);
|
2016-08-29 10:49:18 +00:00
|
|
|
|
|
|
|
// This decoder does not read pkt_timebase correctly yet.
|
2017-12-01 20:05:54 +00:00
|
|
|
if (strstr(lavc_codec->name, "_mmal"))
|
2016-08-29 10:49:18 +00:00
|
|
|
ctx->codec_timebase = (AVRational){1, 1000000};
|
|
|
|
|
2017-08-23 12:00:24 +00:00
|
|
|
ctx->hwdec_failed = false;
|
|
|
|
ctx->hwdec_request_reinit = false;
|
2012-01-28 11:41:36 +00:00
|
|
|
ctx->avctx = avcodec_alloc_context3(lavc_codec);
|
2012-12-11 17:16:42 +00:00
|
|
|
AVCodecContext *avctx = ctx->avctx;
|
2014-12-12 16:28:22 +00:00
|
|
|
if (!ctx->avctx)
|
2014-12-13 21:00:42 +00:00
|
|
|
goto error;
|
2011-04-19 23:59:45 +00:00
|
|
|
avctx->codec_type = AVMEDIA_TYPE_VIDEO;
|
2009-09-23 19:21:38 +00:00
|
|
|
avctx->codec_id = lavc_codec->id;
|
2016-08-29 10:46:12 +00:00
|
|
|
avctx->pkt_timebase = ctx->codec_timebase;
|
2016-04-25 09:47:35 +00:00
|
|
|
|
2013-10-31 17:12:39 +00:00
|
|
|
ctx->pic = av_frame_alloc();
|
2014-12-12 16:28:22 +00:00
|
|
|
if (!ctx->pic)
|
2014-12-13 21:00:42 +00:00
|
|
|
goto error;
|
2013-10-31 17:12:39 +00:00
|
|
|
|
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;
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (ctx->use_hwdec) {
|
vd, vd_lavc: change license to LGPL (almost)
iive agreed only to LGPL 3.0+ only. All of his relevant changes are for
XvMC, for which mpv completely dropped support back in mplayer2 times.
But you could claim that the get_format code represents some residual
copyright (everything else added by iive was removed, only get_format
still is around in some form). While I doubt that this is relly
copyright-relevant, consider it is for now.
michael is the original author of vd_lavc.c, so this file can become
LGPL only after the core becomes LGPL.
cehoyos did not agree with the LGPL relicensing, but all of his code is
gone.
Some others could not be reached, but their code is gone as well. In
particular, vdpau support, which was originally done by Nvidia, had
larger impact on vd_lavc.c, but vdpau support was first refactored a few
times (for the purpose of modularization) and moved to different files,
and then decoding was completely moved to libavcodec.
Lastly, assigning the "opaque" field was moved by Gwenole Beauchesne in
commit 8e5edec13eab. Agreement is pending (due to copyright apparently
owned by the author's employer). So just undo the change, so we don't
have to think about whether the change is copyrightable.
2017-06-15 13:52:18 +00:00
|
|
|
avctx->opaque = vd;
|
2016-04-25 10:12:40 +00:00
|
|
|
avctx->thread_count = 1;
|
2017-03-23 10:06:28 +00:00
|
|
|
avctx->hwaccel_flags |= AV_HWACCEL_FLAG_IGNORE_LEVEL;
|
2017-07-04 12:58:34 +00:00
|
|
|
if (!lavc_param->check_hw_profile)
|
|
|
|
avctx->hwaccel_flags |= AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH;
|
2017-12-01 20:05:54 +00:00
|
|
|
|
2022-12-12 18:05:24 +00:00
|
|
|
#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
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
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) {
|
2017-02-20 07:39:55 +00:00
|
|
|
if (!ctx->hwdec_dev)
|
|
|
|
goto error;
|
|
|
|
}
|
2017-12-01 20:05:54 +00:00
|
|
|
|
|
|
|
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;
|
2017-01-10 15:49:06 +00:00
|
|
|
ctx->hw_probing = true;
|
2013-03-09 19:21:12 +00:00
|
|
|
} else {
|
2015-01-05 11:17:55 +00:00
|
|
|
mp_set_avcodec_threads(vd->log, avctx, lavc_param->threads);
|
2010-12-20 03:53:28 +00:00
|
|
|
}
|
2002-09-06 22:53:26 +00:00
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
if (!ctx->use_hwdec && ctx->vo && lavc_param->dr) {
|
2017-07-23 07:41:51 +00:00
|
|
|
avctx->opaque = vd;
|
|
|
|
avctx->get_buffer2 = get_buffer2_direct;
|
|
|
|
}
|
|
|
|
|
2016-12-29 06:37:31 +00:00
|
|
|
avctx->flags |= lavc_param->bitexact ? AV_CODEC_FLAG_BITEXACT : 0;
|
|
|
|
avctx->flags2 |= lavc_param->fast ? AV_CODEC_FLAG2_FAST : 0;
|
2009-02-12 15:41:59 +00:00
|
|
|
|
2016-04-25 17:11:16 +00:00
|
|
|
if (lavc_param->show_all)
|
2016-12-29 06:37:31 +00:00
|
|
|
avctx->flags |= AV_CODEC_FLAG_OUTPUT_CORRUPT;
|
2013-12-29 13:07:08 +00:00
|
|
|
|
2014-06-13 00:03:45 +00:00
|
|
|
avctx->skip_loop_filter = lavc_param->skip_loop_filter;
|
|
|
|
avctx->skip_idct = lavc_param->skip_idct;
|
|
|
|
avctx->skip_frame = lavc_param->skip_frame;
|
2023-09-01 10:26:38 +00:00
|
|
|
avctx->apply_cropping = lavc_param->apply_cropping;
|
2017-12-26 04:53:44 +00:00
|
|
|
|
|
|
|
if (lavc_codec->id == AV_CODEC_ID_H264 && lavc_param->old_x264)
|
|
|
|
av_opt_set(avctx, "x264_build", "150", AV_OPT_SEARCH_CHILDREN);
|
2008-05-10 18:55:31 +00:00
|
|
|
|
2022-04-11 18:36:51 +00:00
|
|
|
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");
|
2022-04-03 12:17:43 +00:00
|
|
|
}
|
2022-04-11 18:36:51 +00:00
|
|
|
|
|
|
|
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;
|
2022-04-03 12:17:43 +00:00
|
|
|
}
|
|
|
|
|
2014-08-02 01:12:09 +00:00
|
|
|
mp_set_avopts(vd->log, avctx, lavc_param->avopts);
|
2008-05-10 18:55:31 +00:00
|
|
|
|
2011-07-09 10:50:16 +00:00
|
|
|
// Do this after the above avopt handling in case it changes values
|
|
|
|
ctx->skip_frame = avctx->skip_frame;
|
|
|
|
|
2017-01-25 07:24:19 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2002-03-06 20:54:43 +00:00
|
|
|
/* open it */
|
2014-12-13 21:00:42 +00:00
|
|
|
if (avcodec_open2(avctx, lavc_codec, NULL) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2017-12-26 05:09:26 +00:00
|
|
|
// 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);
|
2017-12-26 05:09:26 +00:00
|
|
|
avcodec_receive_frame(avctx, ctx->pic);
|
|
|
|
av_frame_unref(ctx->pic);
|
|
|
|
avcodec_flush_buffers(ctx->avctx);
|
|
|
|
}
|
|
|
|
|
2014-12-13 21:00:42 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
MP_ERR(vd, "Could not open codec.\n");
|
|
|
|
uninit_avctx(vd);
|
2002-03-06 20:54:43 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void reset_avctx(struct mp_filter *vd)
|
2015-11-10 15:06:42 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
|
2016-02-06 09:09:13 +00:00
|
|
|
if (ctx->avctx && avcodec_is_open(ctx->avctx))
|
2015-11-10 15:06:42 +00:00
|
|
|
avcodec_flush_buffers(ctx->avctx);
|
|
|
|
ctx->flushing = false;
|
2017-08-23 12:00:24 +00:00
|
|
|
ctx->hwdec_request_reinit = false;
|
2015-11-10 15:06:42 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void flush_all(struct mp_filter *vd)
|
2016-01-25 20:00:53 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2017-01-10 15:49:06 +00:00
|
|
|
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;
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2016-01-25 20:00:53 +00:00
|
|
|
reset_avctx(vd);
|
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void uninit_avctx(struct mp_filter *vd)
|
2011-10-22 00:51:37 +00:00
|
|
|
{
|
2013-11-23 20:36:20 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2009-02-12 15:41:59 +00:00
|
|
|
|
2016-01-30 19:59:25 +00:00
|
|
|
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);
|
2017-01-17 09:56:16 +00:00
|
|
|
av_buffer_unref(&ctx->cached_hw_frames_ctx);
|
2016-01-30 19:59:25 +00:00
|
|
|
|
2017-07-06 14:12:50 +00:00
|
|
|
avcodec_free_context(&ctx->avctx);
|
2005-01-08 19:16:21 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
av_buffer_unref(&ctx->hwdec_dev);
|
2017-02-20 07:39:55 +00:00
|
|
|
|
vd_lavc: make hardware decoding fallback less violent
Most of hardware decoding is initialized lazily. When the first packet
is parsed, libavcodec will call get_format() to check whether hw or sw
decoding is wanted. Until now, we've returned AV_PIX_FMT_NONE from
get_format() if hw decoder initialization failed. This caused the
avcodec_decode_video2() call to fail, which in turn let us trigger the
fallback. We didn't return a sw format from get_format(), because we
didn't want to continue decoding at all. (The reason being that full
reinitialization is more robust when continuing sw decoding.)
This has some disadvantages. libavcodec vomited some unwanted error
messages. Sometimes the failures are more severe, like it happened with
HEVC. In this case, the error code path simply acted up in a way that
was extremely inconvenient (and had to be fixed by myself). In general,
libavcodec is not designed to fallback this way.
Make it a bit less violent from the API usage point of view. Return a sw
format if hw decoder initialization fails. In this case, we let
get_buffer2() call avcodec_default_get_buffer2() as well. libavcodec is
allowed to perform its own sw fallback. But once the decode function
returns, we do the full reinitialization we wanted to do.
The result is that the fallback is more robust, and doesn't trigger any
decoder error codepaths or messages either. Change our own fallback
message to a warning, since there are no other messages with error
severity anymore.
2015-05-28 19:52:04 +00:00
|
|
|
ctx->hwdec_failed = false;
|
2015-11-03 13:03:02 +00:00
|
|
|
ctx->hwdec_fail_count = 0;
|
2016-01-25 20:00:53 +00:00
|
|
|
ctx->max_delay_queue = 0;
|
2017-01-10 15:49:06 +00:00
|
|
|
ctx->hw_probing = false;
|
2017-12-01 20:05:54 +00:00
|
|
|
ctx->hwdec = (struct hwdec_info){0};
|
|
|
|
ctx->use_hwdec = false;
|
2002-03-06 20:54:43 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static int init_generic_hwaccel(struct mp_filter *vd, enum AVPixelFormat hw_fmt)
|
2017-10-27 15:22:32 +00:00
|
|
|
{
|
|
|
|
struct lavc_ctx *ctx = vd->priv;
|
|
|
|
AVBufferRef *new_frames_ctx = NULL;
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (!ctx->hwdec.use_hw_frames)
|
2017-10-27 15:22:32 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (!ctx->hwdec_dev) {
|
2017-10-27 15:22:32 +00:00
|
|
|
MP_ERR(ctx, "Missing device context.\n");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (avcodec_get_hw_frames_parameters(ctx->avctx,
|
2017-12-01 20:05:54 +00:00
|
|
|
ctx->hwdec_dev, hw_fmt, &new_frames_ctx) < 0)
|
2017-10-27 15:22:32 +00:00
|
|
|
{
|
|
|
|
MP_VERBOSE(ctx, "Hardware decoding of this stream is unsupported?\n");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
AVHWFramesContext *new_fctx = (void *)new_frames_ctx->data;
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
if (ctx->opts->hwdec_image_format)
|
|
|
|
new_fctx->sw_format = imgfmt2pixfmt(ctx->opts->hwdec_image_format);
|
2017-10-27 15:22:32 +00:00
|
|
|
|
|
|
|
// 1 surface is already included by libavcodec. The field is 0 if the
|
|
|
|
// hwaccel supports dynamic surface allocation.
|
|
|
|
if (new_fctx->initial_pool_size)
|
2019-05-31 18:11:32 +00:00
|
|
|
new_fctx->initial_pool_size += ctx->opts->hwdec_extra_frames - 1;
|
2017-10-27 15:22:32 +00:00
|
|
|
|
2017-12-01 05:47:37 +00:00
|
|
|
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);
|
2017-10-27 15:22:32 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2013-11-29 16:39:57 +00:00
|
|
|
static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx,
|
|
|
|
const enum AVPixelFormat *fmt)
|
2012-11-06 14:27:44 +00:00
|
|
|
{
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
struct mp_filter *vd = avctx->opaque;
|
2013-11-23 20:36:20 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2012-11-06 14:27:44 +00:00
|
|
|
|
2013-12-21 16:47:38 +00:00
|
|
|
MP_VERBOSE(vd, "Pixel formats supported by decoder:");
|
2013-11-29 16:39:57 +00:00
|
|
|
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++)
|
2013-12-21 16:47:38 +00:00
|
|
|
MP_VERBOSE(vd, " %s", av_get_pix_fmt_name(fmt[i]));
|
|
|
|
MP_VERBOSE(vd, "\n");
|
2012-12-11 17:16:42 +00:00
|
|
|
|
2016-01-08 08:13:56 +00:00
|
|
|
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);
|
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
assert(ctx->use_hwdec);
|
2012-12-11 17:16:42 +00:00
|
|
|
|
2015-10-12 19:24:25 +00:00
|
|
|
ctx->hwdec_request_reinit |= ctx->hwdec_failed;
|
|
|
|
ctx->hwdec_failed = false;
|
|
|
|
|
2017-03-01 15:02:08 +00:00
|
|
|
enum AVPixelFormat select = AV_PIX_FMT_NONE;
|
2016-04-25 10:12:40 +00:00
|
|
|
for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
|
2017-12-01 20:05:54 +00:00
|
|
|
if (ctx->hwdec.pix_fmt == fmt[i]) {
|
|
|
|
if (init_generic_hwaccel(vd, fmt[i]) < 0)
|
|
|
|
break;
|
2017-03-01 15:02:08 +00:00
|
|
|
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
|
|
|
}
|
2012-11-06 14:27:44 +00:00
|
|
|
}
|
2012-12-11 17:16:42 +00:00
|
|
|
|
2017-03-01 15:02:08 +00:00
|
|
|
if (select == AV_PIX_FMT_NONE) {
|
|
|
|
ctx->hwdec_failed = true;
|
2018-05-16 18:54:46 +00:00
|
|
|
select = avcodec_default_get_format(avctx, fmt);
|
2015-05-29 12:17:51 +00:00
|
|
|
}
|
2017-03-01 15:02:08 +00:00
|
|
|
|
|
|
|
const char *name = av_get_pix_fmt_name(select);
|
|
|
|
MP_VERBOSE(vd, "Requesting pixfmt '%s' from decoder.\n", name ? name : "-");
|
|
|
|
return select;
|
2012-11-06 14:27:44 +00:00
|
|
|
}
|
|
|
|
|
2017-07-23 07:41:51 +00:00
|
|
|
static int get_buffer2_direct(AVCodecContext *avctx, AVFrame *pic, int flags)
|
|
|
|
{
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
struct mp_filter *vd = avctx->opaque;
|
2017-07-23 07:41:51 +00:00
|
|
|
vd_ffmpeg_ctx *p = vd->priv;
|
|
|
|
|
2023-10-21 02:55:41 +00:00
|
|
|
mp_mutex_lock(&p->dr_lock);
|
2017-07-23 07:41:51 +00:00
|
|
|
|
|
|
|
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;
|
2017-07-23 07:41:51 +00:00
|
|
|
for (int n = 0; n < AV_NUM_DATA_POINTERS; n++)
|
|
|
|
stride_align = MPMAX(stride_align, linesize_align[n]);
|
|
|
|
|
2023-10-19 15:53:30 +00:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2017-07-23 07:41:51 +00:00
|
|
|
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;
|
2017-09-28 09:53:57 +00:00
|
|
|
MP_DBG(p, "DR parameter change to %dx%d %s align=%d\n", w, h,
|
|
|
|
mp_imgfmt_to_name(imgfmt), stride_align);
|
2017-07-23 07:41:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct mp_image *img = mp_image_pool_get_no_alloc(p->dr_pool, imgfmt, w, h);
|
|
|
|
if (!img) {
|
2023-01-21 14:45:11 +00:00
|
|
|
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);
|
2017-07-23 07:41:51 +00:00
|
|
|
if (!img) {
|
2017-09-28 09:53:57 +00:00
|
|
|
MP_DBG(p, "...failed..\n");
|
2017-07-23 07:41:51 +00:00
|
|
|
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);
|
2017-07-23 07:41:51 +00:00
|
|
|
|
|
|
|
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);
|
2017-07-23 07:41:51 +00:00
|
|
|
|
|
|
|
return avcodec_default_get_buffer2(avctx, pic, flags);
|
|
|
|
}
|
|
|
|
|
2019-11-02 21:44:39 +00:00
|
|
|
static void prepare_decoding(struct mp_filter *vd)
|
2009-11-21 18:53:10 +00:00
|
|
|
{
|
2013-11-23 20:36:20 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2002-07-14 19:44:40 +00:00
|
|
|
AVCodecContext *avctx = ctx->avctx;
|
2018-05-21 14:05:03 +00:00
|
|
|
struct vd_lavc_params *opts = ctx->opts;
|
2002-07-14 19:44:40 +00:00
|
|
|
|
2019-11-02 21:44:39 +00:00
|
|
|
if (!avctx)
|
|
|
|
return;
|
2015-12-05 22:53:55 +00:00
|
|
|
|
2017-01-10 15:19:57 +00:00
|
|
|
int drop = ctx->framedrop_flags;
|
2017-10-26 17:44:26 +00:00
|
|
|
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;
|
2014-08-08 22:35:25 +00:00
|
|
|
} else {
|
2017-10-26 17:44:26 +00:00
|
|
|
avctx->skip_frame = ctx->skip_frame; // normal playback
|
2014-08-08 22:35:25 +00:00
|
|
|
}
|
2002-07-14 19:44:40 +00:00
|
|
|
|
2017-01-10 15:19:57 +00:00
|
|
|
if (ctx->hwdec_request_reinit)
|
2015-11-10 15:06:42 +00:00
|
|
|
reset_avctx(vd);
|
2017-01-10 15:19:57 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static void handle_err(struct mp_filter *vd)
|
2017-01-10 15:19:57 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2018-05-21 14:05:03 +00:00
|
|
|
struct vd_lavc_params *opts = ctx->opts;
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2019-11-02 21:38:08 +00:00
|
|
|
MP_WARN(vd, "Error while decoding frame%s!\n",
|
|
|
|
ctx->use_hwdec ? " (hardware decoding)" : "");
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2017-12-01 20:05:54 +00:00
|
|
|
if (ctx->use_hwdec) {
|
2017-01-10 15:19:57 +00:00
|
|
|
ctx->hwdec_fail_count += 1;
|
2017-09-26 17:13:26 +00:00
|
|
|
if (ctx->hwdec_fail_count >= opts->software_fallback)
|
2017-01-10 15:19:57 +00:00
|
|
|
ctx->hwdec_failed = true;
|
2016-03-24 16:53:30 +00:00
|
|
|
}
|
2017-01-10 15:19:57 +00:00
|
|
|
}
|
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
|
2017-01-10 15:19:57 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
AVCodecContext *avctx = ctx->avctx;
|
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
if (ctx->num_requeue_packets && ctx->requeue_packets[0] != pkt)
|
|
|
|
return AVERROR(EAGAIN); // cannot consume the packet
|
|
|
|
|
2019-11-02 21:44:39 +00:00
|
|
|
if (ctx->hwdec_failed)
|
|
|
|
return AVERROR(EAGAIN);
|
|
|
|
|
|
|
|
if (!ctx->avctx)
|
|
|
|
return AVERROR_EOF;
|
|
|
|
|
|
|
|
prepare_decoding(vd);
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2017-10-26 17:44:26 +00:00
|
|
|
if (avctx->skip_frame == AVDISCARD_ALL)
|
2019-11-02 20:37:52 +00:00
|
|
|
return 0;
|
2017-10-26 17:44:26 +00:00
|
|
|
|
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);
|
2017-01-10 15:19:57 +00:00
|
|
|
|
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);
|
2017-01-10 15:19:57 +00:00
|
|
|
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;
|
2015-11-10 15:06:42 +00:00
|
|
|
|
2019-11-02 22:00:49 +00:00
|
|
|
if (ctx->hw_probing && ctx->num_sent_packets < 32 &&
|
|
|
|
ctx->opts->software_fallback <= 32)
|
|
|
|
{
|
2017-01-10 15:49:06 +00:00
|
|
|
pkt = pkt ? demux_copy_packet(pkt) : NULL;
|
|
|
|
MP_TARRAY_APPEND(ctx, ctx->sent_packets, ctx->num_sent_packets, pkt);
|
|
|
|
}
|
2003-04-06 23:37:56 +00:00
|
|
|
|
2017-01-10 15:19:57 +00:00
|
|
|
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;
|
2017-01-10 15:19:57 +00:00
|
|
|
}
|
2015-10-19 15:49:30 +00:00
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
static void send_queued_packet(struct mp_filter *vd)
|
2017-01-10 15:49:06 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
assert(ctx->num_requeue_packets);
|
|
|
|
|
|
|
|
if (send_packet(vd, ctx->requeue_packets[0]) != AVERROR(EAGAIN)) {
|
2018-02-04 18:00:28 +00:00
|
|
|
talloc_free(ctx->requeue_packets[0]);
|
|
|
|
MP_TARRAY_REMOVE_AT(ctx->requeue_packets, ctx->num_requeue_packets, 0);
|
2017-01-10 15:49:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-11 09:56:25 +00:00
|
|
|
// 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)
|
2017-01-10 15:19:57 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
AVCodecContext *avctx = ctx->avctx;
|
2016-02-19 17:35:11 +00:00
|
|
|
|
2023-07-12 23:06:33 +00:00
|
|
|
if (!avctx || ctx->force_eof)
|
2019-11-02 21:44:39 +00:00
|
|
|
return AVERROR_EOF;
|
|
|
|
|
|
|
|
prepare_decoding(vd);
|
2019-11-02 21:37:14 +00:00
|
|
|
|
|
|
|
// Re-send old packets (typically after a hwdec fallback during init).
|
|
|
|
if (ctx->num_requeue_packets)
|
|
|
|
send_queued_packet(vd);
|
2017-01-10 15:19:57 +00:00
|
|
|
|
|
|
|
int ret = avcodec_receive_frame(avctx, ctx->pic);
|
2019-12-15 21:26:39 +00:00
|
|
|
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;
|
2016-01-25 20:00:53 +00:00
|
|
|
}
|
2015-10-19 16:19:57 +00:00
|
|
|
|
2024-04-10 19:24:06 +00:00
|
|
|
mp_codec_info_from_av(avctx, ctx->codec);
|
|
|
|
|
2019-12-15 21:26:39 +00:00
|
|
|
// If something was decoded successfully, it must return a frame with valid
|
|
|
|
// data.
|
|
|
|
assert(ctx->pic->buf[0]);
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2014-03-16 08:21:21 +00:00
|
|
|
struct mp_image *mpi = mp_image_from_av_frame(ctx->pic);
|
2016-01-25 19:47:13 +00:00
|
|
|
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;
|
2016-01-25 19:47:13 +00:00
|
|
|
}
|
2019-12-18 00:56:29 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2016-12-07 18:44:29 +00:00
|
|
|
mpi->pts = mp_pts_from_av(ctx->pic->pts, &ctx->codec_timebase);
|
2016-03-24 15:38:14 +00:00
|
|
|
mpi->dts = mp_pts_from_av(ctx->pic->pkt_dts, &ctx->codec_timebase);
|
2024-06-21 16:35:11 +00:00
|
|
|
mpi->pkt_duration = mp_pts_from_av(ctx->pic->duration, &ctx->codec_timebase);
|
2016-12-21 17:18:24 +00:00
|
|
|
|
2016-01-25 19:47:13 +00:00
|
|
|
av_frame_unref(ctx->pic);
|
|
|
|
|
2016-01-25 20:00:53 +00:00
|
|
|
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;
|
2012-12-11 17:16:42 +00:00
|
|
|
}
|
|
|
|
|
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)
|
2013-12-10 18:07:29 +00:00
|
|
|
{
|
|
|
|
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);
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2015-09-23 18:37:47 +00:00
|
|
|
if (ctx->hwdec_failed) {
|
2023-07-17 14:29:10 +00:00
|
|
|
// Failed hardware decoding? Try the next one, and eventually software.
|
2017-01-10 15:49:06 +00:00
|
|
|
struct demux_packet **pkts = ctx->sent_packets;
|
|
|
|
int num_pkts = ctx->num_sent_packets;
|
|
|
|
ctx->sent_packets = NULL;
|
|
|
|
ctx->num_sent_packets = 0;
|
2017-01-10 15:19:57 +00:00
|
|
|
|
2023-07-17 14:29:10 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
2012-12-11 17:16:42 +00:00
|
|
|
|
2017-01-10 15:49:06 +00:00
|
|
|
ctx->requeue_packets = pkts;
|
|
|
|
ctx->num_requeue_packets = num_pkts;
|
2018-02-04 18:00:28 +00:00
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
return 0; // force retry
|
2015-09-02 21:31:01 +00:00
|
|
|
}
|
|
|
|
|
2019-11-02 21:37:14 +00:00
|
|
|
if (ret == AVERROR(EAGAIN) && ctx->num_requeue_packets)
|
|
|
|
return 0; // force retry, so send_queued_packet() gets called
|
|
|
|
|
2023-06-30 17:14:32 +00:00
|
|
|
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;
|
2017-01-11 09:58:30 +00:00
|
|
|
|
2023-06-30 17:14:32 +00:00
|
|
|
if (!ctx->num_delay_queue)
|
|
|
|
return ret;
|
2017-01-11 09:58:30 +00:00
|
|
|
|
|
|
|
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)
|
vd_lavc: fix draining with hwdec copy modes
Commit 5d5fdb77e99 changed details of the decoding control flow, and
called it a "high-risk" change. It turns out that this broke with with
hwdec copy mode, where there is some sort of delay queue (supposedly
increases efficiency, but more likely worthless cargo-cult).
It simply used the wrong (basically inverted) condition for the draining
case.
This was the only case that did not work properly. Other tests,
including video/audio decoding errors, software decoding fallbacks,
etc., seemed to work well. Might still not be exhaustive, as there are
so many corner cases.
Also change two error code returns. This don't/shouldn't really matter,
though the second error code led it to return both a frame and
AVERROR_EOF, which is unexpected, and makes lavc_process() leak a frame.
But also see next commit.
Fixes: 5d5fdb77e99
2019-10-25 19:41:58 +00:00
|
|
|
return AVERROR_UNKNOWN;
|
2017-01-11 09:58:30 +00:00
|
|
|
|
2017-12-02 01:45:49 +00:00
|
|
|
if (ctx->use_hwdec && ctx->hwdec.copying && res->hwctx) {
|
2017-01-12 12:15:45 +00:00
|
|
|
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");
|
2017-01-17 10:03:42 +00:00
|
|
|
ctx->hwdec_fail_count = INT_MAX - 1; // force fallback
|
2017-01-12 12:15:45 +00:00
|
|
|
handle_err(vd);
|
vd_lavc: fix draining with hwdec copy modes
Commit 5d5fdb77e99 changed details of the decoding control flow, and
called it a "high-risk" change. It turns out that this broke with with
hwdec copy mode, where there is some sort of delay queue (supposedly
increases efficiency, but more likely worthless cargo-cult).
It simply used the wrong (basically inverted) condition for the draining
case.
This was the only case that did not work properly. Other tests,
including video/audio decoding errors, software decoding fallbacks,
etc., seemed to work well. Might still not be exhaustive, as there are
so many corner cases.
Also change two error code returns. This don't/shouldn't really matter,
though the second error code led it to return both a frame and
AVERROR_EOF, which is unexpected, and makes lavc_process() leak a frame.
But also see next commit.
Fixes: 5d5fdb77e99
2019-10-25 19:41:58 +00:00
|
|
|
return AVERROR_UNKNOWN;
|
2017-01-12 12:15:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-24 22:40:01 +00:00
|
|
|
if (!ctx->hwdec_notified) {
|
2017-12-01 20:05:54 +00:00
|
|
|
if (ctx->use_hwdec) {
|
2017-01-11 09:58:30 +00:00
|
|
|
MP_INFO(vd, "Using hardware decoding (%s).\n",
|
2017-12-01 20:05:54 +00:00
|
|
|
ctx->hwdec.method_name);
|
2017-01-11 09:58:30 +00:00
|
|
|
} else {
|
2017-01-13 17:52:07 +00:00
|
|
|
MP_VERBOSE(vd, "Using software decoding.\n");
|
2017-01-11 09:58:30 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
*out_frame = MAKE_FRAME(MP_FRAME_VIDEO, res);
|
vd_lavc: fix draining with hwdec copy modes
Commit 5d5fdb77e99 changed details of the decoding control flow, and
called it a "high-risk" change. It turns out that this broke with with
hwdec copy mode, where there is some sort of delay queue (supposedly
increases efficiency, but more likely worthless cargo-cult).
It simply used the wrong (basically inverted) condition for the draining
case.
This was the only case that did not work properly. Other tests,
including video/audio decoding errors, software decoding fallbacks,
etc., seemed to work well. Might still not be exhaustive, as there are
so many corner cases.
Also change two error code returns. This don't/shouldn't really matter,
though the second error code led it to return both a frame and
AVERROR_EOF, which is unexpected, and makes lavc_process() leak a frame.
But also see next commit.
Fixes: 5d5fdb77e99
2019-10-25 19:41:58 +00:00
|
|
|
return 0;
|
2002-03-06 20:54:43 +00:00
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
static int control(struct mp_filter *vd, enum dec_ctrl cmd, void *arg)
|
2011-11-14 18:12:20 +00:00
|
|
|
{
|
2013-11-23 20:36:20 +00:00
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
2011-11-14 18:12:20 +00:00
|
|
|
switch (cmd) {
|
2017-01-10 15:19:57 +00:00
|
|
|
case VDCTRL_SET_FRAMEDROP:
|
|
|
|
ctx->framedrop_flags = *(int *)arg;
|
|
|
|
return CONTROL_TRUE;
|
2023-07-16 02:38:59 +00:00
|
|
|
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: {
|
video: readd codec delay estimation
Approximately reverts commit 3ccac74d. This failed with some avi files,
which do pseudo-VFR by sending packets with empty frames (or repeat
frames, depending on point of view). Specifically, these packets are not
0 bytes, so they don't get skipped by libavformat, as with the usual VFR
avi hack. Instead, the packet contains a VOP with vop_coded=0, so
libavcodec will just return no frame. We could probably distinguish such
skipped frames and delayed frames by explicitly measuring the codec
delay by counting how long it takes to get the very first frame (and
then treat skips as explicit drops), but we may as well simply reinstate
the old code.
To appease to at least one semi-broken case, do not enable this logic on
the RPI, as the FFmpeg MMAL wrapper has arbitrary buffering (and MMAL
itself is asynchronous).
2015-12-02 13:38:47 +00:00
|
|
|
AVCodecContext *avctx = ctx->avctx;
|
2015-12-05 22:53:55 +00:00
|
|
|
if (!avctx)
|
video: readd codec delay estimation
Approximately reverts commit 3ccac74d. This failed with some avi files,
which do pseudo-VFR by sending packets with empty frames (or repeat
frames, depending on point of view). Specifically, these packets are not
0 bytes, so they don't get skipped by libavformat, as with the usual VFR
avi hack. Instead, the packet contains a VOP with vop_coded=0, so
libavcodec will just return no frame. We could probably distinguish such
skipped frames and delayed frames by explicitly measuring the codec
delay by counting how long it takes to get the very first frame (and
then treat skips as explicit drops), but we may as well simply reinstate
the old code.
To appease to at least one semi-broken case, do not enable this logic on
the RPI, as the FFmpeg MMAL wrapper has arbitrary buffering (and MMAL
itself is asynchronous).
2015-12-02 13:38:47 +00:00
|
|
|
break;
|
2018-03-01 22:56:56 +00:00
|
|
|
if (ctx->use_hwdec && strcmp(ctx->hwdec.method_name, "mmal") == 0)
|
video: readd codec delay estimation
Approximately reverts commit 3ccac74d. This failed with some avi files,
which do pseudo-VFR by sending packets with empty frames (or repeat
frames, depending on point of view). Specifically, these packets are not
0 bytes, so they don't get skipped by libavformat, as with the usual VFR
avi hack. Instead, the packet contains a VOP with vop_coded=0, so
libavcodec will just return no frame. We could probably distinguish such
skipped frames and delayed frames by explicitly measuring the codec
delay by counting how long it takes to get the very first frame (and
then treat skips as explicit drops), but we may as well simply reinstate
the old code.
To appease to at least one semi-broken case, do not enable this logic on
the RPI, as the FFmpeg MMAL wrapper has arbitrary buffering (and MMAL
itself is asynchronous).
2015-12-02 13:38:47 +00:00
|
|
|
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;
|
video: readd codec delay estimation
Approximately reverts commit 3ccac74d. This failed with some avi files,
which do pseudo-VFR by sending packets with empty frames (or repeat
frames, depending on point of view). Specifically, these packets are not
0 bytes, so they don't get skipped by libavformat, as with the usual VFR
avi hack. Instead, the packet contains a VOP with vop_coded=0, so
libavcodec will just return no frame. We could probably distinguish such
skipped frames and delayed frames by explicitly measuring the codec
delay by counting how long it takes to get the very first frame (and
then treat skips as explicit drops), but we may as well simply reinstate
the old code.
To appease to at least one semi-broken case, do not enable this logic on
the RPI, as the FFmpeg MMAL wrapper has arbitrary buffering (and MMAL
itself is asynchronous).
2015-12-02 13:38:47 +00:00
|
|
|
return CONTROL_TRUE;
|
|
|
|
}
|
2014-04-22 23:17:28 +00:00
|
|
|
case VDCTRL_GET_HWDEC: {
|
2017-12-01 20:05:54 +00:00
|
|
|
*(char **)arg = ctx->use_hwdec ? ctx->hwdec.method_name : NULL;
|
2014-04-22 23:17:28 +00:00
|
|
|
return CONTROL_TRUE;
|
|
|
|
}
|
2013-12-10 18:07:29 +00:00
|
|
|
case VDCTRL_FORCE_HWDEC_FALLBACK:
|
2017-12-01 20:05:54 +00:00
|
|
|
if (ctx->use_hwdec) {
|
2016-04-22 13:45:23 +00:00
|
|
|
force_fallback(vd);
|
2015-09-02 21:10:39 +00:00
|
|
|
return ctx->avctx ? CONTROL_OK : CONTROL_ERROR;
|
2016-04-22 13:45:23 +00:00
|
|
|
}
|
2015-09-02 21:10:39 +00:00
|
|
|
return CONTROL_FALSE;
|
2016-01-29 21:47:27 +00:00
|
|
|
case VDCTRL_REINIT:
|
|
|
|
reinit(vd);
|
|
|
|
return CONTROL_TRUE;
|
2011-11-14 18:12:20 +00:00
|
|
|
}
|
|
|
|
return CONTROL_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2024-04-10 05:47:05 +00:00
|
|
|
static void vd_lavc_process(struct mp_filter *vd)
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
{
|
|
|
|
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);
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
}
|
|
|
|
|
2024-04-10 05:47:05 +00:00
|
|
|
static void vd_lavc_reset(struct mp_filter *vd)
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
{
|
|
|
|
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};
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
ctx->framedrop_flags = 0;
|
|
|
|
}
|
|
|
|
|
2024-04-10 05:47:05 +00:00
|
|
|
static void vd_lavc_destroy(struct mp_filter *vd)
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
{
|
|
|
|
vd_ffmpeg_ctx *ctx = vd->priv;
|
|
|
|
|
|
|
|
uninit_avctx(vd);
|
|
|
|
|
2023-10-21 02:55:41 +00:00
|
|
|
mp_mutex_destroy(&ctx->dr_lock);
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct mp_filter_info vd_lavc_filter = {
|
|
|
|
.name = "vd_lavc",
|
|
|
|
.priv_size = sizeof(vd_ffmpeg_ctx),
|
2024-04-10 05:47:05 +00:00
|
|
|
.process = vd_lavc_process,
|
|
|
|
.reset = vd_lavc_reset,
|
|
|
|
.destroy = vd_lavc_destroy,
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2018-05-21 14:05:03 +00:00
|
|
|
ctx->opts_cache = m_config_cache_alloc(ctx, vd->global, &vd_lavc_conf);
|
|
|
|
ctx->opts = ctx->opts_cache->opts;
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
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);
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2024-04-10 19:24:06 +00:00
|
|
|
|
|
|
|
codec->codec_desc = ctx->avctx->codec_descriptor->long_name;
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
video: make decoder wrapper a filter
Move dec_video.c to filters/f_decoder_wrapper.c. It essentially becomes
a source filter. vd.h mostly disappears, because mp_filter takes care of
the dataflow, but its remains are in struct mp_decoder_fns.
One goal is to simplify dataflow by letting the filter framework handle
it (or more accurately, using its conventions). One result is that the
decode calls disappear from video.c, because we simply connect the
decoder wrapper and the filter chain with mp_pin_connect().
Another goal is to eventually remove the code duplication between the
audio and video paths for this. This commit prepares for this by trying
to make f_decoder_wrapper.c extensible, so it can be used for audio as
well later.
Decoder framedropping changes a bit. It doesn't seem to be worse than
before, and it's an obscure feature, so I'm content with its new state.
Some special code that was apparently meant to avoid dropping too many
frames in a row is removed, though.
I'm not sure how the source code tree should be organized. For one,
video/decode/vd_lavc.c is the only file in its directory, which is a bit
annoying.
2018-01-28 09:08:45 +00:00
|
|
|
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,
|
2009-11-21 18:53:10 +00:00
|
|
|
};
|