mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
bb8da97205
commit
4d016a92c8
|
@ -10,7 +10,6 @@
|
|||
/mpv
|
||||
/mpv.app
|
||||
/version.h
|
||||
/core/codecs.conf.h
|
||||
/core/input/input_conf.h
|
||||
/tags
|
||||
/TAGS
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
Understanding MPlayer's etc/codecs.conf File
|
||||
|
||||
Introduction
|
||||
------------
|
||||
MPlayer features a very flexible codec architecture which allows it to
|
||||
use its own open source codecs, as well as open source libraries, Win32
|
||||
codec DLLs and other binary codec modules. To the MPlayer user, the
|
||||
most visible piece of this architecture is the etc/codecs.conf file. This
|
||||
is a text-based configuration file that controls which MPlayer components
|
||||
are in charge of handling particular compressed data formats.
|
||||
|
||||
The codecs.conf file is stored either in a shared directory for all system
|
||||
users to access, or in the .mplayer directory in a user's home
|
||||
directory. When MPlayer starts, it first looks for a codecs.conf file in a
|
||||
user's home directory. Failing that, it searches for the shared file. If
|
||||
no codecs.conf file is found MPlayer falls back on its internal hardcoded
|
||||
configuration. If the file is present but has syntax errors, MPlayer will
|
||||
report the error.
|
||||
|
||||
The codecs.conf file is really quite simple. It is simply a collection of
|
||||
codec definition blocks that define how different media types should be
|
||||
handled. There are a number of keywords that can occur in a block. Not all
|
||||
of them are required and no particular order is enforced.
|
||||
|
||||
Editing codecs.conf
|
||||
-------------------
|
||||
You can edit codecs.conf using your favorite text editor. Anything that
|
||||
comes after a semicolon (;) on a line is regarded as a comment. For
|
||||
example:
|
||||
; this is a comment
|
||||
format 0x34616d69 ; "ima4" (MOV files)
|
||||
|
||||
The codec blocks can be in any order; the file parser doesn't
|
||||
care. However, they are organized in a particular order for the benefit of
|
||||
human readers. For example, all of the open source decoders that MPlayer
|
||||
implements natively are grouped in one section.
|
||||
|
||||
Release Number
|
||||
--------------
|
||||
Your codecs.conf now requires a release number to avoid codec release
|
||||
incompatibilities. The format is simple: (YYYYMMDD)
|
||||
|
||||
release 20020520
|
||||
|
||||
Whenever changes are made to the codecs that *require* an updated
|
||||
codecs.conf, then MPlayer will no longer accept outdated versions.
|
||||
It is not recommended to change this line unless you know exactly
|
||||
what you are doing.
|
||||
|
||||
Video Codecs
|
||||
------------
|
||||
Let's jump right in with an example. Here is an example video codec block:
|
||||
|
||||
videocodec indeo5ds
|
||||
info "Intel Indeo 5"
|
||||
status working
|
||||
fourcc IV50,iv50
|
||||
driver dshow
|
||||
dll "ir50_32.dll"
|
||||
guid 0x30355649, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
|
||||
out YV12
|
||||
out YUY2
|
||||
out BGR32,BGR24,BGR16,BGR15
|
||||
|
||||
This is a particularly full-featured video codec. The "videocodec" keyword
|
||||
identifies the fact that this is the start of a new video
|
||||
codec. "indeo5ds" is MPlayer's unique name for the codec. You have to use
|
||||
this name with the -vc/-ac option.
|
||||
|
||||
The next line has the keyword "info" which specifies a human-readable
|
||||
comment accompanying this codec. This is printed by -vc help / -ac help.
|
||||
|
||||
The "status" keyword carries information about the codec's functional
|
||||
status. MPlayer currently recognizes 4 status levels: working, buggy,
|
||||
crashing, and untested. When it gets to codec auto-selection, it tries
|
||||
untested first (to force users to test it for us and report results :)),
|
||||
then working and finally buggy ones. Codecs marked crashing won't be tried,
|
||||
unless explicitly (-vc/-ac) selected.
|
||||
|
||||
The next line lists 4-character codes (FOURCCs) that are associated with
|
||||
this codec. There can be more than one FOURCC specified on a fourcc line
|
||||
as long as they are separated with a comma. There can also be multiple
|
||||
fourcc lines in the codec. A second fourcc can also be given, separated
|
||||
with a space. MPlayer will replace the original fourcc in the headers with
|
||||
this one before opening the codec. It's useful for win32 codecs checking for
|
||||
the fourccs.
|
||||
|
||||
The "driver" keyword associates this codec with an internal MPlayer
|
||||
decoder module. MPlayer has a module named "dshow" that handles data
|
||||
encoded by the codec. See -vfm help / -afm help for the available module list.
|
||||
|
||||
The "dll" keyword specifies which Win32/XAnim/Real/Quicktime binary
|
||||
module needs to be loaded. It's also used to specify which FFmpeg codec
|
||||
to load. The list of FFmpeg codecs can be found in libavcodec/allcodecs.c.
|
||||
|
||||
The "guid" keyword identifies a 16-byte Microsoft GUID that some media
|
||||
files use to identify codecs. Used only for win32 dshow and DMO codecs.
|
||||
|
||||
The "out" keyword identifies which output format the decoder is known
|
||||
to provide. Just like the fourcc line, there can be multiple out lines or
|
||||
multiple comma-separated output formats on the same line. The output
|
||||
formats should be listed in order of preference.
|
||||
|
||||
The outfmt values can be followed by one or more flags, like flip, noflip,
|
||||
static, query. The flags are defined as follows:
|
||||
|
||||
"flip":
|
||||
If this flag is set for a given format, then o_bih->biHeight will NOT be
|
||||
set to -bih->biHeight, i.e. the image will be decoded upside-down.
|
||||
Used only by vfw and vfwex codecs.
|
||||
|
||||
"noflip":
|
||||
This flag is ignored (no effect) without "flip" being set!
|
||||
If this flag is set, it means the codec doesn't decode upside-down,
|
||||
although it's told to do so.
|
||||
|
||||
"yuvhack":
|
||||
This flag is required for the old win32 ms-mpeg4 vfw codecs, including
|
||||
MP42 and DIV3 (DivX 3.11). These DLLs actually support YUV formats,
|
||||
but the query/begin functions are buggy and don't accept YUV fourccs
|
||||
(the decode function accepts it and works well!)
|
||||
If this flag is set, then o_bih->biCompression will be set to 0 for
|
||||
the initialization for the YUV modes. Used only by vfw/vfwex codecs.
|
||||
|
||||
"query":
|
||||
This flag is used to control VDCTRL_QUERY_FORMAT for vfw/vfewx codecs.
|
||||
If this flag is set, the control() will query the codec for the csp
|
||||
support, otherwise it will assume a constant csp table. Required for
|
||||
some DLLs (like huffyuv, CRAM).
|
||||
|
||||
"static",
|
||||
This flag forces STATIC (instead of TEMP) buffer allocation for the codec.
|
||||
Used for some very old DLLs like Indeo 3 and for some XAnim codecs like
|
||||
cinepak. See dr-methods.txt for details on buffer types.
|
||||
|
||||
The "in" keyword -- UNDOCUMENTED
|
||||
|
||||
Audio Codecs
|
||||
------------
|
||||
Here is an example of a rather full-featured audio codec block:
|
||||
|
||||
audiocodec mp3
|
||||
info "MPEG layer-2, layer-3"
|
||||
status working
|
||||
comment "Optimized to MMX/SSE/3Dnow!"
|
||||
format 0x50
|
||||
format 0x55
|
||||
format 0x33706d2e ; ".mp3" CBR/VBR MP3 (MOV files)
|
||||
format 0x5500736d ; "ms\0\x55" older mp3 fcc (MOV files)
|
||||
driver mp3lib
|
||||
dll "mp3lib (mpglib)"
|
||||
flags seekable
|
||||
|
||||
Many of the keywords are the same as a video codec block. However, we see
|
||||
a few that we haven't seen before. The "comment" keyword identifies
|
||||
another human-readable note for this codec.
|
||||
|
||||
The "format" keyword performs a similar job as the fourcc line. However,
|
||||
since certain media file formats (notably AVI) identify audio formats with
|
||||
16-bit numbers rather than 32-bit FOURCCs, it's necessary to use this
|
||||
convention to accommodate them. However, as shown in this example, FOURCCs
|
||||
can also be specified with the format keyword as long as they're converted
|
||||
to their hex representation. It's important to note that this can be
|
||||
useful for video codecs as well if a FOURCC contains a space (such as
|
||||
Apple's "rle " codec).
|
||||
|
||||
The "flags" keywords identifies any additional abilities of this
|
||||
codec. Currently, seekable is the only supported flag.
|
||||
|
||||
|
||||
Adding FFmpeg Codecs
|
||||
-------------------
|
||||
example codec:
|
||||
|
||||
videocodec ffmdec
|
||||
info "FFmpeg Sony PlayStation MDEC (Motion DECoder)"
|
||||
status working
|
||||
fourcc MDEC ; internal MPlayer FourCC
|
||||
driver ffmpeg
|
||||
dll mdec
|
||||
out YV12
|
||||
|
||||
The "videocodec" name should start with ff to differentiate it from other
|
||||
libraries or binary codecs.
|
||||
|
||||
The "dll" name comes from the codec source file or the libavcodec/allcodecs.c
|
||||
file.
|
||||
|
||||
The "out" colorspace can be found in the codec source file in the PIX_FMT
|
||||
struct. Note that some codecs may have several pix_fmt structs.
|
||||
The pix_fmt can be converted to the codecs.conf "out" format by reading
|
||||
the fmt-conversion.c file.
|
||||
|
||||
If there are BE and LE versions of a pix_fmt, ignore them and use the short
|
||||
native format instead. e.g. 422P16_LE becomes out 422P16. also to note that
|
||||
underscores cause parse errors, so 422P16_LE becomes out 422P16LE.
|
||||
|
||||
libmpdemux/mp_taglists.c
|
||||
--------------
|
||||
Sometimes the lavf demuxer will not pass on a fourcc (mostly video game
|
||||
formats or other containers that do not support isom/riff tags). You will have
|
||||
to make one based on the codec_id listed in the codec source file.
|
||||
|
||||
Note that it is a good idea to mark any fourcc you create as
|
||||
' ; internal MPlayer FourCC'. In case another codec uses that fourcc,
|
||||
you can easily change the internal one. Also this will stop other projects
|
||||
from thinking of the internal tag as a real fourcc found in the wild.
|
||||
|
||||
libmpdemux/demuxer.c
|
||||
--------------
|
||||
Some audio codecs require a parser, you can see which ones do
|
||||
by reading the parsers section in libavcodec/allcodecs.c.
|
||||
|
||||
EOF
|
|
@ -120,6 +120,7 @@ Command line switches
|
|||
-vobsub --sub (pass the .idx file)
|
||||
-ass-bottom-margin --vf=sub=bottom:top
|
||||
-vc ffh264vdpau (etc.) --hwdec=vdpau
|
||||
-ac spdifac3 --ad=spdif:ac3 (see --ad=help)
|
||||
-x W, -y H --geometry=WxH + --no-keepaspect
|
||||
-xy W --autofit=W
|
||||
=================================== ===================================
|
||||
|
|
|
@ -283,7 +283,7 @@ hr-seek x see ``--hr-seek``
|
|||
volume x current volume (0-100)
|
||||
mute x current mute status (bool)
|
||||
audio-delay x see ``--audio-delay``
|
||||
audio-format audio format (codec tag)
|
||||
audio-format audio format (string)
|
||||
audio-codec audio codec selected for decoding
|
||||
audio-bitrate audio bitrate
|
||||
samplerate audio samplerate
|
||||
|
@ -306,7 +306,7 @@ saturation x see ``--saturation``
|
|||
hue x see ``--hue``
|
||||
panscan x see ``--panscan``
|
||||
vsync x see ``--vsync``
|
||||
video-format video format (integer FourCC)
|
||||
video-format video format (string)
|
||||
video-codec video codec selected for decoding
|
||||
video-bitrate video bitrate
|
||||
width video width
|
||||
|
|
|
@ -10,14 +10,32 @@
|
|||
(``--ao=oss`` only) (OBSOLETE)
|
||||
Override audio driver/card buffer size detection.
|
||||
|
||||
--ac=<[-\|+]codec1,[-\|+]codec2,...[,]>
|
||||
Specify a priority list of audio codecs to be used, according to their
|
||||
codec name in codecs.conf. Use a '-' before the codec name to omit it.
|
||||
Use a '+' before the codec name to force it, this will likely crash! If
|
||||
the list has a trailing ',' mpv will fall back on codecs not contained
|
||||
in the list.
|
||||
--ad=<[+|-]family1:(*|decoder1),[+|-]family2:(*|decoder2),...[-]>
|
||||
Specify a priority list of audio decoders to be used, according to their
|
||||
family and decoder name. Entries like ``family:*`` prioritize all decoders
|
||||
of the given family. When determining which decoder to use, the first
|
||||
decoder that matches the audio format is selected. If that is unavailable,
|
||||
the next decoder is used. Finally, it tries all other decoders that are not
|
||||
explicitly selected or rejected by the option.
|
||||
|
||||
*NOTE*: See ``--ac=help`` for a full list of available codecs.
|
||||
``-`` at the end of the list suppresses fallback to other available
|
||||
decoders not on the ``--ad`` list. ``+`` in front of an entry forces the
|
||||
decoder. Both of these shouldn't normally be used, because they break
|
||||
normal decoder auto-selection!
|
||||
|
||||
``-`` in front of an entry disables selection of the decoder.
|
||||
|
||||
*EXAMPLE*:
|
||||
|
||||
``--ad=lavc:mp3float``
|
||||
Prefer the FFmpeg/Libav ``mp3float`` decoder over all other mp3
|
||||
decoders.
|
||||
|
||||
``--ad=spdif:ac3,lavc:*``
|
||||
Always prefer spdif AC3 over FFmpeg/Libav over anything else.
|
||||
|
||||
``--ad=help``
|
||||
List all available decoders.
|
||||
|
||||
--af=<filter1[=parameter1:parameter2:...],filter2,...>
|
||||
Specify a list of audio filters to apply to the audio stream. See
|
||||
|
@ -60,17 +78,6 @@
|
|||
list=<filters>
|
||||
Same as ``--af``.
|
||||
|
||||
--afm=<driver1,driver2,...>
|
||||
Specify a priority list of audio codec families to be used, according to
|
||||
their codec name in codecs.conf. Falls back on the default codecs if none
|
||||
of the given codec families work.
|
||||
|
||||
*NOTE*: See ``--afm=help`` for a full list of available codec families.
|
||||
|
||||
*EXAMPLE*:
|
||||
|
||||
:``--afm=ffmpeg``: Try FFmpeg's libavcodec codecs first.
|
||||
|
||||
--aid=<ID|auto|no>
|
||||
Select audio channel. ``auto`` selects the default, ``no`` disables audio.
|
||||
See also ``--alang``.
|
||||
|
@ -409,10 +416,6 @@
|
|||
the start of the next one then keep playing video normally over the
|
||||
chapter change instead of doing a seek.
|
||||
|
||||
--codecs-file=<filename>
|
||||
Override the standard search path and use the specified file instead of
|
||||
the builtin codecs.conf.
|
||||
|
||||
--colormatrix=<colorspace>
|
||||
Controls the YUV to RGB color space conversion when playing video. There
|
||||
are various standards. Normally, BT.601 should be used for SD video, and
|
||||
|
@ -2257,14 +2260,13 @@
|
|||
Increment verbosity level, one level for each ``-v`` found on the command
|
||||
line.
|
||||
|
||||
--vc=<[-\|+]codec1,[-\|+]codec2,...[,]>
|
||||
Specify a priority list of video codecs to be used, according to their
|
||||
codec name in ``codecs.conf``. Use a '-' before the codec name to omit it.
|
||||
Use a '+' before the codec name to force it, this will likely crash! If
|
||||
the list has a trailing ',' mpv will fall back on codecs not contained
|
||||
in the list.
|
||||
--vd=<[+|-]family1:(*|decoder1),[+|-]family2:(*|decoder2),...[-]>
|
||||
Specify a priority list of video decoders to be used, according to their
|
||||
family and name. See ``--ad`` for further details. Both of these options
|
||||
use the same syntax and semantics, the only difference is that they
|
||||
operate on different codec lists.
|
||||
|
||||
*NOTE*: See ``--vc=help`` for a full list of available codecs.
|
||||
*NOTE*: See ``--vd=help`` for a full list of available decoders.
|
||||
|
||||
--vf=<filter1[=parameter1:parameter2:...],filter2,...>
|
||||
Specify a list of video filters to apply to the video stream. See
|
||||
|
@ -2273,13 +2275,6 @@
|
|||
``--vf-clr`` exist to modify a previously specified list, but you
|
||||
shouldn't need these for typical use.
|
||||
|
||||
--vfm=<driver1,driver2,...>
|
||||
Specify a priority list of video codec families to be used, according to
|
||||
their names in codecs.conf. Falls back on the default codecs if none of
|
||||
the given codec families work.
|
||||
|
||||
*NOTE*: See ``--vfm=help`` for a full list of available codec families.
|
||||
|
||||
--vid=<ID|auto|no>
|
||||
Select video channel. ``auto`` selects the default, ``no`` disables video.
|
||||
|
||||
|
|
|
@ -203,7 +203,5 @@ core/timeline/:
|
|||
segments for playing an ordered chapters file is in tl_matroska.c.
|
||||
|
||||
etc/:
|
||||
The files codecs.conf and input.conf are actually integrated into the
|
||||
mplayer binary by the build system. These files define the default settings.
|
||||
codecs.conf maps video/audio formats to decoders. input.conf contains
|
||||
the default keybindings.
|
||||
The file input.conf is actually integrated into the mpv binary by the
|
||||
build system. It contains the default keybindings.
|
||||
|
|
9
Makefile
9
Makefile
|
@ -151,10 +151,11 @@ SOURCES = talloc.c \
|
|||
audio/out/ao_null.c \
|
||||
audio/out/ao_pcm.c \
|
||||
core/asxparser.c \
|
||||
core/av_common.c \
|
||||
core/av_log.c \
|
||||
core/av_opts.c \
|
||||
core/bstr.c \
|
||||
core/codec-cfg.c \
|
||||
core/codecs.c \
|
||||
core/command.c \
|
||||
core/cpudetect.c \
|
||||
core/defaultopts.c \
|
||||
|
@ -181,6 +182,7 @@ SOURCES = talloc.c \
|
|||
demux/asfheader.c \
|
||||
demux/aviheader.c \
|
||||
demux/aviprint.c \
|
||||
demux/codec_tags.c \
|
||||
demux/demux.c \
|
||||
demux/demux_asf.c \
|
||||
demux/demux_avi.c \
|
||||
|
@ -343,10 +345,6 @@ mpv$(EXESUF): $(OBJECTS)
|
|||
mpv$(EXESUF):
|
||||
$(CC) -o $@ $^ $(EXTRALIBS)
|
||||
|
||||
core/codec-cfg.c: core/codecs.conf.h
|
||||
core/codecs.conf.h: TOOLS/file2string.pl etc/codecs.conf
|
||||
./$^ >$@
|
||||
|
||||
core/input/input.c: core/input/input_conf.h
|
||||
core/input/input_conf.h: TOOLS/file2string.pl etc/input.conf
|
||||
./$^ >$@
|
||||
|
@ -442,7 +440,6 @@ clean:
|
|||
-$(RM) $(call ADD_ALL_EXESUFS,mpv)
|
||||
-$(RM) DOCS/man/en/mpv.1
|
||||
-$(RM) version.h
|
||||
-$(RM) core/codecs.conf.h
|
||||
-$(RM) core/input/input_conf.h
|
||||
-$(RM) video/out/vdpau_template.c
|
||||
-$(RM) demux/ebml_types.h demux/ebml_defs.c
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
/* Missed vorbis, mad, dshow */
|
||||
|
||||
extern const ad_functions_t mpcodecs_ad_mpg123;
|
||||
extern const ad_functions_t mpcodecs_ad_ffmpeg;
|
||||
extern const ad_functions_t mpcodecs_ad_lavc;
|
||||
extern const ad_functions_t mpcodecs_ad_spdif;
|
||||
|
||||
const ad_functions_t * const mpcodecs_ad_drivers[] =
|
||||
|
@ -40,7 +40,7 @@ const ad_functions_t * const mpcodecs_ad_drivers[] =
|
|||
#ifdef CONFIG_MPG123
|
||||
&mpcodecs_ad_mpg123,
|
||||
#endif
|
||||
&mpcodecs_ad_ffmpeg,
|
||||
&mpcodecs_ad_lavc,
|
||||
&mpcodecs_ad_spdif,
|
||||
NULL
|
||||
};
|
||||
|
|
|
@ -19,17 +19,20 @@
|
|||
#ifndef MPLAYER_AD_H
|
||||
#define MPLAYER_AD_H
|
||||
|
||||
#include "core/mpc_info.h"
|
||||
#include "core/codecs.h"
|
||||
#include "demux/stheader.h"
|
||||
|
||||
typedef struct mp_codec_info ad_info_t;
|
||||
|
||||
struct mp_decoder_list;
|
||||
|
||||
/* interface of video decoder drivers */
|
||||
typedef struct ad_functions
|
||||
{
|
||||
const ad_info_t *info;
|
||||
const char *name;
|
||||
void (*add_decoders)(struct mp_decoder_list *list);
|
||||
int (*preinit)(sh_audio_t *sh);
|
||||
int (*init)(sh_audio_t *sh);
|
||||
int (*init)(sh_audio_t *sh, const char *decoder);
|
||||
void (*uninit)(sh_audio_t *sh);
|
||||
int (*control)(sh_audio_t *sh,int cmd,void* arg, ...);
|
||||
int (*decode_audio)(sh_audio_t *sh, unsigned char *buffer, int minlen,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef MPLAYER_AD_INTERNAL_H
|
||||
#define MPLAYER_AD_INTERNAL_H
|
||||
|
||||
#include "core/codec-cfg.h"
|
||||
#include "core/codecs.h"
|
||||
#include "audio/format.h"
|
||||
|
||||
#include "stream/stream.h"
|
||||
|
@ -28,14 +28,16 @@
|
|||
|
||||
#include "ad.h"
|
||||
|
||||
static int init(sh_audio_t *sh);
|
||||
static void add_decoders(struct mp_decoder_list *list);
|
||||
static int init(sh_audio_t *sh, const char *decoder);
|
||||
static int preinit(sh_audio_t *sh);
|
||||
static void uninit(sh_audio_t *sh);
|
||||
static int control(sh_audio_t *sh,int cmd,void* arg, ...);
|
||||
static int decode_audio(sh_audio_t *sh,unsigned char *buffer,int minlen,int maxlen);
|
||||
|
||||
#define LIBAD_EXTERN(x) const ad_functions_t mpcodecs_ad_##x = {\
|
||||
&info,\
|
||||
#x, \
|
||||
add_decoders, \
|
||||
preinit,\
|
||||
init,\
|
||||
uninit,\
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "talloc.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "core/av_common.h"
|
||||
#include "core/codecs.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "core/options.h"
|
||||
|
||||
|
@ -37,17 +39,7 @@
|
|||
#include "compat/mpbswap.h"
|
||||
#include "compat/libav.h"
|
||||
|
||||
static const ad_info_t info =
|
||||
{
|
||||
"libavcodec audio decoders",
|
||||
"ffmpeg",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
.print_name = "libavcodec",
|
||||
};
|
||||
|
||||
LIBAD_EXTERN(ffmpeg)
|
||||
LIBAD_EXTERN(lavc)
|
||||
|
||||
struct priv {
|
||||
AVCodecContext *avctx;
|
||||
|
@ -189,48 +181,26 @@ static int setup_format(sh_audio_t *sh_audio,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int init(sh_audio_t *sh_audio)
|
||||
static int init(sh_audio_t *sh_audio, const char *decoder)
|
||||
{
|
||||
struct MPOpts *opts = sh_audio->opts;
|
||||
AVCodecContext *lavc_context;
|
||||
AVCodec *lavc_codec;
|
||||
|
||||
const char *dll = sh_audio->codec->dll;
|
||||
|
||||
if (sh_audio->wf && dll && strcmp(dll, "pcm") == 0) {
|
||||
if (sh_audio->format == MKTAG('M', 'P', 'a', 'f')) {
|
||||
// demuxer_rawaudio convenience (abuses wFormatTag)
|
||||
dll = find_pcm_decoder(af_map, sh_audio->wf->wFormatTag, 0);
|
||||
} else {
|
||||
dll = find_pcm_decoder(tag_map, sh_audio->format,
|
||||
if (sh_audio->wf && strcmp(decoder, "pcm") == 0) {
|
||||
decoder = find_pcm_decoder(tag_map, sh_audio->format,
|
||||
sh_audio->wf->wBitsPerSample);
|
||||
}
|
||||
} else if (sh_audio->wf && strcmp(decoder, "mp-pcm") == 0) {
|
||||
decoder = find_pcm_decoder(af_map, sh_audio->format, 0);
|
||||
}
|
||||
|
||||
if (dll) {
|
||||
lavc_codec = avcodec_find_decoder_by_name(dll);
|
||||
if (!lavc_codec) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR,
|
||||
"Cannot find codec '%s' in libavcodec...\n", dll);
|
||||
return 0;
|
||||
}
|
||||
} else if (!sh_audio->libav_codec_id) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "No Libav codec ID known. "
|
||||
"Generic lavc decoder is not applicable.\n");
|
||||
lavc_codec = avcodec_find_decoder_by_name(decoder);
|
||||
if (!lavc_codec) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR,
|
||||
"Cannot find codec '%s' in libavcodec...\n", decoder);
|
||||
return 0;
|
||||
} else {
|
||||
lavc_codec = avcodec_find_decoder(sh_audio->libav_codec_id);
|
||||
if (!lavc_codec) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Libavcodec has no decoder "
|
||||
"for this codec\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sh_audio->codecname = lavc_codec->long_name;
|
||||
if (!sh_audio->codecname)
|
||||
sh_audio->codecname = lavc_codec->name;
|
||||
|
||||
struct priv *ctx = talloc_zero(NULL, struct priv);
|
||||
sh_audio->context = ctx;
|
||||
lavc_context = avcodec_alloc_context3(lavc_codec);
|
||||
|
@ -303,7 +273,7 @@ static int init(sh_audio_t *sh_audio)
|
|||
}
|
||||
if (++tries >= 5) {
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
|
||||
"ad_ffmpeg: initial decode failed\n");
|
||||
"ad_lavc: initial decode failed\n");
|
||||
uninit(sh_audio);
|
||||
return 0;
|
||||
}
|
||||
|
@ -328,7 +298,6 @@ static int init(sh_audio_t *sh_audio)
|
|||
|
||||
static void uninit(sh_audio_t *sh)
|
||||
{
|
||||
sh->codecname = NULL;
|
||||
struct priv *ctx = sh->context;
|
||||
if (!ctx)
|
||||
return;
|
||||
|
@ -494,3 +463,10 @@ static int decode_audio(sh_audio_t *sh_audio, unsigned char *buf, int minlen,
|
|||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void add_decoders(struct mp_decoder_list *list)
|
||||
{
|
||||
mp_add_lavc_decoders(list, AVMEDIA_TYPE_AUDIO);
|
||||
mp_add_decoder(list, "lavc", "pcm", "pcm", "Raw PCM");
|
||||
mp_add_decoder(list, "lavc", "mp-pcm", "mp-pcm", "Raw PCM");
|
||||
}
|
||||
|
|
|
@ -26,14 +26,6 @@
|
|||
|
||||
#include "ad_internal.h"
|
||||
|
||||
static const ad_info_t info = {
|
||||
"MPEG 1.0/2.0/2.5 layers I, II, III",
|
||||
"mpg123",
|
||||
"Thomas Orgis",
|
||||
"mpg123.org",
|
||||
"High-performance decoder using libmpg123."
|
||||
};
|
||||
|
||||
LIBAD_EXTERN(mpg123)
|
||||
|
||||
/* Reducing the ifdeffery to two main variants:
|
||||
|
@ -327,7 +319,7 @@ static int reopen_stream(sh_audio_t *sh)
|
|||
* Paranoia note: The mpg123_close() on errors is not really necessary,
|
||||
* But it ensures that we don't accidentally continue decoding with a
|
||||
* bad state (possibly interpreting the format badly or whatnot). */
|
||||
static int init(sh_audio_t *sh)
|
||||
static int init(sh_audio_t *sh, const char *decoder)
|
||||
{
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
|
@ -487,3 +479,9 @@ static int control(sh_audio_t *sh, int cmd, void *arg, ...)
|
|||
}
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
|
||||
static void add_decoders(struct mp_decoder_list *list)
|
||||
{
|
||||
mp_add_decoder(list, "mpg123", "mp3", "mp3",
|
||||
"High-performance decoder using libmpg123");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* Copyright (C) 2012 Naoya OYAMA
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
@ -24,16 +26,9 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "core/av_common.h"
|
||||
#include "ad_internal.h"
|
||||
|
||||
static const ad_info_t info = {
|
||||
"libavformat/spdifenc audio pass-through decoder.",
|
||||
"spdif",
|
||||
"Naoya OYAMA",
|
||||
"Naoya OYAMA",
|
||||
"For ALL hardware decoders"
|
||||
};
|
||||
|
||||
LIBAD_EXTERN(spdif)
|
||||
|
||||
#define FILENAME_SPDIFENC "spdif"
|
||||
|
@ -76,22 +71,21 @@ static int preinit(sh_audio_t *sh)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int init(sh_audio_t *sh)
|
||||
static int codecs[] = {
|
||||
CODEC_ID_AAC,
|
||||
CODEC_ID_AC3,
|
||||
CODEC_ID_DTS,
|
||||
CODEC_ID_EAC3,
|
||||
CODEC_ID_MP3,
|
||||
CODEC_ID_TRUEHD,
|
||||
CODEC_ID_NONE
|
||||
};
|
||||
|
||||
static int init(sh_audio_t *sh, const char *decoder)
|
||||
{
|
||||
int i, x, in_size, srate, bps, *dtshd_rate;
|
||||
int x, in_size, srate, bps, *dtshd_rate;
|
||||
unsigned char *start;
|
||||
double pts;
|
||||
static const struct {
|
||||
const char *name; enum CodecID id;
|
||||
} fmt_id_type[] = {
|
||||
{ "aac" , CODEC_ID_AAC },
|
||||
{ "ac3" , CODEC_ID_AC3 },
|
||||
{ "dca" , CODEC_ID_DTS },
|
||||
{ "eac3", CODEC_ID_EAC3 },
|
||||
{ "mpa" , CODEC_ID_MP3 },
|
||||
{ "thd" , CODEC_ID_TRUEHD },
|
||||
{ NULL , 0 }
|
||||
};
|
||||
AVFormatContext *lavf_ctx = NULL;
|
||||
AVStream *stream = NULL;
|
||||
const AVOption *opt = NULL;
|
||||
|
@ -122,12 +116,7 @@ static int init(sh_audio_t *sh)
|
|||
goto fail;
|
||||
lavf_ctx->duration = AV_NOPTS_VALUE;
|
||||
lavf_ctx->start_time = AV_NOPTS_VALUE;
|
||||
for (i = 0; fmt_id_type[i].name; i++) {
|
||||
if (!strcmp(sh->codec->dll, fmt_id_type[i].name)) {
|
||||
lavf_ctx->streams[0]->codec->codec_id = fmt_id_type[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lavf_ctx->streams[0]->codec->codec_id = mp_codec_to_av_codec_id(decoder);
|
||||
lavf_ctx->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
|
||||
if (AVERROR_PATCHWELCOME == lavf_ctx->oformat->write_header(lavf_ctx)) {
|
||||
mp_msg(MSGT_DECAUDIO,MSGL_INFO,
|
||||
|
@ -306,3 +295,14 @@ static void uninit(sh_audio_t *sh)
|
|||
av_freep(&lavf_ctx);
|
||||
av_freep(&spdif_ctx);
|
||||
}
|
||||
|
||||
static void add_decoders(struct mp_decoder_list *list)
|
||||
{
|
||||
for (int n = 0; codecs[n] != CODEC_ID_NONE; n++) {
|
||||
const char *format = mp_codec_from_av_codec_id(codecs[n]);
|
||||
if (format) {
|
||||
mp_add_decoder(list, "spdif", format, format,
|
||||
"libavformat/spdifenc audio pass-through decoder");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,14 +21,16 @@
|
|||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "demux/codec_tags.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "core/codecs.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "core/bstr.h"
|
||||
|
||||
#include "stream/stream.h"
|
||||
#include "demux/demux.h"
|
||||
|
||||
#include "core/codec-cfg.h"
|
||||
#include "demux/stheader.h"
|
||||
|
||||
#include "dec_audio.h"
|
||||
|
@ -41,27 +43,7 @@ int fakemono = 0;
|
|||
|
||||
struct af_cfg af_cfg = {1, NULL}; // Configuration for audio filters
|
||||
|
||||
void afm_help(void)
|
||||
{
|
||||
int i;
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO,
|
||||
"Available (compiled-in) audio codec families/drivers:\n");
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_DRIVERS\n");
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_INFO, " afm: info: (comment)\n");
|
||||
for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++)
|
||||
if (mpcodecs_ad_drivers[i]->info->comment
|
||||
&& mpcodecs_ad_drivers[i]->info->comment[0])
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s (%s)\n",
|
||||
mpcodecs_ad_drivers[i]->info->short_name,
|
||||
mpcodecs_ad_drivers[i]->info->name,
|
||||
mpcodecs_ad_drivers[i]->info->comment);
|
||||
else
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "%9s %s\n",
|
||||
mpcodecs_ad_drivers[i]->info->short_name,
|
||||
mpcodecs_ad_drivers[i]->info->name);
|
||||
}
|
||||
|
||||
static int init_audio_codec(sh_audio_t *sh_audio)
|
||||
static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder)
|
||||
{
|
||||
assert(!sh_audio->initialized);
|
||||
resync_audio_stream(sh_audio);
|
||||
|
@ -77,7 +59,7 @@ static int init_audio_codec(sh_audio_t *sh_audio)
|
|||
}
|
||||
sh_audio->audio_out_minsize = 8192; // default, preinit() may change it
|
||||
if (!sh_audio->ad_driver->preinit(sh_audio)) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "ADecoder preinit failed :(\n");
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Audio decoder preinit failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -104,8 +86,8 @@ static int init_audio_codec(sh_audio_t *sh_audio)
|
|||
abort();
|
||||
sh_audio->a_buffer_len = 0;
|
||||
|
||||
if (!sh_audio->ad_driver->init(sh_audio)) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "ADecoder init failed :(\n");
|
||||
if (!sh_audio->ad_driver->init(sh_audio, decoder)) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Audio decoder init failed.\n");
|
||||
uninit_audio(sh_audio); // free buffers
|
||||
return 0;
|
||||
}
|
||||
|
@ -125,140 +107,83 @@ static int init_audio_codec(sh_audio_t *sh_audio)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int init_audio(sh_audio_t *sh_audio, char *codecname, char *afm,
|
||||
int status, stringset_t *selected)
|
||||
struct mp_decoder_list *mp_audio_decoder_list(void)
|
||||
{
|
||||
int force = 0;
|
||||
if (codecname && codecname[0] == '+') {
|
||||
codecname = &codecname[1];
|
||||
force = 1;
|
||||
}
|
||||
sh_audio->codec = NULL;
|
||||
while (1) {
|
||||
const ad_functions_t *mpadec;
|
||||
sh_audio->ad_driver = 0;
|
||||
if (!(sh_audio->codec = find_audio_codec(sh_audio->format, NULL,
|
||||
sh_audio->codec, force)))
|
||||
break;
|
||||
// ok we found one codec
|
||||
if (stringset_test(selected, sh_audio->codec->name))
|
||||
continue; // already tried & failed
|
||||
if (codecname && strcmp(sh_audio->codec->name, codecname))
|
||||
continue; // -ac
|
||||
if (afm && strcmp(sh_audio->codec->drv, afm))
|
||||
continue; // afm doesn't match
|
||||
if (!force && sh_audio->codec->status < status)
|
||||
continue; // too unstable
|
||||
stringset_add(selected, sh_audio->codec->name); // tagging it
|
||||
// ok, it matches all rules, let's find the driver!
|
||||
int i;
|
||||
for (i = 0; mpcodecs_ad_drivers[i] != NULL; i++)
|
||||
if (!strcmp(mpcodecs_ad_drivers[i]->info->short_name,
|
||||
sh_audio->codec->drv))
|
||||
break;
|
||||
mpadec = mpcodecs_ad_drivers[i];
|
||||
if (!mpadec) { // driver not available (==compiled in)
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR, "Requested audio codec family "
|
||||
"[%s] (afm=%s) not available.\nEnable it at compilation.\n",
|
||||
sh_audio->codec->name, sh_audio->codec->drv);
|
||||
continue;
|
||||
}
|
||||
// it's available, let's try to init!
|
||||
// init()
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder: [%s] %s\n",
|
||||
mpadec->info->short_name, mpadec->info->name);
|
||||
sh_audio->ad_driver = mpadec;
|
||||
if (!init_audio_codec(sh_audio)) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for "
|
||||
"codecs.conf entry \"%s\".\n", sh_audio->codec->name);
|
||||
continue; // try next...
|
||||
}
|
||||
// Yeah! We got it!
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
|
||||
for (int i = 0; mpcodecs_ad_drivers[i] != NULL; i++)
|
||||
mpcodecs_ad_drivers[i]->add_decoders(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list,
|
||||
char **audio_fm_list)
|
||||
static struct mp_decoder_list *mp_select_audio_decoders(const char *codec,
|
||||
char *selection)
|
||||
{
|
||||
stringset_t selected;
|
||||
char *ac_l_default[2] = {
|
||||
"", (char *) NULL
|
||||
};
|
||||
// hack:
|
||||
if (!audio_codec_list)
|
||||
audio_codec_list = ac_l_default;
|
||||
// Go through the codec.conf and find the best codec...
|
||||
sh_audio->initialized = 0;
|
||||
stringset_init(&selected);
|
||||
while (!sh_audio->initialized && *audio_codec_list) {
|
||||
char *audio_codec = *(audio_codec_list++);
|
||||
if (audio_codec[0]) {
|
||||
if (audio_codec[0] == '-') {
|
||||
// disable this codec:
|
||||
stringset_add(&selected, audio_codec + 1);
|
||||
} else {
|
||||
// forced codec by name:
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Forced audio codec: %s\n",
|
||||
audio_codec);
|
||||
init_audio(sh_audio, audio_codec, NULL, -1, &selected);
|
||||
}
|
||||
} else {
|
||||
int status;
|
||||
// try in stability order: UNTESTED, WORKING, BUGGY.
|
||||
// never try CRASHING.
|
||||
if (audio_fm_list) {
|
||||
char **fmlist = audio_fm_list;
|
||||
// try first the preferred codec families:
|
||||
while (!sh_audio->initialized && *fmlist) {
|
||||
char *audio_fm = *(fmlist++);
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO,
|
||||
"Trying to force audio codec driver family %s...\n",
|
||||
audio_fm);
|
||||
for (status = CODECS_STATUS__MAX;
|
||||
status >= CODECS_STATUS__MIN; --status)
|
||||
if (init_audio(sh_audio, NULL, audio_fm, status,
|
||||
&selected))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sh_audio->initialized)
|
||||
for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN;
|
||||
--status)
|
||||
if (init_audio(sh_audio, NULL, NULL, status, &selected))
|
||||
break;
|
||||
struct mp_decoder_list *list = mp_audio_decoder_list();
|
||||
struct mp_decoder_list *new = mp_select_decoders(list, codec, selection);
|
||||
talloc_free(list);
|
||||
return new;
|
||||
}
|
||||
|
||||
static const struct ad_functions *find_driver(const char *name)
|
||||
{
|
||||
for (int i = 0; mpcodecs_ad_drivers[i] != NULL; i++) {
|
||||
if (strcmp(mpcodecs_ad_drivers[i]->name, name) == 0)
|
||||
return mpcodecs_ad_drivers[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders)
|
||||
{
|
||||
assert(!sh_audio->initialized);
|
||||
|
||||
struct mp_decoder_entry *decoder = NULL;
|
||||
struct mp_decoder_list *list =
|
||||
mp_select_audio_decoders(sh_audio->gsh->codec, audio_decoders);
|
||||
|
||||
mp_print_decoders(MSGT_DECAUDIO, MSGL_V, "Codec list:", list);
|
||||
|
||||
for (int n = 0; n < list->num_entries; n++) {
|
||||
struct mp_decoder_entry *sel = &list->entries[n];
|
||||
const struct ad_functions *driver = find_driver(sel->family);
|
||||
if (!driver)
|
||||
continue;
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Opening audio decoder %s:%s\n",
|
||||
sel->family, sel->decoder);
|
||||
sh_audio->ad_driver = driver;
|
||||
if (init_audio_codec(sh_audio, sel->decoder)) {
|
||||
decoder = sel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
stringset_free(&selected);
|
||||
|
||||
if (!sh_audio->initialized) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_ERR,
|
||||
"Cannot find codec for audio format 0x%X.\n",
|
||||
sh_audio->format);
|
||||
return 0; // failed
|
||||
sh_audio->ad_driver = NULL;
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_WARN, "Audio decoder init failed for "
|
||||
"%s:%s\n", sel->family, sel->decoder);
|
||||
}
|
||||
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s [%s]\n",
|
||||
sh_audio->codecname ? sh_audio->codecname : sh_audio->codec->info,
|
||||
sh_audio->ad_driver->info->print_name ?
|
||||
sh_audio->ad_driver->info->print_name :
|
||||
sh_audio->ad_driver->info->short_name);
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V,
|
||||
"Audio codecs.conf entry: %s (%s) afm: %s\n",
|
||||
sh_audio->codec->name, sh_audio->codec->info, sh_audio->codec->drv);
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_V,
|
||||
"AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n",
|
||||
sh_audio->samplerate, sh_audio->channels,
|
||||
af_fmt2str_short(sh_audio->sample_format),
|
||||
sh_audio->i_bps * 8 * 0.001,
|
||||
((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0,
|
||||
sh_audio->i_bps, sh_audio->o_bps);
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
|
||||
"ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n",
|
||||
sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels);
|
||||
if (sh_audio->initialized) {
|
||||
sh_audio->gsh->decoder_desc =
|
||||
talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family,
|
||||
decoder->decoder);
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_INFO, "Selected audio codec: %s\n",
|
||||
sh_audio->gsh->decoder_desc);
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_V,
|
||||
"AUDIO: %d Hz, %d ch, %s, %3.1f kbit/%3.2f%% (ratio: %d->%d)\n",
|
||||
sh_audio->samplerate, sh_audio->channels,
|
||||
af_fmt2str_short(sh_audio->sample_format),
|
||||
sh_audio->i_bps * 8 * 0.001,
|
||||
((float) sh_audio->i_bps / sh_audio->o_bps) * 100.0,
|
||||
sh_audio->i_bps, sh_audio->o_bps);
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
|
||||
"ID_AUDIO_BITRATE=%d\nID_AUDIO_RATE=%d\n" "ID_AUDIO_NCH=%d\n",
|
||||
sh_audio->i_bps * 8, sh_audio->samplerate, sh_audio->channels);
|
||||
} else {
|
||||
mp_msg(MSGT_DECAUDIO, MSGL_ERR,
|
||||
"Failed to initialize an audio decoder for codec '%s'.\n",
|
||||
sh_audio->gsh->codec ? sh_audio->gsh->codec : "<unknown>");
|
||||
}
|
||||
|
||||
return 1; // success
|
||||
talloc_free(list);
|
||||
return sh_audio->initialized;
|
||||
}
|
||||
|
||||
void uninit_audio(sh_audio_t *sh_audio)
|
||||
|
@ -270,11 +195,12 @@ void uninit_audio(sh_audio_t *sh_audio)
|
|||
sh_audio->afilter = NULL;
|
||||
}
|
||||
if (sh_audio->initialized) {
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio: %s\n",
|
||||
sh_audio->codec->drv);
|
||||
mp_tmsg(MSGT_DECAUDIO, MSGL_V, "Uninit audio.\n");
|
||||
sh_audio->ad_driver->uninit(sh_audio);
|
||||
sh_audio->initialized = 0;
|
||||
}
|
||||
talloc_free(sh_audio->gsh->decoder_desc);
|
||||
sh_audio->gsh->decoder_desc = NULL;
|
||||
av_freep(&sh_audio->a_buffer);
|
||||
av_freep(&sh_audio->a_in_buffer);
|
||||
}
|
||||
|
|
|
@ -22,11 +22,10 @@
|
|||
#include "demux/stheader.h"
|
||||
|
||||
struct bstr;
|
||||
struct mp_decoder_list;
|
||||
|
||||
// dec_audio.c:
|
||||
void afm_help(void);
|
||||
int init_best_audio_codec(sh_audio_t *sh_audio, char **audio_codec_list,
|
||||
char **audio_fm_list);
|
||||
struct mp_decoder_list *mp_audio_decoder_list(void);
|
||||
int init_best_audio_codec(sh_audio_t *sh_audio, char *audio_decoders);
|
||||
int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen);
|
||||
void decode_audio_prepend_bytes(struct bstr *outbuf, int count, int byte);
|
||||
void resync_audio_stream(sh_audio_t *sh_audio);
|
||||
|
|
|
@ -22,13 +22,7 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "core/bstr.h"
|
||||
|
||||
#define CONTROL_OK 1
|
||||
#define CONTROL_TRUE 1
|
||||
#define CONTROL_FALSE 0
|
||||
#define CONTROL_UNKNOWN -1
|
||||
#define CONTROL_ERROR -2
|
||||
#define CONTROL_NA -3
|
||||
#include "core/mp_common.h"
|
||||
|
||||
enum aocontrol {
|
||||
// _VOLUME commands take struct ao_control_vol pointer for input/output.
|
||||
|
|
|
@ -2663,6 +2663,28 @@ else
|
|||
fi
|
||||
|
||||
|
||||
echocheck "libavcodec AVCodecDescriptor API"
|
||||
_avcodec_codec_desc_api=no
|
||||
statement_check libavcodec/avcodec.h 'const AVCodecDescriptor *desc = avcodec_descriptor_get_by_name("c")' $_ld_tmp && _avcodec_codec_desc_api=yes
|
||||
if test "$_avcodec_codec_desc_api" = yes ; then
|
||||
def_avcodec_codec_desc_api='#define HAVE_AVCODEC_CODEC_DESC_API 1'
|
||||
else
|
||||
def_avcodec_codec_desc_api='#define HAVE_AVCODEC_CODEC_DESC_API 0'
|
||||
fi
|
||||
echores "$_avcodec_codec_desc_api"
|
||||
|
||||
|
||||
echocheck "libavcodec av_codec_is_decoder API"
|
||||
_avcodec_is_decoder_api=no
|
||||
statement_check libavcodec/avcodec.h 'av_codec_is_decoder(NULL)' $_ld_tmp && _avcodec_is_decoder_api=yes
|
||||
if test "$_avcodec_is_decoder_api" = yes ; then
|
||||
def_avcodec_is_decoder_api='#define HAVE_AVCODEC_IS_DECODER_API 1'
|
||||
else
|
||||
def_avcodec_is_decoder_api='#define HAVE_AVCODEC_IS_DECODER_API 0'
|
||||
fi
|
||||
echores "$_avcodec_is_decoder_api"
|
||||
|
||||
|
||||
echocheck "libavfilter >= 3.17.0"
|
||||
if test "$libavfilter" = auto ; then
|
||||
libavfilter=no
|
||||
|
@ -3158,6 +3180,8 @@ $def_vcd
|
|||
$def_mpg123
|
||||
$def_zlib
|
||||
|
||||
$def_avcodec_codec_desc_api
|
||||
$def_avcodec_is_decoder_api
|
||||
$def_libpostproc
|
||||
$def_libavdevice
|
||||
$def_libavfilter
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "core/mp_talloc.h"
|
||||
#include "av_common.h"
|
||||
#include "codecs.h"
|
||||
|
||||
|
||||
#if !HAVE_AVCODEC_IS_DECODER_API
|
||||
static int av_codec_is_decoder(AVCodec *codec)
|
||||
{
|
||||
return !!codec->decode;
|
||||
}
|
||||
#endif
|
||||
|
||||
void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type)
|
||||
{
|
||||
AVCodec *cur = NULL;
|
||||
for (;;) {
|
||||
cur = av_codec_next(cur);
|
||||
if (!cur)
|
||||
break;
|
||||
if (av_codec_is_decoder(cur) && cur->type == type) {
|
||||
struct mp_decoder_entry entry = {
|
||||
.family = "lavc",
|
||||
.codec = mp_codec_from_av_codec_id(cur->id),
|
||||
.decoder = cur->name,
|
||||
.desc = cur->long_name,
|
||||
};
|
||||
assert(entry.family);
|
||||
MP_TARRAY_APPEND(list, list->entries, list->num_entries, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_AVCODEC_CODEC_DESC_API
|
||||
|
||||
int mp_codec_to_av_codec_id(const char *codec)
|
||||
{
|
||||
|
||||
const AVCodecDescriptor *desc = avcodec_descriptor_get_by_name(codec);
|
||||
return desc ? desc->id : CODEC_ID_NONE;
|
||||
}
|
||||
|
||||
const char *mp_codec_from_av_codec_id(int codec_id)
|
||||
{
|
||||
const AVCodecDescriptor *desc = avcodec_descriptor_get(codec_id);
|
||||
return desc ? desc->name : NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct mp_av_codec {
|
||||
const char *name;
|
||||
int codec_id;
|
||||
};
|
||||
|
||||
// Some decoders have a different name from the canonical codec name, for
|
||||
// example the codec "dts" CODEC_ID_DTS has the decoder named "dca", and
|
||||
// avcodec_find_decoder_by_name("dts") would return 0. We always want the
|
||||
// canonical name.
|
||||
// On newer lavc versions, avcodec_descriptor_get_by_name("dts") will return
|
||||
// CODEC_ID_DTS, which is what we want, but for older versions we need this
|
||||
// lookup table.
|
||||
struct mp_av_codec mp_av_codec_id_list[] = {
|
||||
{"ra_144", CODEC_ID_RA_144},
|
||||
{"ra_288", CODEC_ID_RA_288},
|
||||
{"smackaudio", CODEC_ID_SMACKAUDIO},
|
||||
{"dts", CODEC_ID_DTS},
|
||||
{"musepack7", CODEC_ID_MUSEPACK7},
|
||||
{"musepack8", CODEC_ID_MUSEPACK8},
|
||||
{"amr_nb", CODEC_ID_AMR_NB},
|
||||
{"amr_wb", CODEC_ID_AMR_WB},
|
||||
{"adpcm_g722", CODEC_ID_ADPCM_G722},
|
||||
{"adpcm_g726", CODEC_ID_ADPCM_G726},
|
||||
{"westwood_snd1", CODEC_ID_WESTWOOD_SND1},
|
||||
{"mp4als", CODEC_ID_MP4ALS},
|
||||
{"vixl", CODEC_ID_VIXL},
|
||||
{"flv1", CODEC_ID_FLV1},
|
||||
{"msmpeg4v3", CODEC_ID_MSMPEG4V3},
|
||||
{"jpeg2000", CODEC_ID_JPEG2000},
|
||||
{"ulti", CODEC_ID_ULTI},
|
||||
{"smackvideo", CODEC_ID_SMACKVIDEO},
|
||||
{"tscc", CODEC_ID_TSCC},
|
||||
{"cscd", CODEC_ID_CSCD},
|
||||
{"tgv", CODEC_ID_TGV},
|
||||
{"roq", CODEC_ID_ROQ},
|
||||
{"idcin", CODEC_ID_IDCIN},
|
||||
{"ws_vqa", CODEC_ID_WS_VQA},
|
||||
{0},
|
||||
};
|
||||
|
||||
int mp_codec_to_av_codec_id(const char *codec)
|
||||
{
|
||||
for (int n = 0; mp_av_codec_id_list[n].name; n++) {
|
||||
if (strcmp(mp_av_codec_id_list[n].name, codec) == 0)
|
||||
return mp_av_codec_id_list[n].codec_id;
|
||||
}
|
||||
AVCodec *avcodec = avcodec_find_decoder_by_name(codec);
|
||||
return avcodec ? avcodec->id : CODEC_ID_NONE;
|
||||
}
|
||||
|
||||
const char *mp_codec_from_av_codec_id(int codec_id)
|
||||
{
|
||||
for (int n = 0; mp_av_codec_id_list[n].name; n++) {
|
||||
if (mp_av_codec_id_list[n].codec_id == codec_id)
|
||||
return mp_av_codec_id_list[n].name;
|
||||
}
|
||||
AVCodec *avcodec = avcodec_find_decoder(codec_id);
|
||||
return avcodec ? avcodec->name : NULL;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MP_AVCOMMON_H
|
||||
#define MP_AVCOMMON_H
|
||||
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
struct mp_decoder_list;
|
||||
|
||||
void mp_add_lavc_decoders(struct mp_decoder_list *list, enum AVMediaType type);
|
||||
int mp_codec_to_av_codec_id(const char *codec);
|
||||
const char *mp_codec_from_av_codec_id(int codec_id);
|
||||
|
||||
#endif
|
|
@ -439,11 +439,9 @@ const m_option_t common_opts[] = {
|
|||
{"af-adv", (void *) audio_filter_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
|
||||
|
||||
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list),
|
||||
// select audio/video codec (by name) or codec family (by number):
|
||||
{"afm", &audio_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
|
||||
{"vfm", &video_fm_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
|
||||
{"ac", &audio_codec_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
|
||||
{"vc", &video_codec_list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
|
||||
|
||||
OPT_STRING("ad", audio_decoders, 0),
|
||||
OPT_STRING("vd", video_decoders, 0),
|
||||
|
||||
OPT_CHOICE("hwdec", hwdec_api, 0,
|
||||
({"no", 0},
|
||||
|
@ -473,7 +471,6 @@ const m_option_t common_opts[] = {
|
|||
|
||||
{"lavdopts", (void *) lavc_decode_opts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
|
||||
{"lavfdopts", (void *) lavfdopts_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
|
||||
OPT_STRING("codecs-file", codecs_file, 0),
|
||||
// ------------------------- subtitles options --------------------
|
||||
|
||||
OPT_STRINGLIST("sub", sub_name, 0),
|
||||
|
|
607
core/codec-cfg.c
607
core/codec-cfg.c
|
@ -1,607 +0,0 @@
|
|||
/*
|
||||
* codecs.conf parser
|
||||
*
|
||||
* Copyright (C) 2001 Szabolcs Berecz <szabi@inf.elte.hu>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "video/img_format.h"
|
||||
#include "codec-cfg.h"
|
||||
#include "core/bstr.h"
|
||||
#include "stream/stream.h"
|
||||
#include "core/path.h"
|
||||
|
||||
static const char embedded_file[] =
|
||||
#include "codecs.conf.h"
|
||||
;
|
||||
static const struct bstr builtin_codecs_conf = {
|
||||
.start = (char *)embedded_file, .len = sizeof(embedded_file) - 1
|
||||
};
|
||||
|
||||
#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
|
||||
( (uint32_t)(uint8_t)(ch0) | ( (uint32_t)(uint8_t)(ch1) << 8 ) | \
|
||||
( (uint32_t)(uint8_t)(ch2) << 16 ) | ( (uint32_t)(uint8_t)(ch3) << 24 ) )
|
||||
|
||||
#define PRINT_LINENUM mp_msg(MSGT_CODECCFG,MSGL_ERR," at line %d\n", line_num)
|
||||
|
||||
#define MAX_NR_TOKEN 16
|
||||
|
||||
#define RET_EOF -1
|
||||
#define RET_EOL -2
|
||||
|
||||
#define TYPE_VIDEO 0
|
||||
#define TYPE_AUDIO 1
|
||||
|
||||
static int add_to_fourcc(char *s, char *alias, unsigned int *fourcc,
|
||||
unsigned int *map)
|
||||
{
|
||||
int i, j, freeslots;
|
||||
unsigned int tmp;
|
||||
|
||||
/* find first unused slot */
|
||||
for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
|
||||
/* NOTHING */;
|
||||
freeslots = CODECS_MAX_FOURCC - i;
|
||||
if (!freeslots)
|
||||
goto err_out_too_many;
|
||||
|
||||
do {
|
||||
if (strlen(s) < 4)
|
||||
goto err_out_parse_error;
|
||||
tmp = mmioFOURCC(s[0], s[1], s[2], s[3]);
|
||||
for (j = 0; j < i; j++)
|
||||
if (tmp == fourcc[j])
|
||||
goto err_out_duplicated;
|
||||
fourcc[i] = tmp;
|
||||
map[i] = alias ? mmioFOURCC(alias[0], alias[1], alias[2], alias[3]) : tmp;
|
||||
s += 4;
|
||||
i++;
|
||||
} while ((*(s++) == ',') && --freeslots);
|
||||
|
||||
if (!freeslots)
|
||||
goto err_out_too_many;
|
||||
if (*(--s) != '\0')
|
||||
goto err_out_parse_error;
|
||||
return 1;
|
||||
err_out_duplicated:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated FourCC");
|
||||
return 0;
|
||||
err_out_too_many:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
|
||||
return 0;
|
||||
err_out_parse_error:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_to_format(char *s, char *alias,unsigned int *fourcc, unsigned int *fourccmap)
|
||||
{
|
||||
int i, j;
|
||||
char *endptr;
|
||||
|
||||
/* find first unused slot */
|
||||
for (i = 0; i < CODECS_MAX_FOURCC && fourcc[i] != 0xffffffff; i++)
|
||||
/* NOTHING */;
|
||||
if (i == CODECS_MAX_FOURCC) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"too many FourCCs/formats...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fourcc[i]=strtoul(s,&endptr,0);
|
||||
if (*endptr != '\0') {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID not a number?)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(alias){
|
||||
fourccmap[i]=strtoul(alias,&endptr,0);
|
||||
if (*endptr != '\0') {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error (format ID alias not a number?)");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
fourccmap[i]=fourcc[i];
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
if (fourcc[j] == fourcc[i]) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"duplicated format ID");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int validate_codec(codecs_t *c, int type)
|
||||
{
|
||||
unsigned int i;
|
||||
char *tmp_name = c->name;
|
||||
|
||||
for (i = 0; i < strlen(tmp_name) && isalnum(tmp_name[i]); i++)
|
||||
/* NOTHING */;
|
||||
|
||||
if (i < strlen(tmp_name)) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) name is not valid!\n", c->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!c->info)
|
||||
c->info = strdup(c->name);
|
||||
|
||||
if (!c->drv) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"\ncodec(%s) does not have a driver!\n", c->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int add_comment(char *s, char **d)
|
||||
{
|
||||
int pos;
|
||||
|
||||
if (!*d)
|
||||
pos = 0;
|
||||
else {
|
||||
pos = strlen(*d);
|
||||
(*d)[pos++] = '\n';
|
||||
}
|
||||
if (!(*d = realloc(*d, pos + strlen(s) + 1))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't allocate memory for comment. ");
|
||||
return 0;
|
||||
}
|
||||
strcpy(*d + pos, s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct bstr filetext;
|
||||
static int line_num = 0;
|
||||
static char *line;
|
||||
static char *token[MAX_NR_TOKEN];
|
||||
static int read_nextline = 1;
|
||||
|
||||
static int get_token(int min, int max)
|
||||
{
|
||||
static int line_pos;
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if (max >= MAX_NR_TOKEN) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"get_token(): max >= MAX_MR_TOKEN!");
|
||||
goto out_eof;
|
||||
}
|
||||
|
||||
memset(token, 0x00, sizeof(*token) * max);
|
||||
|
||||
if (read_nextline) {
|
||||
if (!filetext.len)
|
||||
goto out_eof;
|
||||
struct bstr nextline = bstr_getline(filetext, &filetext);
|
||||
line = nextline.start;
|
||||
line[nextline.len - 1] = 0;
|
||||
line_pos = 0;
|
||||
++line_num;
|
||||
read_nextline = 0;
|
||||
}
|
||||
for (i = 0; i < max; i++) {
|
||||
while (isspace(line[line_pos]))
|
||||
++line_pos;
|
||||
if (line[line_pos] == '\0' || line[line_pos] == '#' ||
|
||||
line[line_pos] == ';') {
|
||||
read_nextline = 1;
|
||||
if (i >= min)
|
||||
goto out_ok;
|
||||
goto out_eol;
|
||||
}
|
||||
token[i] = line + line_pos;
|
||||
c = line[line_pos];
|
||||
if (c == '"' || c == '\'') {
|
||||
token[i]++;
|
||||
while (line[++line_pos] != c && line[line_pos])
|
||||
/* NOTHING */;
|
||||
} else {
|
||||
for (/* NOTHING */; !isspace(line[line_pos]) &&
|
||||
line[line_pos]; line_pos++)
|
||||
/* NOTHING */;
|
||||
}
|
||||
if (!line[line_pos]) {
|
||||
read_nextline = 1;
|
||||
if (i >= min - 1)
|
||||
goto out_ok;
|
||||
goto out_eol;
|
||||
}
|
||||
line[line_pos] = '\0';
|
||||
line_pos++;
|
||||
}
|
||||
out_ok:
|
||||
return i;
|
||||
out_eof:
|
||||
read_nextline = 1;
|
||||
return RET_EOF;
|
||||
out_eol:
|
||||
return RET_EOL;
|
||||
}
|
||||
|
||||
static codecs_t *video_codecs=NULL;
|
||||
static codecs_t *audio_codecs=NULL;
|
||||
static int nr_vcodecs = 0;
|
||||
static int nr_acodecs = 0;
|
||||
|
||||
int parse_codec_cfg(const char *cfgfile)
|
||||
{
|
||||
codecs_t *codec = NULL; // current codec
|
||||
codecs_t **codecsp = NULL;// points to audio_codecs or to video_codecs
|
||||
char *endptr; // strtoul()...
|
||||
int *nr_codecsp;
|
||||
int codec_type; /* TYPE_VIDEO/TYPE_AUDIO */
|
||||
int tmp, i;
|
||||
int codec_cfg_min;
|
||||
|
||||
for (struct bstr s = builtin_codecs_conf; ; bstr_getline(s, &s)) {
|
||||
if (!s.len)
|
||||
abort();
|
||||
if (bstr_eatstart0(&s, "release ")) {
|
||||
codec_cfg_min = atoi(s.start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// in case we call it a second time
|
||||
codecs_uninit_free();
|
||||
|
||||
nr_vcodecs = 0;
|
||||
nr_acodecs = 0;
|
||||
|
||||
if (cfgfile) {
|
||||
// Avoid printing errors from open_stream when trying optional files
|
||||
if (!mp_path_exists(cfgfile)) {
|
||||
mp_tmsg(MSGT_CODECCFG, MSGL_V,
|
||||
"No optional codecs config file: %s\n", cfgfile);
|
||||
return 0;
|
||||
}
|
||||
mp_msg(MSGT_CODECCFG, MSGL_V, "Reading codec config file: %s\n",
|
||||
cfgfile);
|
||||
struct stream *s = open_stream(cfgfile, NULL, NULL);
|
||||
if (!s)
|
||||
return 0;
|
||||
filetext = stream_read_complete(s, NULL, 10000000, 1);
|
||||
free_stream(s);
|
||||
if (!filetext.start)
|
||||
return 0;
|
||||
} else
|
||||
// Parsing modifies the data
|
||||
filetext = bstrdup(NULL, builtin_codecs_conf);
|
||||
void *tmpmem = filetext.start;
|
||||
|
||||
read_nextline = 1;
|
||||
|
||||
/*
|
||||
* this only catches release lines at the start of
|
||||
* codecs.conf, before audiocodecs and videocodecs.
|
||||
*/
|
||||
while ((tmp = get_token(1, 1)) == RET_EOL)
|
||||
/* NOTHING */;
|
||||
if (tmp == RET_EOF)
|
||||
goto out;
|
||||
if (!strcmp(token[0], "release")) {
|
||||
if (get_token(1, 2) < 0)
|
||||
goto err_out_parse_error;
|
||||
tmp = atoi(token[0]);
|
||||
if (tmp < codec_cfg_min)
|
||||
goto err_out_release_num;
|
||||
while ((tmp = get_token(1, 1)) == RET_EOL)
|
||||
/* NOTHING */;
|
||||
if (tmp == RET_EOF)
|
||||
goto out;
|
||||
} else
|
||||
goto err_out_release_num;
|
||||
|
||||
/*
|
||||
* check if the next block starts with 'audiocodec' or
|
||||
* with 'videocodec'
|
||||
*/
|
||||
if (!strcmp(token[0], "audiocodec") || !strcmp(token[0], "videocodec"))
|
||||
goto loop_enter;
|
||||
goto err_out_parse_error;
|
||||
|
||||
while ((tmp = get_token(1, 1)) != RET_EOF) {
|
||||
if (tmp == RET_EOL)
|
||||
continue;
|
||||
if (!strcmp(token[0], "audiocodec") ||
|
||||
!strcmp(token[0], "videocodec")) {
|
||||
if (!validate_codec(codec, codec_type))
|
||||
goto err_out_not_valid;
|
||||
loop_enter:
|
||||
if (*token[0] == 'v') {
|
||||
codec_type = TYPE_VIDEO;
|
||||
nr_codecsp = &nr_vcodecs;
|
||||
codecsp = &video_codecs;
|
||||
} else {
|
||||
assert(*token[0] == 'a');
|
||||
codec_type = TYPE_AUDIO;
|
||||
nr_codecsp = &nr_acodecs;
|
||||
codecsp = &audio_codecs;
|
||||
}
|
||||
if (!(*codecsp = realloc(*codecsp,
|
||||
sizeof(codecs_t) * (*nr_codecsp + 2)))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_FATAL,"Can't realloc '*codecsp': %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
codec=*codecsp + *nr_codecsp;
|
||||
++*nr_codecsp;
|
||||
memset(codec,0,sizeof(codecs_t));
|
||||
memset(codec->fourcc, 0xff, sizeof(codec->fourcc));
|
||||
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
for (i = 0; i < *nr_codecsp - 1; i++) {
|
||||
if(( (*codecsp)[i].name!=NULL) &&
|
||||
(!strcmp(token[0], (*codecsp)[i].name)) ) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec name '%s' isn't unique.", token[0]);
|
||||
goto err_out_print_linenum;
|
||||
}
|
||||
}
|
||||
if (!(codec->name = strdup(token[0]))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'name': %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
} else if (!strcmp(token[0], "info")) {
|
||||
if (codec->info || get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!(codec->info = strdup(token[0]))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'info': %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
} else if (!strcmp(token[0], "comment")) {
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
add_comment(token[0], &codec->comment);
|
||||
} else if (!strcmp(token[0], "fourcc")) {
|
||||
if (get_token(1, 2) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!add_to_fourcc(token[0], token[1],
|
||||
codec->fourcc,
|
||||
codec->fourccmap))
|
||||
goto err_out_print_linenum;
|
||||
} else if (!strcmp(token[0], "format")) {
|
||||
if (get_token(1, 2) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!add_to_format(token[0], token[1],
|
||||
codec->fourcc,codec->fourccmap))
|
||||
goto err_out_print_linenum;
|
||||
} else if (!strcmp(token[0], "driver")) {
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!(codec->drv = strdup(token[0]))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'driver': %s\n", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
} else if (!strcmp(token[0], "dll")) {
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!(codec->dll = strdup(token[0]))) {
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Can't strdup -> 'dll': %s", strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
} else if (!strcmp(token[0], "guid")) {
|
||||
if (get_token(11, 11) < 0)
|
||||
goto err_out_parse_error;
|
||||
codec->guid.f1=strtoul(token[0],&endptr,0);
|
||||
if ((*endptr != ',' || *(endptr + 1) != '\0') &&
|
||||
*endptr != '\0')
|
||||
goto err_out_parse_error;
|
||||
codec->guid.f2=strtoul(token[1],&endptr,0);
|
||||
if ((*endptr != ',' || *(endptr + 1) != '\0') &&
|
||||
*endptr != '\0')
|
||||
goto err_out_parse_error;
|
||||
codec->guid.f3=strtoul(token[2],&endptr,0);
|
||||
if ((*endptr != ',' || *(endptr + 1) != '\0') &&
|
||||
*endptr != '\0')
|
||||
goto err_out_parse_error;
|
||||
for (i = 0; i < 8; i++) {
|
||||
codec->guid.f4[i]=strtoul(token[i + 3],&endptr,0);
|
||||
if ((*endptr != ',' || *(endptr + 1) != '\0') &&
|
||||
*endptr != '\0')
|
||||
goto err_out_parse_error;
|
||||
}
|
||||
} else if (!strcmp(token[0], "flags")) {
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!strcmp(token[0], "flip"))
|
||||
codec->flags |= CODECS_FLAG_FLIP;
|
||||
else
|
||||
goto err_out_parse_error;
|
||||
} else if (!strcmp(token[0], "status")) {
|
||||
if (get_token(1, 1) < 0)
|
||||
goto err_out_parse_error;
|
||||
if (!strcasecmp(token[0], "working"))
|
||||
codec->status = CODECS_STATUS_WORKING;
|
||||
else if (!strcasecmp(token[0], "crashing"))
|
||||
codec->status = CODECS_STATUS_NOT_WORKING;
|
||||
else if (!strcasecmp(token[0], "untested"))
|
||||
codec->status = CODECS_STATUS_UNTESTED;
|
||||
else if (!strcasecmp(token[0], "buggy"))
|
||||
codec->status = CODECS_STATUS_PROBLEMS;
|
||||
else
|
||||
goto err_out_parse_error;
|
||||
} else if (!strcmp(token[0], "anyinput")) {
|
||||
codec->anyinput = true;
|
||||
} else
|
||||
goto err_out_parse_error;
|
||||
}
|
||||
if (!validate_codec(codec, codec_type))
|
||||
goto err_out_not_valid;
|
||||
mp_tmsg(MSGT_CODECCFG, MSGL_V, "%d audio & %d video codecs\n", nr_acodecs,
|
||||
nr_vcodecs);
|
||||
if(video_codecs) video_codecs[nr_vcodecs].name = NULL;
|
||||
if(audio_codecs) audio_codecs[nr_acodecs].name = NULL;
|
||||
out:
|
||||
talloc_free(tmpmem);
|
||||
line=NULL;
|
||||
return 1;
|
||||
|
||||
err_out_parse_error:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"parse error");
|
||||
err_out_print_linenum:
|
||||
PRINT_LINENUM;
|
||||
err_out:
|
||||
codecs_uninit_free();
|
||||
|
||||
talloc_free(tmpmem);
|
||||
line=NULL;
|
||||
line_num = 0;
|
||||
return 0;
|
||||
err_out_not_valid:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"Codec is not defined correctly.");
|
||||
goto err_out_print_linenum;
|
||||
err_out_release_num:
|
||||
mp_tmsg(MSGT_CODECCFG,MSGL_ERR,"This codecs.conf is too old and incompatible with this MPlayer release!");
|
||||
goto err_out_print_linenum;
|
||||
}
|
||||
|
||||
static void codecs_free(codecs_t* codecs,int count) {
|
||||
int i;
|
||||
for ( i = 0; i < count; i++)
|
||||
if ( codecs[i].name ) {
|
||||
free(codecs[i].name);
|
||||
free(codecs[i].info);
|
||||
free(codecs[i].comment);
|
||||
free(codecs[i].dll);
|
||||
free(codecs[i].drv);
|
||||
}
|
||||
free(codecs);
|
||||
}
|
||||
|
||||
void codecs_uninit_free(void) {
|
||||
if (video_codecs)
|
||||
codecs_free(video_codecs,nr_vcodecs);
|
||||
video_codecs=NULL;
|
||||
if (audio_codecs)
|
||||
codecs_free(audio_codecs,nr_acodecs);
|
||||
audio_codecs=NULL;
|
||||
}
|
||||
|
||||
codecs_t *find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int force)
|
||||
{
|
||||
return find_codec(fourcc, fourccmap, start, 1, force);
|
||||
}
|
||||
|
||||
codecs_t *find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int force)
|
||||
{
|
||||
return find_codec(fourcc, fourccmap, start, 0, force);
|
||||
}
|
||||
|
||||
struct codecs *find_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int audioflag, int force)
|
||||
{
|
||||
struct codecs *c, *end;
|
||||
|
||||
if (audioflag) {
|
||||
c = audio_codecs;
|
||||
end = c + nr_acodecs;
|
||||
} else {
|
||||
c = video_codecs;
|
||||
end = c + nr_vcodecs;
|
||||
}
|
||||
if (start)
|
||||
c = start + 1; // actually starts from the next one after the given one
|
||||
for (; c < end; c++) {
|
||||
for (int j = 0; j < CODECS_MAX_FOURCC; j++) {
|
||||
if (c->fourcc[j] == -1)
|
||||
break;
|
||||
if (c->fourcc[j] == fourcc) {
|
||||
if (fourccmap)
|
||||
*fourccmap = c->fourccmap[j];
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (c->anyinput || force)
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void stringset_init(stringset_t *set) {
|
||||
*set = calloc(1, sizeof(char *));
|
||||
}
|
||||
|
||||
void stringset_free(stringset_t *set) {
|
||||
int count = 0;
|
||||
while ((*set)[count]) free((*set)[count++]);
|
||||
free(*set);
|
||||
*set = NULL;
|
||||
}
|
||||
|
||||
void stringset_add(stringset_t *set, const char *str) {
|
||||
int count = 0;
|
||||
while ((*set)[count]) count++;
|
||||
count++;
|
||||
*set = realloc(*set, sizeof(char *) * (count + 1));
|
||||
(*set)[count - 1] = strdup(str);
|
||||
(*set)[count] = NULL;
|
||||
}
|
||||
|
||||
int stringset_test(stringset_t *set, const char *str) {
|
||||
stringset_t s;
|
||||
for (s = *set; *s; s++)
|
||||
if (strcmp(*s, str) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void list_codecs(int audioflag){
|
||||
int i;
|
||||
codecs_t *c;
|
||||
|
||||
if (audioflag) {
|
||||
i = nr_acodecs;
|
||||
c = audio_codecs;
|
||||
mp_msg(MSGT_CODECCFG,MSGL_INFO,"ac: afm: status: info: [lib/dll]\n");
|
||||
} else {
|
||||
i = nr_vcodecs;
|
||||
c = video_codecs;
|
||||
mp_msg(MSGT_CODECCFG,MSGL_INFO,"vc: vfm: status: info: [lib/dll]\n");
|
||||
}
|
||||
if(!i) return;
|
||||
for (/* NOTHING */; i--; c++) {
|
||||
char* s="unknown ";
|
||||
switch(c->status){
|
||||
case CODECS_STATUS_WORKING: s="working ";break;
|
||||
case CODECS_STATUS_PROBLEMS: s="problems";break;
|
||||
case CODECS_STATUS_NOT_WORKING: s="crashing";break;
|
||||
case CODECS_STATUS_UNTESTED: s="untested";break;
|
||||
}
|
||||
if(c->dll)
|
||||
mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s [%s]\n",c->name,c->drv,s,c->info,c->dll);
|
||||
else
|
||||
mp_msg(MSGT_CODECCFG,MSGL_INFO,"%-11s %-9s %s %s\n",c->name,c->drv,s,c->info);
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_CODEC_CFG_H
|
||||
#define MPLAYER_CODEC_CFG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CODECS_MAX_FOURCC 92
|
||||
|
||||
// Global flags:
|
||||
#define CODECS_FLAG_FLIP (1<<0)
|
||||
|
||||
#define CODECS_STATUS__MIN 0
|
||||
#define CODECS_STATUS_NOT_WORKING -1
|
||||
#define CODECS_STATUS_PROBLEMS 0
|
||||
#define CODECS_STATUS_WORKING 1
|
||||
#define CODECS_STATUS_UNTESTED 2
|
||||
#define CODECS_STATUS__MAX 2
|
||||
|
||||
|
||||
#if !defined(GUID_TYPE) && !defined(GUID_DEFINED)
|
||||
#define GUID_TYPE 1
|
||||
#define GUID_DEFINED 1
|
||||
typedef struct {
|
||||
unsigned long f1;
|
||||
unsigned short f2;
|
||||
unsigned short f3;
|
||||
unsigned char f4[8];
|
||||
} GUID;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct codecs {
|
||||
unsigned int fourcc[CODECS_MAX_FOURCC];
|
||||
unsigned int fourccmap[CODECS_MAX_FOURCC];
|
||||
char *name;
|
||||
char *info;
|
||||
char *comment;
|
||||
char *dll;
|
||||
char* drv;
|
||||
GUID guid;
|
||||
short flags;
|
||||
short status;
|
||||
bool anyinput;
|
||||
} codecs_t;
|
||||
|
||||
int parse_codec_cfg(const char *cfgfile);
|
||||
codecs_t* find_video_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int force);
|
||||
codecs_t* find_audio_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int force);
|
||||
codecs_t* find_codec(unsigned int fourcc, unsigned int *fourccmap,
|
||||
codecs_t *start, int audioflag, int force);
|
||||
void list_codecs(int audioflag);
|
||||
void codecs_uninit_free(void);
|
||||
|
||||
typedef char ** stringset_t;
|
||||
void stringset_init(stringset_t *set);
|
||||
void stringset_free(stringset_t *set);
|
||||
void stringset_add(stringset_t *set, const char *str);
|
||||
int stringset_test(stringset_t *set, const char *str);
|
||||
|
||||
#endif /* MPLAYER_CODEC_CFG_H */
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "core/mp_talloc.h"
|
||||
#include "core/bstr.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "codecs.h"
|
||||
|
||||
void mp_add_decoder(struct mp_decoder_list *list, const char *family,
|
||||
const char *codec, const char *decoder, const char *desc)
|
||||
{
|
||||
struct mp_decoder_entry entry = {
|
||||
.family = talloc_strdup(list, family),
|
||||
.codec = talloc_strdup(list, codec),
|
||||
.decoder = talloc_strdup(list, decoder),
|
||||
.desc = talloc_strdup(list, desc),
|
||||
};
|
||||
MP_TARRAY_APPEND(list, list->entries, list->num_entries, entry);
|
||||
}
|
||||
|
||||
static void mp_add_decoder_entry(struct mp_decoder_list *list,
|
||||
struct mp_decoder_entry *entry)
|
||||
{
|
||||
mp_add_decoder(list, entry->family, entry->codec, entry->decoder,
|
||||
entry->desc);
|
||||
}
|
||||
|
||||
static struct mp_decoder_entry *find_decoder(struct mp_decoder_list *list,
|
||||
bstr family, bstr decoder)
|
||||
{
|
||||
for (int n = 0; n < list->num_entries; n++) {
|
||||
struct mp_decoder_entry *cur = &list->entries[n];
|
||||
if (bstr_equals0(decoder, cur->decoder) &&
|
||||
bstr_equals0(family, cur->family))
|
||||
return cur;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add entry, but only if it's not yet on the list, and if the codec matches.
|
||||
// If codec == NULL, don't compare codecs.
|
||||
static void add_new(struct mp_decoder_list *to, struct mp_decoder_entry *entry,
|
||||
const char *codec)
|
||||
{
|
||||
if (!entry || (codec && strcmp(entry->codec, codec) != 0))
|
||||
return;
|
||||
if (!find_decoder(to, bstr0(entry->family), bstr0(entry->decoder)))
|
||||
mp_add_decoder_entry(to, entry);
|
||||
}
|
||||
|
||||
// Select a decoder from the given list for the given codec. The selection
|
||||
// can be influenced by the selection string, which can specify a priority
|
||||
// list of preferred decoders.
|
||||
// This returns a list of decoders to try, with the preferred decoders first.
|
||||
// The selection string corresponds to --vd/--ad directly, and has the
|
||||
// following syntax:
|
||||
// selection = [<entry> ("," <entry>)*]
|
||||
// entry = <family> ":" <decoder> // prefer decoder
|
||||
// entry = <family> ":*" // prefer all decoders
|
||||
// entry = "+" <family> ":" <decoder> // force a decoder
|
||||
// entry = "-" <family> ":" <decoder> // exclude a decoder
|
||||
// entry = "-" // don't add fallback decoders
|
||||
// Forcing a decoder means it's added even if the codec mismatches.
|
||||
struct mp_decoder_list *mp_select_decoders(struct mp_decoder_list *all,
|
||||
const char *codec,
|
||||
const char *selection)
|
||||
{
|
||||
struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
|
||||
struct mp_decoder_list *remove = talloc_zero(NULL, struct mp_decoder_list);
|
||||
if (!codec)
|
||||
codec = "unknown";
|
||||
bool stop = false;
|
||||
bstr sel = bstr0(selection);
|
||||
while (sel.len) {
|
||||
bstr entry;
|
||||
bstr_split_tok(sel, ",", &entry, &sel);
|
||||
if (bstr_equals0(entry, "-")) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
bool force = bstr_eatstart0(&entry, "+");
|
||||
bool exclude = !force && bstr_eatstart0(&entry, "-");
|
||||
struct mp_decoder_list *dest = exclude ? remove : list;
|
||||
bstr family, decoder;
|
||||
if (!bstr_split_tok(entry, ":", &family, &decoder)) {
|
||||
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Decoders must be specified as "
|
||||
"'family:decoder' for the --ad/--vd options.\n");
|
||||
break;
|
||||
}
|
||||
if (bstr_equals0(decoder, "*")) {
|
||||
for (int n = 0; n < all->num_entries; n++) {
|
||||
struct mp_decoder_entry *cur = &all->entries[n];
|
||||
if (bstr_equals0(family, cur->family))
|
||||
add_new(dest, cur, codec);
|
||||
}
|
||||
} else {
|
||||
add_new(dest, find_decoder(all, family, decoder),
|
||||
force ? NULL : codec);
|
||||
}
|
||||
}
|
||||
if (!stop) {
|
||||
// Add the remaining codecs which haven't been added yet
|
||||
for (int n = 0; n < all->num_entries; n++)
|
||||
add_new(list, &all->entries[n], codec);
|
||||
}
|
||||
for (int n = 0; n < remove->num_entries; n++) {
|
||||
struct mp_decoder_entry *ex = &remove->entries[n];
|
||||
struct mp_decoder_entry *del =
|
||||
find_decoder(list, bstr0(ex->family), bstr0(ex->decoder));
|
||||
if (del) {
|
||||
int index = del - &list->entries[0];
|
||||
MP_TARRAY_REMOVE_AT(list->entries, list->num_entries, index);
|
||||
}
|
||||
}
|
||||
talloc_free(remove);
|
||||
return list;
|
||||
}
|
||||
|
||||
void mp_print_decoders(int msgt, int msgl, const char *header,
|
||||
struct mp_decoder_list *list)
|
||||
{
|
||||
mp_msg(msgt, msgl, "%s\n", header);
|
||||
for (int n = 0; n < list->num_entries; n++) {
|
||||
struct mp_decoder_entry *entry = &list->entries[n];
|
||||
mp_msg(msgt, msgl, " %s:%s", entry->family, entry->decoder);
|
||||
if (strcmp(entry->decoder, entry->codec) != 0)
|
||||
mp_msg(msgt, msgl, " (%s)", entry->codec);
|
||||
mp_msg(msgt, msgl, " - %s\n", entry->desc);
|
||||
}
|
||||
if (list->num_entries == 0)
|
||||
mp_msg(msgt, msgl, " (no decoders)\n");
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MP_CODECS_H
|
||||
#define MP_CODECS_H
|
||||
|
||||
struct mp_decoder_entry {
|
||||
const char *family; // decoder module (e.g. ad_lavc => "lavc")
|
||||
const char *codec; // name of the codec (e.g. "mp3")
|
||||
const char *decoder; // decoder name (e.g. "mp3float")
|
||||
const char *desc; // human readable description
|
||||
};
|
||||
|
||||
struct mp_decoder_list {
|
||||
struct mp_decoder_entry *entries;
|
||||
int num_entries;
|
||||
};
|
||||
|
||||
void mp_add_decoder(struct mp_decoder_list *list, const char *family,
|
||||
const char *codec, const char *decoder, const char *desc);
|
||||
|
||||
struct mp_decoder_list *mp_select_decoders(struct mp_decoder_list *all,
|
||||
const char *codec,
|
||||
const char *selection);
|
||||
|
||||
void mp_print_decoders(int msgt, int msgl, const char *header,
|
||||
struct mp_decoder_list *list);
|
||||
|
||||
#endif
|
|
@ -30,7 +30,6 @@
|
|||
#include "stream/stream.h"
|
||||
#include "demux/demux.h"
|
||||
#include "demux/stheader.h"
|
||||
#include "codec-cfg.h"
|
||||
#include "mplayer.h"
|
||||
#include "playlist.h"
|
||||
#include "playlist_parser.h"
|
||||
|
@ -603,22 +602,16 @@ static int mp_property_audio_delay(m_option_t *prop, int action,
|
|||
static int mp_property_audio_format(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->sh_audio)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
return m_property_int_ro(prop, action, arg, mpctx->sh_audio->format);
|
||||
const char *c = mpctx->sh_audio ? mpctx->sh_audio->gsh->codec : NULL;
|
||||
return m_property_strdup_ro(prop, action, arg, c);
|
||||
}
|
||||
|
||||
/// Audio codec name (RO)
|
||||
static int mp_property_audio_codec(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->sh_audio || !mpctx->sh_audio->codec)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (action == M_PROPERTY_GET) {
|
||||
*(char **)arg = talloc_strdup(NULL, mpctx->sh_audio->codec->name);
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
const char *c = mpctx->sh_audio ? mpctx->sh_audio->gsh->decoder_desc : NULL;
|
||||
return m_property_strdup_ro(prop, action, arg, c);
|
||||
}
|
||||
|
||||
/// Audio bitrate (RO)
|
||||
|
@ -1103,51 +1096,16 @@ static int mp_property_vsync(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_video_format(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
char *meta;
|
||||
if (!mpctx->sh_video)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
switch (action) {
|
||||
case M_PROPERTY_PRINT:
|
||||
switch (mpctx->sh_video->format) {
|
||||
case 0x10000001:
|
||||
meta = talloc_strdup(NULL, "mpeg1");
|
||||
break;
|
||||
case 0x10000002:
|
||||
meta = talloc_strdup(NULL, "mpeg2");
|
||||
break;
|
||||
case 0x10000004:
|
||||
meta = talloc_strdup(NULL, "mpeg4");
|
||||
break;
|
||||
case 0x10000005:
|
||||
meta = talloc_strdup(NULL, "h264");
|
||||
break;
|
||||
default:
|
||||
if (mpctx->sh_video->format >= 0x20202020) {
|
||||
meta = talloc_asprintf(NULL, "%.4s",
|
||||
(char *) &mpctx->sh_video->format);
|
||||
} else
|
||||
meta = talloc_asprintf(NULL, "0x%08X", mpctx->sh_video->format);
|
||||
}
|
||||
*(char **)arg = meta;
|
||||
return M_PROPERTY_OK;
|
||||
case M_PROPERTY_GET:
|
||||
*(int *)arg = mpctx->sh_video->format;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
const char *c = mpctx->sh_video ? mpctx->sh_video->gsh->codec : NULL;
|
||||
return m_property_strdup_ro(prop, action, arg, c);
|
||||
}
|
||||
|
||||
/// Video codec name (RO)
|
||||
static int mp_property_video_codec(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->sh_video || !mpctx->sh_video->codec)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (action == M_PROPERTY_GET) {
|
||||
*(char **)arg = talloc_strdup(NULL, mpctx->sh_video->codec->name);
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
const char *c = mpctx->sh_video ? mpctx->sh_video->gsh->decoder_desc : NULL;
|
||||
return m_property_strdup_ro(prop, action, arg, c);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1395,7 +1353,7 @@ static const m_option_t mp_properties[] = {
|
|||
{ "mute", mp_property_mute, CONF_TYPE_FLAG,
|
||||
M_OPT_RANGE, 0, 1, NULL },
|
||||
M_OPTION_PROPERTY_CUSTOM("audio-delay", mp_property_audio_delay),
|
||||
{ "audio-format", mp_property_audio_format, CONF_TYPE_INT,
|
||||
{ "audio-format", mp_property_audio_format, CONF_TYPE_STRING,
|
||||
0, 0, 0, NULL },
|
||||
{ "audio-codec", mp_property_audio_codec, CONF_TYPE_STRING,
|
||||
0, 0, 0, NULL },
|
||||
|
@ -1435,7 +1393,7 @@ static const m_option_t mp_properties[] = {
|
|||
.offset = offsetof(struct MPOpts, vo_gamma_hue)),
|
||||
M_OPTION_PROPERTY_CUSTOM("panscan", mp_property_panscan),
|
||||
M_OPTION_PROPERTY_CUSTOM_("vsync", mp_property_vsync),
|
||||
{ "video-format", mp_property_video_format, CONF_TYPE_INT,
|
||||
{ "video-format", mp_property_video_format, CONF_TYPE_STRING,
|
||||
0, 0, 0, NULL },
|
||||
{ "video-codec", mp_property_video_codec, CONF_TYPE_STRING,
|
||||
0, 0, 0, NULL },
|
||||
|
|
|
@ -10,6 +10,8 @@ void set_default_mplayer_options(struct MPOpts *opts)
|
|||
*opts = (const struct MPOpts){
|
||||
.audio_driver_list = NULL,
|
||||
.video_driver_list = NULL,
|
||||
.audio_decoders = "-spdif:*", // never select spdif by default
|
||||
.video_decoders = NULL,
|
||||
.fixed_vo = 1,
|
||||
.softvol = SOFTVOL_AUTO,
|
||||
.softvol_max = 200,
|
||||
|
|
|
@ -358,6 +358,8 @@ int m_property_strdup_ro(const struct m_option* prop, int action, void* arg,
|
|||
const char *var)
|
||||
{
|
||||
if (action == M_PROPERTY_GET) {
|
||||
if (!var)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
*(char **)arg = talloc_strdup(NULL, var);
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,13 @@
|
|||
|
||||
#define ROUND(x) ((int)((x) < 0 ? (x) - 0.5 : (x) + 0.5))
|
||||
|
||||
#define CONTROL_OK 1
|
||||
#define CONTROL_TRUE 1
|
||||
#define CONTROL_FALSE 0
|
||||
#define CONTROL_UNKNOWN -1
|
||||
#define CONTROL_ERROR -2
|
||||
#define CONTROL_NA -3
|
||||
|
||||
extern const char *mplayer_version;
|
||||
extern const char *mplayer_builddate;
|
||||
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_MPC_INFO_H
|
||||
#define MPLAYER_MPC_INFO_H
|
||||
|
||||
struct mp_codec_info
|
||||
{
|
||||
/* codec long name ("Autodesk FLI/FLC Animation decoder" */
|
||||
const char *name;
|
||||
/* short name (same as driver name in codecs.conf) ("dshow") */
|
||||
const char *short_name;
|
||||
/* interface author/maintainer */
|
||||
const char *maintainer;
|
||||
/* codec author ("Aaron Holtzman <aholtzma@ess.engr.uvic.ca>") */
|
||||
const char *author;
|
||||
/* any additional comments */
|
||||
const char *comment;
|
||||
const char *print_name;
|
||||
};
|
||||
|
||||
#define CONTROL_OK 1
|
||||
#define CONTROL_TRUE 1
|
||||
#define CONTROL_FALSE 0
|
||||
#define CONTROL_UNKNOWN -1
|
||||
#define CONTROL_ERROR -2
|
||||
#define CONTROL_NA -3
|
||||
|
||||
#endif /* MPLAYER_MPC_INFO_H */
|
|
@ -86,7 +86,7 @@
|
|||
|
||||
#include "audio/out/ao.h"
|
||||
|
||||
#include "core/codec-cfg.h"
|
||||
#include "core/codecs.h"
|
||||
|
||||
#include "sub/spudec.h"
|
||||
|
||||
|
@ -203,12 +203,6 @@ static int drop_frame_cnt; // total number of dropped frames
|
|||
static int64_t seek_to_byte;
|
||||
static double step_sec;
|
||||
|
||||
// codecs:
|
||||
char **audio_codec_list; // override audio codec
|
||||
char **video_codec_list; // override video codec
|
||||
char **audio_fm_list; // override audio codec family
|
||||
char **video_fm_list; // override video codec family
|
||||
|
||||
// this dvdsub_id was selected via slang
|
||||
// use this to allow dvdnav to follow -slang across stream resets,
|
||||
// in particular the subtitle ID for a language changes
|
||||
|
@ -314,37 +308,12 @@ static void print_stream(struct MPContext *mpctx, struct track *t, int id)
|
|||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " [P]");
|
||||
if (t->title)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " '%s'", t->title);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (");
|
||||
if (s && s->common_header->format) {
|
||||
int format = s->common_header->format;
|
||||
// not sure about endian crap
|
||||
char name[sizeof(format) + 1] = {0};
|
||||
memcpy(name, &format, sizeof(format));
|
||||
bool ok = true;
|
||||
for (int n = 0; name[n]; n++) {
|
||||
if ((name[n] < 32 || name[n] >= 128) && name[n] != 0)
|
||||
ok = false;
|
||||
}
|
||||
if (ok && strlen(name) > 0) {
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", name);
|
||||
} else {
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%#x", format);
|
||||
}
|
||||
} else if (s && t->type == STREAM_SUB) {
|
||||
char t = s->sub->type;
|
||||
const char *name = NULL;
|
||||
switch (t) {
|
||||
case 't': name = "SRT"; break;
|
||||
case 'a': name = "ASS"; break;
|
||||
case 'v': name = "VobSub"; break;
|
||||
}
|
||||
if (!name)
|
||||
name = (char[2]){t, '\0'};
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", name);
|
||||
}
|
||||
if (s && s->common_header->demuxer_codecname)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "/%s", s->common_header->demuxer_codecname);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, ")");
|
||||
const char *codec = s ? s->codec : NULL;
|
||||
if (s && t->type == STREAM_SUB)
|
||||
codec = sh_sub_type2str(s->sub->type);
|
||||
if (t->sh_sub) // external subs hack
|
||||
codec = sh_sub_type2str(t->sh_sub->type);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (%s)", codec ? codec : "<unknown>");
|
||||
if (t->is_external)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (external)");
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
|
||||
|
@ -1590,7 +1559,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
|||
goto no_audio;
|
||||
}
|
||||
if (!(mpctx->initialized_flags & INITIALIZED_ACODEC)) {
|
||||
if (!init_best_audio_codec(mpctx->sh_audio, audio_codec_list, audio_fm_list))
|
||||
if (!init_best_audio_codec(mpctx->sh_audio, opts->audio_decoders))
|
||||
goto init_error;
|
||||
mpctx->initialized_flags |= INITIALIZED_ACODEC;
|
||||
}
|
||||
|
@ -2414,17 +2383,13 @@ int reinit_video_chain(struct MPContext *mpctx)
|
|||
mpctx->osd->render_subs_in_filter
|
||||
= vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE;
|
||||
|
||||
init_best_video_codec(sh_video, video_codec_list, video_fm_list);
|
||||
init_best_video_codec(sh_video, opts->video_decoders);
|
||||
|
||||
if (!sh_video->initialized)
|
||||
goto err_out;
|
||||
|
||||
mpctx->initialized_flags |= INITIALIZED_VCODEC;
|
||||
|
||||
if (sh_video->codec)
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
|
||||
"ID_VIDEO_CODEC=%s\n", sh_video->codec->name);
|
||||
|
||||
sh_video->last_pts = MP_NOPTS_VALUE;
|
||||
sh_video->num_buffered_pts = 0;
|
||||
sh_video->next_frame_time = 0;
|
||||
|
@ -4261,33 +4226,21 @@ static bool handle_help_options(struct MPContext *mpctx)
|
|||
list_audio_out();
|
||||
opt_exit = 1;
|
||||
}
|
||||
if (audio_codec_list && strcmp(audio_codec_list[0], "help") == 0) {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Available audio codecs:\n");
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_CODECS\n");
|
||||
list_codecs(1);
|
||||
mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
|
||||
if (opts->audio_decoders && strcmp(opts->audio_decoders, "help") == 0) {
|
||||
struct mp_decoder_list *list = mp_audio_decoder_list();
|
||||
mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Audio decoders:", list);
|
||||
talloc_free(list);
|
||||
opt_exit = 1;
|
||||
}
|
||||
if (video_codec_list && strcmp(video_codec_list[0], "help") == 0) {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Available video codecs:\n");
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_CODECS\n");
|
||||
list_codecs(0);
|
||||
mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
|
||||
opt_exit = 1;
|
||||
}
|
||||
if (video_fm_list && strcmp(video_fm_list[0], "help") == 0) {
|
||||
vfm_help();
|
||||
mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
|
||||
opt_exit = 1;
|
||||
}
|
||||
if (audio_fm_list && strcmp(audio_fm_list[0], "help") == 0) {
|
||||
afm_help();
|
||||
mp_msg(MSGT_FIXME, MSGL_FIXME, "\n");
|
||||
if (opts->video_decoders && strcmp(opts->video_decoders, "help") == 0) {
|
||||
struct mp_decoder_list *list = mp_video_decoder_list();
|
||||
mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Video decoders:", list);
|
||||
talloc_free(list);
|
||||
opt_exit = 1;
|
||||
}
|
||||
if (af_cfg.list && strcmp(af_cfg.list[0], "help") == 0) {
|
||||
af_help();
|
||||
printf("\n");
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
|
||||
opt_exit = 1;
|
||||
}
|
||||
#ifdef CONFIG_X11
|
||||
|
@ -4315,15 +4268,6 @@ static bool handle_help_options(struct MPContext *mpctx)
|
|||
return opt_exit;
|
||||
}
|
||||
|
||||
static bool load_codecs_conf(struct MPContext *mpctx)
|
||||
{
|
||||
/* Check codecs.conf. */
|
||||
if (mpctx->opts.codecs_file && parse_codec_cfg(mpctx->opts.codecs_file))
|
||||
return true;
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_V, "Using built-in default codecs.conf.\n");
|
||||
return parse_codec_cfg(NULL);
|
||||
}
|
||||
|
||||
#ifdef PTW32_STATIC_LIB
|
||||
static void detach_ptw32(void)
|
||||
{
|
||||
|
@ -4415,9 +4359,6 @@ int main(int argc, char *argv[])
|
|||
exit_player(mpctx, EXIT_ERROR, 1);
|
||||
}
|
||||
|
||||
if (!load_codecs_conf(mpctx))
|
||||
exit_player(mpctx, EXIT_ERROR, 1);
|
||||
|
||||
if (handle_help_options(mpctx))
|
||||
exit_player(mpctx, EXIT_NONE, 1);
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ typedef struct MPOpts {
|
|||
char** vo_fstype_list;
|
||||
int vo_stop_screensaver;
|
||||
|
||||
char *audio_decoders;
|
||||
char *video_decoders;
|
||||
|
||||
// ranges -100 - 100, 1000 if the vo default should be used
|
||||
int vo_gamma_gamma;
|
||||
int vo_gamma_brightness;
|
||||
|
@ -55,7 +58,6 @@ typedef struct MPOpts {
|
|||
int chapter_merge_threshold;
|
||||
int quiet;
|
||||
int load_config;
|
||||
char *codecs_file;
|
||||
int stream_cache_size;
|
||||
float stream_cache_min_percent;
|
||||
float stream_cache_seek_min_percent;
|
||||
|
|
|
@ -349,6 +349,7 @@ static int asf_init_audio_stream(demuxer_t *demuxer,struct asf_priv* asf, sh_aud
|
|||
memcpy(sh_audio->wf,buffer,streamh->type_size);
|
||||
le2me_WAVEFORMATEX(sh_audio->wf);
|
||||
sh_audio->format=sh_audio->wf->wFormatTag;
|
||||
mp_set_audio_codec_from_tag(sh_audio);
|
||||
if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
|
||||
if(ASF_LOAD_GUID_PREFIX(streamh->concealment)==ASF_GUID_PREFIX_audio_conceal_interleave){
|
||||
buffer = &hdr[pos];
|
||||
|
@ -516,6 +517,9 @@ int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
|
|||
sh_video->bih->biHeight;
|
||||
}
|
||||
sh_video->i_bps = asf->bps;
|
||||
sh_video->format = sh_video->bih->biCompression;
|
||||
mp_set_video_codec_from_tag(sh_video);
|
||||
sh_video->format = mp_video_fourcc_alias(sh_video->format);
|
||||
|
||||
if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
|
||||
//asf_video_id=streamh.stream_no & 0x7F;
|
||||
|
|
|
@ -279,6 +279,8 @@ while(1){
|
|||
sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
|
||||
sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
|
||||
sh_video->format = sh_video->bih->biCompression;
|
||||
mp_set_video_codec_from_tag(sh_video);
|
||||
sh_video->format = mp_video_fourcc_alias(sh_video->format);
|
||||
// if(demuxer->video->id==-1) demuxer->video->id=stream_id;
|
||||
// IdxFix:
|
||||
idxfix_videostream=stream_id;
|
||||
|
@ -335,6 +337,7 @@ while(1){
|
|||
if (sh_audio->format == 1 &&
|
||||
last_fccHandler == mmioFOURCC('A', 'x', 'a', 'n'))
|
||||
sh_audio->format = last_fccHandler;
|
||||
mp_set_audio_codec_from_tag(sh_audio);
|
||||
sh_audio->i_bps=sh_audio->wf->nAvgBytesPerSec;
|
||||
chunksize=0;
|
||||
if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf,MSGL_V);
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/common.h>
|
||||
#include "codec_tags.h"
|
||||
#include "stheader.h"
|
||||
#include "core/av_common.h"
|
||||
|
||||
/* The following tables map FourCCs to codec names (as defined by libavcodec).
|
||||
* However, this includes only names that are not defined by libavformat's
|
||||
* RIFF tag tables, or which are mapped differently (for unknown reasons).
|
||||
* These mappings were extracted from the codecs.conf file when it was removed,
|
||||
* and these mappings have been maintained for years, meaning they are well
|
||||
* tested and possibly make some files work. Or they could just be bugs.
|
||||
*
|
||||
* Note that demux_lavf does not use these tables, and always uses the native
|
||||
* libavformat mappings.
|
||||
*
|
||||
* Note about internal mplayer FourCCs:
|
||||
*
|
||||
* These are made-up FourCCs which don't actually show up in files, but which
|
||||
* were used by the original MPlayer to identify codecs. Since we don't quite
|
||||
* know/care if there are still some uses of them left, they're still here.
|
||||
*/
|
||||
|
||||
struct mp_codec_tag {
|
||||
uint32_t tag;
|
||||
const char *codec;
|
||||
};
|
||||
|
||||
static const struct mp_codec_tag mp_audio_codec_tags[] = {
|
||||
{MKTAG('Q', 'D', 'M', '2'), "qdm2"},
|
||||
{MKTAG('Q', 'c', 'l', 'p'), "qcelp"},
|
||||
{MKTAG('s', 'q', 'c', 'p'), "qcelp"},
|
||||
{MKTAG('Q', 'c', 'l', 'q'), "qcelp"},
|
||||
{MKTAG('1', '4', '_', '4'), "ra_144"},
|
||||
{MKTAG('l', 'p', 'c', 'J'), "ra_144"},
|
||||
{MKTAG('2', '8', '_', '8'), "ra_288"},
|
||||
{MKTAG('c', 'o', 'o', 'k'), "cook"},
|
||||
{MKTAG('a', 't', 'r', 'c'), "atrac3"},
|
||||
{MKTAG('s', 'i', 'p', 'r'), "sipr"},
|
||||
{MKTAG('S', 'M', 'K', 'A'), "smackaudio"},
|
||||
{MKTAG('A', 'x', 'a', 'n'), "xan_dpcm"},
|
||||
{0x594a , "xan_dpcm"},
|
||||
{MKTAG('T', 'H', 'P', 'A'), "adpcm_thp"},
|
||||
{MKTAG('R', 'A', 'D', 'V'), "dvaudio"},
|
||||
{MKTAG('v', 'd', 'v', 'a'), "dvaudio"},
|
||||
{MKTAG('d', 'v', 'c', 'a'), "dvaudio"},
|
||||
{MKTAG('d', 'v', 'a', 'u'), "dvaudio"},
|
||||
{MKTAG('m', 'p', '4', 'a'), "aac"},
|
||||
{MKTAG('M', 'P', '4', 'A'), "aac"},
|
||||
{MKTAG('r', 'a', 'a', 'c'), "aac"},
|
||||
{MKTAG('r', 'a', 'c', 'p'), "aac"},
|
||||
{0xa106 , "aac"}, // libav 0.8: -, ffmpeg 1.1: aac
|
||||
{0xaac0 , "aac"},
|
||||
{MKTAG('f', 'L', 'a', 'C'), "flac"},
|
||||
{MKTAG('m', 's', 241, 172), "flac"},
|
||||
{MKTAG('a', 'l', 'a', 'c'), "alac"},
|
||||
{MKTAG('A', 'P', 'E', ' '), "ape"},
|
||||
{MKTAG('d', 'a', 'u', 'd'), "pcm_s24daud"},
|
||||
{MKTAG('W', 'M', 'A', '3'), "wmapro"},
|
||||
{MKTAG('M', 'A', 'C', '3'), "mace3"},
|
||||
{MKTAG('M', 'A', 'C', '6'), "mace6"},
|
||||
{MKTAG('S', 'O', 'N', 'C'), "sonic"},
|
||||
{0x2048 , "sonic"}, // libav 0.8: -, ffmpeg 1.1: sonic
|
||||
{MKTAG('T', 'S', 0 , 'U'), "mp3"},
|
||||
{MKTAG('G', 'S', 'M', ' '), "gsm"},
|
||||
{0x1500 , "gsm"}, // lavf: gsm_ms
|
||||
{MKTAG('a', 'g', 's', 'm'), "gsm"},
|
||||
{0x32 , "gsm_ms"},
|
||||
{MKTAG(1 , 0 , 1 , 0 ), "pcm_dvd"},
|
||||
{MKTAG('B', 'S', 'S', 'D'), "s302m"},
|
||||
{MKTAG('A', 'C', '-', '3'), "ac3"},
|
||||
{MKTAG('d', 'n', 'e', 't'), "ac3"},
|
||||
{MKTAG('s', 'a', 'c', '3'), "ac3"},
|
||||
{MKTAG('E', 'A', 'C', '3'), "eac3"},
|
||||
{0x86 , "dts"},
|
||||
{MKTAG('M', 'P', 'C', ' '), "musepack7"},
|
||||
{MKTAG('M', 'P', 'C', '8'), "musepack8"},
|
||||
{MKTAG('M', 'P', 'C', 'K'), "musepack8"},
|
||||
{MKTAG('s', 'a', 'm', 'r'), "amr_nb"},
|
||||
{MKTAG('s', 'a', 'w', 'b'), "amr_wb"},
|
||||
{MKTAG('v', 'r', 'b', 's'), "vorbis"},
|
||||
// Special cased in ad_lavc:
|
||||
{0 , "pcm"},
|
||||
{0x1 , "pcm"}, // lavf: pcm_s16le
|
||||
{0x3 , "pcm"}, // lavf: pcm_f32le
|
||||
{0xfffe , "pcm"},
|
||||
// ------- internal mplayer FourCCs ------
|
||||
{MKTAG('S', 'a', 'd', 'x'), "adpcm_adx"},
|
||||
{MKTAG('A', 'M', 'V', 'A'), "adpcm_ima_amv"},
|
||||
{MKTAG('R', 'o', 'Q', 'A'), "roq_dpcm"},
|
||||
{MKTAG('B', 'A', 'U', '1'), "binkaudio_dct"},
|
||||
{MKTAG('B', 'A', 'U', '2'), "binkaudio_rdft"},
|
||||
{MKTAG('D', 'C', 'I', 'A'), "dsicinaudio"},
|
||||
{MKTAG('4', 'X', 'M', 'A'), "adpcm_4xm"},
|
||||
{MKTAG('A', 'I', 'W', 'S'), "adpcm_ima_ws"},
|
||||
{MKTAG('S', 'N', 'D', '1'), "westwood_snd1"},
|
||||
{MKTAG('I', 'N', 'P', 'A'), "interplay_dpcm"},
|
||||
{MKTAG('A', 'D', 'E', 'A'), "adpcm_ea"},
|
||||
{MKTAG('A', 'D', 'X', 'A'), "adpcm_ea_maxis_xa"},
|
||||
{MKTAG('P', 'S', 'X', 'A'), "adpcm_xa"},
|
||||
{MKTAG('M', 'P', '4', 'L'), "aac_latm"},
|
||||
{MKTAG('T', 'T', 'A', '1'), "tta"},
|
||||
{MKTAG('W', 'V', 'P', 'K'), "wavpack"},
|
||||
{MKTAG('s', 'h', 'r', 'n'), "shorten"},
|
||||
{MKTAG('A', 'L', 'S', ' '), "mp4als"},
|
||||
{MKTAG('M', 'L', 'P', ' '), "mlp"},
|
||||
{MKTAG('T', 'R', 'H', 'D'), "truehd"},
|
||||
{MKTAG('N', 'E', 'L', 'L'), "nellymoser"},
|
||||
{MKTAG('m', '4', 'a', 29 ), "mp3on4"},
|
||||
{MKTAG('a', 'd', 'u', 'U'), "mp3adu"},
|
||||
{MKTAG('B', 'P', 'C', 'M'), "pcm_bluray"},
|
||||
{MKTAG('P', 'L', 'X', 'F'), "pcm_lxf"},
|
||||
{MKTAG('T', 'W', 'I', '2'), "twinvq"},
|
||||
{0x20776172, "pcm"}, // demux_mpg.c dvdpcm
|
||||
{0},
|
||||
};
|
||||
|
||||
static const struct mp_codec_tag mp_video_codec_tags[] = {
|
||||
{MKTAG('V', 'B', 'V', '1'), "vb"},
|
||||
{MKTAG('M', 'L', '2', '0'), "mimic"},
|
||||
{MKTAG('R', '1', '0', 'g'), "r10k"},
|
||||
{MKTAG('m', '1', 'v', '1'), "mpeg1video"},
|
||||
{MKTAG('m', 'p', 'g', '2'), "mpeg2video"}, // lavf: mpeg1video
|
||||
{MKTAG('M', 'P', 'G', '2'), "mpeg2video"}, // lavf: mpeg1video
|
||||
{MKTAG('m', 'x', '5', 'p'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '1'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '2'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '3'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '4'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '5'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '6'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '7'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '8'), "mpeg2video"},
|
||||
{MKTAG('h', 'd', 'v', '9'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '1'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '2'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '3'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '4'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '5'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '6'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '7'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '8'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', '9'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'a'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'b'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'c'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'd'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'e'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', 'v', 'f'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'a'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'b'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'c'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'd'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'e'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', 'f'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', '9'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', '4'), "mpeg2video"},
|
||||
{MKTAG('x', 'd', '5', '5'), "mpeg2video"},
|
||||
{MKTAG('m', 'x', '5', 'n'), "mpeg2video"},
|
||||
{MKTAG('m', 'x', '4', 'n'), "mpeg2video"},
|
||||
{MKTAG('m', 'x', '4', 'p'), "mpeg2video"},
|
||||
{MKTAG('m', 'x', '3', 'n'), "mpeg2video"},
|
||||
{MKTAG('m', 'x', '3', 'p'), "mpeg2video"},
|
||||
{MKTAG('A', 'V', 'm', 'p'), "mpeg2video"},
|
||||
{MKTAG('V', 'C', 'R', '2'), "mpeg2video"}, // lavf: mpeg1video
|
||||
{MKTAG('m', 'p', '2', 'v'), "mpeg2video"},
|
||||
{MKTAG('m', '2', 'v', '1'), "mpeg2video"},
|
||||
{MKTAG('R', 'J', 'P', 'G'), "nuv"},
|
||||
{MKTAG('b', 'm', 'p', ' '), "bmp"},
|
||||
{MKTAG('b', 'm', 'p', 0 ), "bmp"},
|
||||
{MKTAG('g', 'i', 'f', ' '), "gif"},
|
||||
{MKTAG('t', 'i', 'f', 'f'), "tiff"},
|
||||
{MKTAG('p', 'c', 'x', ' '), "pcx"},
|
||||
{MKTAG('m', 't', 'g', 'a'), "targa"},
|
||||
{MKTAG('M', 'T', 'G', 'A'), "targa"},
|
||||
{MKTAG('r', 'l', 'e', ' '), "qtrle"},
|
||||
{MKTAG('s', 'm', 'c', ' '), "smc"},
|
||||
{MKTAG('8', 'B', 'P', 'S'), "8bps"},
|
||||
{MKTAG('W', 'R', 'L', 'E'), "msrle"},
|
||||
{MKTAG('F', 'F', 'V', 'H'), "huffyuv"}, // lavf: ffvhuff
|
||||
{MKTAG('P', 'I', 'X', 'L'), "vixl"},
|
||||
{MKTAG('X', 'I', 'X', 'L'), "vixl"},
|
||||
{MKTAG('q', 'd', 'r', 'w'), "qdraw"},
|
||||
{MKTAG('D', 'I', 'V', 'F'), "msmpeg4v3"},
|
||||
{MKTAG('d', 'i', 'v', 'f'), "msmpeg4v3"},
|
||||
{MKTAG('3', 'I', 'V', 'D'), "msmpeg4v3"},
|
||||
{MKTAG('3', 'i', 'v', 'd'), "msmpeg4v3"},
|
||||
{MKTAG('w', 'm', 'v', 'p'), "wmv3"}, // lavf: wmv3image
|
||||
{MKTAG('W', 'M', 'V', 'P'), "wmv3"}, // lavf: wmv3image
|
||||
{MKTAG('v', 'c', '-', '1'), "vc1"},
|
||||
{MKTAG('V', 'C', '-', '1'), "vc1"},
|
||||
{MKTAG('v', 'v', 'v', 'c'), "h264"},
|
||||
{MKTAG('a', 'i', '5', '5'), "h264"},
|
||||
{MKTAG('a', 'i', '1', '5'), "h264"},
|
||||
{MKTAG('a', 'i', '1', 'q'), "h264"},
|
||||
{MKTAG('a', 'i', '5', 'q'), "h264"},
|
||||
{MKTAG('a', 'i', '1', '2'), "h264"},
|
||||
{MKTAG(5 , 0 , 0 , 16 ), "h264"},
|
||||
{MKTAG('S', 'V', 'Q', '3'), "svq3"}, // libav 0.8: -, ffmpeg 1.1: svq3
|
||||
{MKTAG('d', 'r', 'a', 'c'), "dirac"}, // libav 0.8: -, ffmpeg 1.1: dirac
|
||||
{MKTAG('A', 'V', 'R', 'n'), "mjpeg"}, // libav 0.8: mjpeg, ffmpeg 1.1: avrn
|
||||
{MKTAG('A', 'V', 'D', 'J'), "mjpeg"},
|
||||
{MKTAG('A', 'D', 'J', 'V'), "mjpeg"},
|
||||
{MKTAG('J', 'F', 'I', 'F'), "mjpeg"},
|
||||
{MKTAG('M', 'J', 'L', 'S'), "mjpeg"}, // lavf: jpegls
|
||||
{MKTAG('m', 'j', 'p', 'b'), "mjpegb"},
|
||||
{MKTAG('U', '2', '6', '3'), "h263"}, // libav 0.8: -, ffmpeg 1.1: h263
|
||||
{MKTAG('v', 'i', 'v', '1'), "h263"},
|
||||
{MKTAG('s', '2', '6', '3'), "h263"}, // libav 0.8: -, ffmpeg 1.1: flv1
|
||||
{MKTAG('S', '2', '6', '3'), "h263"}, // same
|
||||
{MKTAG('D', '2', '6', '3'), "h263"},
|
||||
{MKTAG('I', 'L', 'V', 'R'), "h263"},
|
||||
{MKTAG('d', 'v', 'p', ' '), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'p', 'p'), "dvvideo"},
|
||||
{MKTAG('A', 'V', 'd', 'v'), "dvvideo"},
|
||||
{MKTAG('A', 'V', 'd', '1'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'h', 'q'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'h', 'p'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'h', '5'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'h', '6'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 'h', '3'), "dvvideo"},
|
||||
{MKTAG('d', 'v', 's', '1'), "dvvideo"},
|
||||
{MKTAG('R', 'V', '2', '0'), "rv20"},
|
||||
{MKTAG('r', 'v', '2', '0'), "rv20"},
|
||||
{MKTAG('R', 'V', 'T', 'R'), "rv20"},
|
||||
{MKTAG('R', 'V', '3', '0'), "rv30"},
|
||||
{MKTAG('r', 'v', '3', '0'), "rv30"},
|
||||
{MKTAG('R', 'V', '4', '0'), "rv40"},
|
||||
{MKTAG('r', 'v', '4', '0'), "rv40"},
|
||||
{MKTAG('R', 'V', '1', '0'), "rv10"},
|
||||
{MKTAG('r', 'v', '1', '0'), "rv10"},
|
||||
{MKTAG('R', 'V', '1', '3'), "rv10"},
|
||||
{MKTAG('r', 'v', '1', '3'), "rv10"},
|
||||
{MKTAG('T', 'h', 'r', 'a'), "theora"},
|
||||
{0xfffc , "theora"},
|
||||
{MKTAG('V', 'P', '6', 'A'), "vp6a"},
|
||||
{MKTAG('S', 'P', '5', '3'), "sp5x"},
|
||||
{MKTAG('S', 'P', '5', '5'), "sp5x"},
|
||||
{MKTAG('S', 'P', '5', '6'), "sp5x"},
|
||||
{MKTAG('S', 'P', '5', '7'), "sp5x"},
|
||||
{MKTAG('S', 'P', '5', '8'), "sp5x"},
|
||||
{MKTAG('S', 'M', 'K', '2'), "smackvideo"},
|
||||
{MKTAG('S', 'M', 'K', '4'), "smackvideo"},
|
||||
{MKTAG('a', 'v', 's', '2'), "cavs"},
|
||||
{MKTAG('A', 'V', 'd', 'n'), "dnxhd"},
|
||||
{MKTAG('a', 'p', 'c', 'h'), "prores"},
|
||||
{MKTAG('a', 'p', 'c', 'n'), "prores"},
|
||||
{MKTAG('a', 'p', 'c', 's'), "prores"},
|
||||
{MKTAG('a', 'p', 'c', 'o'), "prores"},
|
||||
{MKTAG('a', 'p', '4', 'h'), "prores"},
|
||||
{MKTAG('f', 'V', 'G', 'T'), "tgv"},
|
||||
// These are probably not correctly handled. The original codecs.conf
|
||||
// entries mapped these to separate pixel formats via vd_raw and the
|
||||
// "out" directive (look at MPlayer's codecs.conf).
|
||||
// Should they be aliased to supported FourCCs of the same formats?
|
||||
{MKTAG('A', 'V', '1', 'x'), "rawvideo"},
|
||||
{MKTAG('A', 'V', 'u', 'p'), "rawvideo"},
|
||||
{MKTAG('4', '4', '4', 'p'), "rawvideo"},
|
||||
{MKTAG('4', '4', '4', 'P'), "rawvideo"},
|
||||
{MKTAG('4', '2', '2', 'p'), "rawvideo"},
|
||||
{MKTAG('4', '2', '2', 'P'), "rawvideo"},
|
||||
// Unknown:
|
||||
{MKTAG('r', 'a', 'w', ' '), "rawvideo"},
|
||||
{MKTAG('D', 'V', 'O', 'O'), "rawvideo"},
|
||||
// ------- internal mplayer FourCCs ------
|
||||
{MKTAG('A', 'N', 'M', ' '), "anm"},
|
||||
{MKTAG('B', 'I', 'K', 'f'), "binkvideo"},
|
||||
{MKTAG('B', 'I', 'K', 'g'), "binkvideo"},
|
||||
{MKTAG('B', 'I', 'K', 'h'), "binkvideo"},
|
||||
{MKTAG('B', 'I', 'K', 'i'), "binkvideo"},
|
||||
{MKTAG('C', 'D', 'G', 'R'), "cdgraphics"},
|
||||
{MKTAG('M', 'V', 'I', '1'), "motionpixels"},
|
||||
{MKTAG('M', 'D', 'E', 'C'), "mdec"},
|
||||
{MKTAG('N', 'U', 'V', '1'), "nuv"},
|
||||
{MKTAG('p', 't', 'x', ' '), "ptx"},
|
||||
{MKTAG('S', 'G', 'I', '1'), "sgi"},
|
||||
{MKTAG('s', 'u', 'n', ' '), "sunrast"},
|
||||
{MKTAG('F', 'L', 'I', 'C'), "flic"},
|
||||
{MKTAG('R', 'o', 'Q', 'V'), "roq"},
|
||||
{MKTAG('A', 'M', 'V', 'V'), "amv"},
|
||||
{MKTAG('F', 'F', 'J', 'V'), "jv"},
|
||||
{MKTAG('T', 'S', 'E', 'Q'), "tiertexseqvideo"},
|
||||
{MKTAG('V', 'M', 'D', 'V'), "vmdvideo"},
|
||||
{MKTAG('D', 'X', 'A', '1'), "dxa"},
|
||||
{MKTAG('D', 'C', 'I', 'V'), "dsicinvideo"},
|
||||
{MKTAG('T', 'H', 'P', 'V'), "thp"},
|
||||
{MKTAG('B', 'F', 'I', 'V'), "bfi"},
|
||||
{MKTAG('B', 'E', 'T', 'H'), "bethsoftvid"},
|
||||
{MKTAG('R', 'L', '2', 'V'), "rl2"},
|
||||
{MKTAG('T', 'X', 'D', 'V'), "txd"},
|
||||
{MKTAG('W', 'C', '3', 'V'), "xan_wc3"},
|
||||
{MKTAG('I', 'D', 'C', 'I'), "idcin"},
|
||||
{MKTAG('I', 'N', 'P', 'V'), "interplayvideo"},
|
||||
{MKTAG('V', 'Q', 'A', 'V'), "ws_vqa"},
|
||||
{MKTAG('C', '9', '3', 'V'), "c93"},
|
||||
{0},
|
||||
};
|
||||
|
||||
static const int mp_fourcc_video_aliases[][2] = {
|
||||
// msmpeg4
|
||||
{MKTAG('M', 'P', 'G', '3'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('m', 'p', 'g', '3'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('M', 'P', '4', '3'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('m', 'p', '4', '3'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('D', 'I', 'V', '5'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('d', 'i', 'v', '5'), MKTAG('d', 'i', 'v', '3')},
|
||||
{MKTAG('D', 'I', 'V', '6'), MKTAG('d', 'i', 'v', '4')},
|
||||
{MKTAG('d', 'i', 'v', '6'), MKTAG('d', 'i', 'v', '4')},
|
||||
{MKTAG('A', 'P', '4', '1'), MKTAG('d', 'i', 'v', '3')},
|
||||
|
||||
// msmpeg4v2
|
||||
{MKTAG('D', 'I', 'V', '2'), MKTAG('m', 'p', '4', '2')},
|
||||
{MKTAG('d', 'i', 'v', '2'), MKTAG('m', 'p', '4', '2')},
|
||||
{MKTAG('D', 'I', 'V', '1'), MKTAG('d', 'i', 'v', 'x')},
|
||||
{MKTAG('d', 'i', 'v', '1'), MKTAG('d', 'i', 'v', 'x')},
|
||||
|
||||
// mpeg4
|
||||
{MKTAG('d', 'x', '5', '0'), MKTAG('D', 'X', '5', '0')},
|
||||
{MKTAG('B', 'L', 'Z', '0'), MKTAG('D', 'X', '5', '0')},
|
||||
|
||||
{MKTAG('v', 'i', 'v', '1'), MKTAG('h', '2', '6', '3')},
|
||||
{MKTAG('T', 'h', 'r', 'a'), MKTAG('t', 'h', 'e', 'o')},
|
||||
|
||||
{0},
|
||||
};
|
||||
|
||||
static const char *lookup_tag(const struct mp_codec_tag *mp_table,
|
||||
const struct AVCodecTag *av_table,
|
||||
uint32_t tag)
|
||||
{
|
||||
for (int n = 0; mp_table[n].codec; n++) {
|
||||
if (mp_table[n].tag == tag)
|
||||
return mp_table[n].codec;
|
||||
}
|
||||
const struct AVCodecTag *av_tags[] = {av_table, NULL};
|
||||
int id = av_codec_get_id(av_tags, tag);
|
||||
return id == CODEC_ID_NONE ? NULL : mp_codec_from_av_codec_id(id);
|
||||
}
|
||||
|
||||
void mp_set_video_codec_from_tag(struct sh_video *sh)
|
||||
{
|
||||
sh->gsh->codec = lookup_tag(mp_video_codec_tags,
|
||||
avformat_get_riff_video_tags(),
|
||||
sh->format);
|
||||
}
|
||||
|
||||
void mp_set_audio_codec_from_tag(struct sh_audio *sh)
|
||||
{
|
||||
sh->gsh->codec = lookup_tag(mp_audio_codec_tags,
|
||||
avformat_get_riff_audio_tags(),
|
||||
sh->format);
|
||||
}
|
||||
|
||||
uint32_t mp_video_fourcc_alias(uint32_t fourcc)
|
||||
{
|
||||
for (int n = 0; mp_fourcc_video_aliases[n][0]; n++) {
|
||||
if (mp_fourcc_video_aliases[n][0] == fourcc)
|
||||
return mp_fourcc_video_aliases[n][1];
|
||||
}
|
||||
return fourcc;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MP_CODEC_TAGS_H
|
||||
#define MP_CODEC_TAGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t mp_video_fourcc_alias(uint32_t fourcc);
|
||||
|
||||
struct sh_video;
|
||||
struct sh_audio;
|
||||
|
||||
void mp_set_audio_codec_from_tag(struct sh_audio *sh);
|
||||
void mp_set_video_codec_from_tag(struct sh_video *sh);
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "core/options.h"
|
||||
#include "core/av_common.h"
|
||||
#include "talloc.h"
|
||||
#include "core/mp_msg.h"
|
||||
|
||||
|
@ -485,63 +486,28 @@ void ds_add_packet(demux_stream_t *ds, demux_packet_t *dp)
|
|||
ds->demuxer->video->packs);
|
||||
}
|
||||
|
||||
static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, unsigned format)
|
||||
static void allocate_parser(AVCodecContext **avctx, AVCodecParserContext **parser, const char *format)
|
||||
{
|
||||
enum CodecID codec_id = CODEC_ID_NONE;
|
||||
enum CodecID codec_id = mp_codec_to_av_codec_id(format);
|
||||
|
||||
switch (format) {
|
||||
case MKTAG('M', 'P', '4', 'L'):
|
||||
codec_id = CODEC_ID_AAC_LATM;
|
||||
break;
|
||||
case 0x2000:
|
||||
case 0x332D6361:
|
||||
case 0x332D4341:
|
||||
case 0x20736D:
|
||||
case MKTAG('s', 'a', 'c', '3'):
|
||||
codec_id = CODEC_ID_AC3;
|
||||
break;
|
||||
case MKTAG('d', 'n', 'e', 't'):
|
||||
// DNET/byte-swapped AC-3 - there is no parser for that yet
|
||||
//codec_id = CODEC_ID_DNET;
|
||||
break;
|
||||
case MKTAG('E', 'A', 'C', '3'):
|
||||
codec_id = CODEC_ID_EAC3;
|
||||
break;
|
||||
case 0x2001:
|
||||
case 0x86:
|
||||
codec_id = CODEC_ID_DTS;
|
||||
break;
|
||||
case MKTAG('f', 'L', 'a', 'C'):
|
||||
codec_id = CODEC_ID_FLAC;
|
||||
break;
|
||||
case MKTAG('M', 'L', 'P', ' '):
|
||||
codec_id = CODEC_ID_MLP;
|
||||
break;
|
||||
case 0x55:
|
||||
case 0x5500736d:
|
||||
case 0x55005354:
|
||||
case MKTAG('.', 'm', 'p', '3'):
|
||||
case MKTAG('M', 'P', '3', ' '):
|
||||
case MKTAG('L', 'A', 'M', 'E'):
|
||||
codec_id = CODEC_ID_MP3;
|
||||
break;
|
||||
case 0x50:
|
||||
case 0x5000736d:
|
||||
case MKTAG('.', 'm', 'p', '2'):
|
||||
case MKTAG('.', 'm', 'p', '1'):
|
||||
codec_id = CODEC_ID_MP2;
|
||||
break;
|
||||
case MKTAG('T', 'R', 'H', 'D'):
|
||||
codec_id = CODEC_ID_TRUEHD;
|
||||
break;
|
||||
}
|
||||
if (codec_id != CODEC_ID_NONE) {
|
||||
switch (codec_id) {
|
||||
case CODEC_ID_AAC_LATM:
|
||||
case CODEC_ID_AC3:
|
||||
case CODEC_ID_EAC3:
|
||||
case CODEC_ID_DTS:
|
||||
case CODEC_ID_FLAC:
|
||||
case CODEC_ID_MLP:
|
||||
case CODEC_ID_MP3:
|
||||
case CODEC_ID_MP2:
|
||||
case CODEC_ID_TRUEHD:
|
||||
*avctx = avcodec_alloc_context3(NULL);
|
||||
if (!*avctx)
|
||||
return;
|
||||
*parser = av_parser_init(codec_id);
|
||||
if (!*parser)
|
||||
av_freep(avctx);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,7 +524,7 @@ static void get_parser(sh_common_t *sh, AVCodecContext **avctx, AVCodecParserCon
|
|||
if (*parser)
|
||||
return;
|
||||
|
||||
allocate_parser(avctx, parser, sh->format);
|
||||
allocate_parser(avctx, parser, sh->gsh->codec);
|
||||
sh->avctx = *avctx;
|
||||
sh->parser = *parser;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "core/options.h"
|
||||
#include "core/mp_msg.h"
|
||||
#include "core/av_opts.h"
|
||||
#include "core/av_common.h"
|
||||
#include "core/bstr.h"
|
||||
|
||||
#include "stream/stream.h"
|
||||
|
@ -344,8 +345,7 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
if (override_tag)
|
||||
codec->codec_tag = override_tag;
|
||||
|
||||
AVCodec *avc = avcodec_find_decoder(codec->codec_id);
|
||||
const char *codec_name = avc ? avc->name : "unknown";
|
||||
const char *mp_codec = mp_codec_from_av_codec_id(codec->codec_id);
|
||||
|
||||
bool set_demuxer_id = matches_avinputformat_name(priv, "mpeg");
|
||||
|
||||
|
@ -356,12 +356,11 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams);
|
||||
if (!sh_audio)
|
||||
break;
|
||||
sh_audio->demuxer_codecname = codec_name;
|
||||
if (set_demuxer_id)
|
||||
sh_audio->gsh->demuxer_id = st->id;
|
||||
stream_type = "audio";
|
||||
priv->astreams[priv->audio_streams] = i;
|
||||
sh_audio->libav_codec_id = codec->codec_id;
|
||||
sh_audio->gsh->codec = mp_codec;
|
||||
sh_audio->gsh->lavf_codec_tag = lavf_codec_tag;
|
||||
wf = calloc(sizeof(*wf) + codec->extradata_size, 1);
|
||||
// mp4a tag is used for all mp4 files no matter what they actually contain
|
||||
|
@ -430,12 +429,11 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_video = new_sh_video_vid(demuxer, i, priv->video_streams);
|
||||
if (!sh_video)
|
||||
break;
|
||||
sh_video->demuxer_codecname = codec_name;
|
||||
if (set_demuxer_id)
|
||||
sh_video->gsh->demuxer_id = st->id;
|
||||
stream_type = "video";
|
||||
priv->vstreams[priv->video_streams] = i;
|
||||
sh_video->libav_codec_id = codec->codec_id;
|
||||
sh_video->gsh->codec = mp_codec;
|
||||
sh_video->gsh->lavf_codec_tag = lavf_codec_tag;
|
||||
if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||
sh_video->gsh->attached_picture = true;
|
||||
|
@ -547,12 +545,11 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams);
|
||||
if (!sh_sub)
|
||||
break;
|
||||
sh_sub->demuxer_codecname = codec_name;
|
||||
if (set_demuxer_id)
|
||||
sh_sub->gsh->demuxer_id = st->id;
|
||||
stream_type = "subtitle";
|
||||
priv->sstreams[priv->sub_streams] = i;
|
||||
sh_sub->libav_codec_id = codec->codec_id;
|
||||
sh_sub->gsh->codec = mp_codec;
|
||||
sh_sub->gsh->lavf_codec_tag = lavf_codec_tag;
|
||||
sh_sub->type = type;
|
||||
if (codec->extradata_size) {
|
||||
|
@ -590,10 +587,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
st->discard = AVDISCARD_ALL;
|
||||
}
|
||||
if (stream_type) {
|
||||
if (!avc && *stream_type == 's' && demuxer->s_streams[i])
|
||||
codec_name = sh_sub_type2str((demuxer->s_streams[i])->type);
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "[lavf] stream %d: %s (%s), -%cid %d",
|
||||
i, stream_type, codec_name, *stream_type, stream_id);
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "[lavf] stream %d: %s, -%cid %d",
|
||||
i, stream_type, *stream_type, stream_id);
|
||||
if (lang && lang->value && *stream_type != 'v')
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, ", -%clang %s",
|
||||
*stream_type, lang->value);
|
||||
|
|
|
@ -1261,13 +1261,14 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track,
|
|||
|
||||
sh_v = new_sh_video(demuxer, vid);
|
||||
sh_v->gsh->demuxer_id = track->tnum;
|
||||
sh_v->demuxer_codecname = track->codec_id;
|
||||
sh_v->gsh->title = talloc_strdup(sh_v, track->name);
|
||||
sh_v->bih = bih;
|
||||
sh_v->format = sh_v->bih->biCompression;
|
||||
if (raw) {
|
||||
sh_v->format = mmioFOURCC('M', 'P', 'r', 'v');
|
||||
sh_v->imgfmt = sh_v->bih->biCompression;
|
||||
sh_v->gsh->codec = "rawvideo";
|
||||
} else {
|
||||
mp_set_video_codec_from_tag(sh_v);
|
||||
sh_v->format = mp_video_fourcc_alias(sh_v->format);
|
||||
}
|
||||
if (track->v_frate == 0.0)
|
||||
track->v_frate = 25.0;
|
||||
|
@ -1338,7 +1339,6 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
|
|||
if (track->language && (strcmp(track->language, "und") != 0))
|
||||
sh_a->lang = talloc_strdup(sh_a, track->language);
|
||||
sh_a->gsh->demuxer_id = track->tnum;
|
||||
sh_a->demuxer_codecname = track->codec_id;
|
||||
sh_a->gsh->title = talloc_strdup(sh_a, track->name);
|
||||
sh_a->gsh->default_track = track->default_track;
|
||||
sh_a->ds = demuxer->audio;
|
||||
|
@ -1569,6 +1569,8 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
|
|||
goto error;
|
||||
}
|
||||
|
||||
mp_set_audio_codec_from_tag(sh_a);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
@ -1586,7 +1588,6 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track,
|
|||
uint8_t *buffer;
|
||||
sh_sub_t *sh = new_sh_sub(demuxer, sid);
|
||||
sh->gsh->demuxer_id = track->tnum;
|
||||
sh->demuxer_codecname = track->codec_id;
|
||||
track->sh_sub = sh;
|
||||
sh->type = track->subtitle_type;
|
||||
size = track->private_size;
|
||||
|
|
|
@ -437,8 +437,8 @@ static demuxer_t * demux_mng_open(demuxer_t * demuxer)
|
|||
sh_video->ds = demuxer->video;
|
||||
|
||||
// set format of pixels in video packets
|
||||
sh_video->format = MP_FOURCC_RAWVIDEO;
|
||||
sh_video->imgfmt = MP_FOURCC_RGB32;
|
||||
sh_video->gsh->codec = "rawvideo";
|
||||
sh_video->format = MP_FOURCC_RGB32;
|
||||
|
||||
// set framerate to some value (MNG does not have a fixed framerate)
|
||||
sh_video->fps = 5.0f;
|
||||
|
|
|
@ -282,6 +282,7 @@ static void new_audio_stream(demuxer_t *demux, int aid){
|
|||
if((aid & 0xC0) == 0xC0) sh_a->format=0x2000;
|
||||
else if(aid >= 0x98 && aid <= 0x9f) sh_a->format=0x2001;
|
||||
if (mpg_d) mpg_d->a_stream_ids[mpg_d->num_a_streams++] = aid;
|
||||
mp_set_audio_codec_from_tag(sh_a);
|
||||
}
|
||||
if(demux->audio->id==-1) demux->audio->id=aid;
|
||||
}
|
||||
|
@ -487,6 +488,7 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){
|
|||
if(priv && ds->sh) {
|
||||
sh_video_t *sh = (sh_video_t *)ds->sh;
|
||||
sh->format = mmioFOURCC('W', 'V', 'C', '1');
|
||||
mp_set_video_codec_from_tag(sh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -604,6 +606,7 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){
|
|||
sh->format = priv->es_map[id - 0x1B0];
|
||||
mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
|
||||
dvdpcm_header(sh);
|
||||
mp_set_audio_codec_from_tag(sh);
|
||||
}
|
||||
}
|
||||
} else
|
||||
|
@ -619,6 +622,7 @@ static int demux_mpg_read_packet(demuxer_t *demux,int id){
|
|||
sh_video_t *sh = (sh_video_t *)ds->sh;
|
||||
if(priv->es_map[id - 0x1B0]) {
|
||||
sh->format = priv->es_map[id - 0x1B0];
|
||||
mp_set_video_codec_from_tag(sh);
|
||||
mp_dbg(MSGT_DEMUX,MSGL_DBG2,"ASSIGNED TO STREAM %d CODEC %x\n", id, priv->es_map[id - 0x1B0]);
|
||||
}
|
||||
}
|
||||
|
@ -1186,6 +1190,7 @@ static demuxer_t* demux_mpg_ps_open(demuxer_t* demuxer)
|
|||
num_elementary_packets1B6==0)
|
||||
sh_video->format = 0x10000005;
|
||||
else sh_video->format = 0x10000002;
|
||||
mp_set_video_codec_from_tag(sh_video);
|
||||
}
|
||||
|
||||
return demuxer;
|
||||
|
|
|
@ -51,17 +51,16 @@ static demuxer_t* demux_rawaudio_open(demuxer_t* demuxer) {
|
|||
return NULL;
|
||||
|
||||
sh_audio = new_sh_audio(demuxer,0);
|
||||
sh_audio->gsh->codec = "mp-pcm";
|
||||
sh_audio->format = format;
|
||||
sh_audio->wf = w = malloc(sizeof(*w));
|
||||
// Not a WAVEFORMATEX format; just abuse it to pass the internal mplayer
|
||||
// format to ad_pcm.c
|
||||
w->wFormatTag = format;
|
||||
sh_audio->format = MKTAG('M', 'P', 'a', 'f');
|
||||
w->wFormatTag = 0;
|
||||
w->nChannels = sh_audio->channels = channels;
|
||||
w->nSamplesPerSec = sh_audio->samplerate = samplerate;
|
||||
sh_audio->samplesize = (af_fmt2bits(format) + 7) / 8;
|
||||
w->nAvgBytesPerSec = samplerate * sh_audio->samplesize * channels;
|
||||
w->nBlockAlign = channels * sh_audio->samplesize;
|
||||
w->wBitsPerSample = 8 * sh_audio->samplesize;
|
||||
int samplesize = (af_fmt2bits(format) + 7) / 8;
|
||||
w->nAvgBytesPerSec = samplerate * samplesize * channels;
|
||||
w->nBlockAlign = channels * samplesize;
|
||||
w->wBitsPerSample = 8 * samplesize;
|
||||
w->cbSize = 0;
|
||||
|
||||
demuxer->movi_start = demuxer->stream->start_pos;
|
||||
|
|
|
@ -81,10 +81,11 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int tag, fmt;
|
||||
const char *decoder = "rawvideo";
|
||||
int imgfmt = format;
|
||||
if (mp_format) {
|
||||
tag = MP_FOURCC_IMGFMT;
|
||||
fmt = mp_format;
|
||||
decoder = "mp-rawvideo";
|
||||
imgfmt = mp_format;
|
||||
if (!imgsize) {
|
||||
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(mp_format);
|
||||
for (int p = 0; p < desc.num_planes; p++) {
|
||||
|
@ -92,9 +93,6 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) {
|
|||
desc.bpp[p] + 7) / 8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tag = MP_FOURCC_RAWVIDEO;
|
||||
fmt = format;
|
||||
}
|
||||
|
||||
if (!imgsize) {
|
||||
|
@ -131,8 +129,8 @@ static demuxer_t* demux_rawvideo_open(demuxer_t* demuxer) {
|
|||
}
|
||||
|
||||
sh_video = new_sh_video(demuxer,0);
|
||||
sh_video->format=tag;
|
||||
sh_video->imgfmt=fmt;
|
||||
sh_video->gsh->codec=decoder;
|
||||
sh_video->format=imgfmt;
|
||||
sh_video->fps=fps;
|
||||
sh_video->frametime=1.0/fps;
|
||||
sh_video->disp_w=width;
|
||||
|
|
|
@ -353,6 +353,7 @@ static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es)
|
|||
const char *lang = pid_lang_from_pmt(priv, es->pid);
|
||||
sh->needs_parsing = 1;
|
||||
sh->format = IS_AUDIO(es->type) ? es->type : es->subtype;
|
||||
mp_set_audio_codec_from_tag(sh);
|
||||
sh->ds = demuxer->audio;
|
||||
|
||||
priv->ts.streams[es->pid].id = priv->last_aid;
|
||||
|
@ -378,6 +379,7 @@ static void ts_add_stream(demuxer_t * demuxer, ES_stream_t *es)
|
|||
if(sh)
|
||||
{
|
||||
sh->format = IS_VIDEO(es->type) ? es->type : es->subtype;
|
||||
mp_set_video_codec_from_tag(sh);
|
||||
sh->ds = demuxer->video;
|
||||
|
||||
priv->ts.streams[es->pid].id = priv->last_vid;
|
||||
|
@ -1054,6 +1056,7 @@ static demuxer_t *demux_open_ts(demuxer_t * demuxer)
|
|||
demuxer->video->id = priv->ts.streams[params.vpid].id;
|
||||
sh_video->ds = demuxer->video;
|
||||
sh_video->format = params.vtype;
|
||||
mp_set_video_codec_from_tag(sh_video);
|
||||
demuxer->video->sh = sh_video;
|
||||
}
|
||||
|
||||
|
@ -1067,6 +1070,7 @@ static demuxer_t *demux_open_ts(demuxer_t * demuxer)
|
|||
demuxer->audio->id = priv->ts.streams[params.apid].id;
|
||||
sh_audio->ds = demuxer->audio;
|
||||
sh_audio->format = params.atype;
|
||||
mp_set_audio_codec_from_tag(sh_audio);
|
||||
demuxer->audio->sh = sh_audio;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "codec_tags.h"
|
||||
|
||||
#include "aviheader.h"
|
||||
#include "ms_hdr.h"
|
||||
struct MPOpts;
|
||||
|
@ -54,6 +56,9 @@ struct sh_stream {
|
|||
struct sh_video *video;
|
||||
struct sh_sub *sub;
|
||||
|
||||
// E.g. "h264" (usually corresponds to AVCodecDescriptor.name)
|
||||
const char *codec;
|
||||
|
||||
// Work around other hacks.
|
||||
int lavf_codec_tag;
|
||||
|
||||
|
@ -61,6 +66,9 @@ struct sh_stream {
|
|||
bool default_track; // container default track flag
|
||||
bool attached_picture; // stream is a picture (such as album art)
|
||||
|
||||
// Human readable description of the running decoder, or NULL
|
||||
char *decoder_desc;
|
||||
|
||||
// shouldn't exist type of stuff
|
||||
struct MPOpts *opts;
|
||||
};
|
||||
|
@ -68,12 +76,10 @@ struct sh_stream {
|
|||
|
||||
#define SH_COMMON \
|
||||
struct sh_stream *gsh; \
|
||||
const char *demuxer_codecname; \
|
||||
struct MPOpts *opts; \
|
||||
struct demux_stream *ds; \
|
||||
struct codecs *codec; \
|
||||
/* usually a FourCC, exact meaning depends on gsh->format */ \
|
||||
unsigned int format; \
|
||||
int libav_codec_id; \
|
||||
int initialized; \
|
||||
/* number of seconds stream should be delayed \
|
||||
* (according to dwStart or similar) */ \
|
||||
|
@ -87,7 +93,6 @@ struct sh_stream {
|
|||
double pts; \
|
||||
/* decoder context */ \
|
||||
void *context; \
|
||||
const char *codecname; \
|
||||
char *lang; /* track language */ \
|
||||
|
||||
typedef struct sh_common {
|
||||
|
@ -154,7 +159,6 @@ typedef struct sh_video {
|
|||
int disp_w, disp_h; // display size (filled by demuxer)
|
||||
int colorspace; // mp_csp
|
||||
int color_range; // mp_csp_levels
|
||||
int imgfmt; // raw video image format
|
||||
// output driver/filters: (set by libmpcodecs core)
|
||||
unsigned int outfmt;
|
||||
struct vf_instance *vfilter; // video filter chain
|
||||
|
|
2210
etc/codecs.conf
2210
etc/codecs.conf
File diff suppressed because it is too large
Load Diff
10
stream/tv.c
10
stream/tv.c
|
@ -713,8 +713,8 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
|
|||
/* get IMAGE FORMAT */
|
||||
int fourcc;
|
||||
funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &fourcc);
|
||||
sh_video->format = MP_FOURCC_RAWVIDEO;
|
||||
sh_video->imgfmt = fourcc;
|
||||
sh_video->gsh->codec = "rawvideo";
|
||||
sh_video->format = fourcc;
|
||||
|
||||
/* set FPS and FRAMETIME */
|
||||
|
||||
|
@ -758,7 +758,6 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
|
|||
if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE)
|
||||
{
|
||||
int audio_format;
|
||||
int sh_audio_format;
|
||||
char buf[128];
|
||||
|
||||
/* yeah, audio is present */
|
||||
|
@ -779,7 +778,6 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
|
|||
case AF_FORMAT_S16_BE:
|
||||
case AF_FORMAT_S32_LE:
|
||||
case AF_FORMAT_S32_BE:
|
||||
sh_audio_format = 0x1; /* PCM */
|
||||
break;
|
||||
case AF_FORMAT_MPEG2:
|
||||
default:
|
||||
|
@ -797,8 +795,8 @@ static demuxer_t* demux_open_tv(demuxer_t *demuxer)
|
|||
funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS,
|
||||
&sh_audio->channels);
|
||||
|
||||
sh_audio->format = sh_audio_format;
|
||||
sh_audio->sample_format = audio_format;
|
||||
sh_audio->gsh->codec = "mp-pcm";
|
||||
sh_audio->format = audio_format;
|
||||
|
||||
sh_audio->i_bps = sh_audio->o_bps =
|
||||
sh_audio->samplerate * sh_audio->samplesize *
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "demux/codec_tags.h"
|
||||
|
||||
#include "core/mp_msg.h"
|
||||
|
||||
|
@ -32,7 +34,7 @@
|
|||
#include "stream/stream.h"
|
||||
#include "demux/demux.h"
|
||||
|
||||
#include "core/codec-cfg.h"
|
||||
#include "core/codecs.h"
|
||||
|
||||
#include "video/out/vo.h"
|
||||
#include "video/csputils.h"
|
||||
|
@ -180,173 +182,97 @@ void uninit_video(sh_video_t *sh_video)
|
|||
{
|
||||
if (!sh_video->initialized)
|
||||
return;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video: %s\n", sh_video->codec->drv);
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n");
|
||||
sh_video->vd_driver->uninit(sh_video);
|
||||
vf_uninit_filter_chain(sh_video->vfilter);
|
||||
talloc_free(sh_video->gsh->decoder_desc);
|
||||
sh_video->gsh->decoder_desc = NULL;
|
||||
sh_video->initialized = 0;
|
||||
}
|
||||
|
||||
void vfm_help(void)
|
||||
static int init_video_codec(sh_video_t *sh_video, const char *decoder)
|
||||
{
|
||||
int i;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Available (compiled-in) video codec families/drivers:\n");
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_DRIVERS\n");
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_INFO, " vfm: info: (comment)\n");
|
||||
for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "%8s %s (%s)\n",
|
||||
mpcodecs_vd_drivers[i]->info->short_name,
|
||||
mpcodecs_vd_drivers[i]->info->name,
|
||||
mpcodecs_vd_drivers[i]->info->comment);
|
||||
}
|
||||
assert(!sh_video->vf_initialized);
|
||||
|
||||
static int init_video(sh_video_t *sh_video, char *codecname, char *vfm,
|
||||
int status, stringset_t *selected)
|
||||
{
|
||||
int force = 0;
|
||||
unsigned int orig_fourcc =
|
||||
sh_video->bih ? sh_video->bih->biCompression : 0;
|
||||
sh_video->codec = NULL;
|
||||
sh_video->vf_initialized = 0;
|
||||
if (codecname && codecname[0] == '+') {
|
||||
codecname = &codecname[1];
|
||||
force = 1;
|
||||
if (!sh_video->vd_driver->init(sh_video, decoder)) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Video decoder init failed.\n");
|
||||
//uninit_video(sh_video);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int i;
|
||||
int orig_w, orig_h;
|
||||
// restore original fourcc:
|
||||
if (sh_video->bih)
|
||||
sh_video->bih->biCompression = orig_fourcc;
|
||||
if (!
|
||||
(sh_video->codec =
|
||||
find_video_codec(sh_video->format,
|
||||
sh_video->bih ? ((unsigned int *) &sh_video->
|
||||
bih->biCompression) : NULL,
|
||||
sh_video->codec, force)))
|
||||
break;
|
||||
// ok we found one codec
|
||||
if (stringset_test(selected, sh_video->codec->name))
|
||||
continue; // already tried & failed
|
||||
if (codecname && strcmp(sh_video->codec->name, codecname))
|
||||
continue; // -vc
|
||||
if (vfm && strcmp(sh_video->codec->drv, vfm))
|
||||
continue; // vfm doesn't match
|
||||
if (!force && sh_video->codec->status < status)
|
||||
continue; // too unstable
|
||||
stringset_add(selected, sh_video->codec->name); // tagging it
|
||||
// ok, it matches all rules, let's find the driver!
|
||||
for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
|
||||
if (!strcmp(mpcodecs_vd_drivers[i]->info->short_name,
|
||||
sh_video->codec->drv))
|
||||
break;
|
||||
sh_video->vd_driver = mpcodecs_vd_drivers[i];
|
||||
if (!sh_video->vd_driver) { // driver not available (==compiled in)
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN,
|
||||
_("Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"),
|
||||
sh_video->codec->name, sh_video->codec->drv);
|
||||
sh_video->initialized = 1;
|
||||
sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
|
||||
sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct mp_decoder_list *mp_video_decoder_list(void)
|
||||
{
|
||||
struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
|
||||
for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
|
||||
mpcodecs_vd_drivers[i]->add_decoders(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static struct mp_decoder_list *mp_select_video_decoders(const char *codec,
|
||||
char *selection)
|
||||
{
|
||||
struct mp_decoder_list *list = mp_video_decoder_list();
|
||||
struct mp_decoder_list *new = mp_select_decoders(list, codec, selection);
|
||||
talloc_free(list);
|
||||
return new;
|
||||
}
|
||||
|
||||
static const struct vd_functions *find_driver(const char *name)
|
||||
{
|
||||
for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) {
|
||||
if (strcmp(mpcodecs_vd_drivers[i]->name, name) == 0)
|
||||
return mpcodecs_vd_drivers[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int init_best_video_codec(sh_video_t *sh_video, char* video_decoders)
|
||||
{
|
||||
assert(!sh_video->initialized);
|
||||
|
||||
struct mp_decoder_entry *decoder = NULL;
|
||||
struct mp_decoder_list *list =
|
||||
mp_select_video_decoders(sh_video->gsh->codec, video_decoders);
|
||||
|
||||
mp_print_decoders(MSGT_DECVIDEO, MSGL_V, "Codec list:", list);
|
||||
|
||||
for (int n = 0; n < list->num_entries; n++) {
|
||||
struct mp_decoder_entry *sel = &list->entries[n];
|
||||
const struct vd_functions *driver = find_driver(sel->family);
|
||||
if (!driver)
|
||||
continue;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder %s:%s\n",
|
||||
sel->family, sel->decoder);
|
||||
sh_video->vd_driver = driver;
|
||||
if (init_video_codec(sh_video, sel->decoder)) {
|
||||
decoder = sel;
|
||||
break;
|
||||
}
|
||||
orig_w = sh_video->bih ? sh_video->bih->biWidth : sh_video->disp_w;
|
||||
orig_h = sh_video->bih ? sh_video->bih->biHeight : sh_video->disp_h;
|
||||
sh_video->disp_w = orig_w;
|
||||
sh_video->disp_h = orig_h;
|
||||
if (sh_video->bih) {
|
||||
sh_video->bih->biWidth = sh_video->disp_w;
|
||||
sh_video->bih->biHeight = sh_video->disp_h;
|
||||
}
|
||||
|
||||
// init()
|
||||
const struct vd_functions *vd = sh_video->vd_driver;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder: [%s] %s\n",
|
||||
vd->info->short_name, vd->info->name);
|
||||
// clear vf init error, it is no longer relevant
|
||||
if (sh_video->vf_initialized < 0)
|
||||
sh_video->vf_initialized = 0;
|
||||
if (!vd->init(sh_video)) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Video decoder init failed for "
|
||||
"codecs.conf entry \"%s\".\n", sh_video->codec->name);
|
||||
sh_video->disp_w = orig_w;
|
||||
sh_video->disp_h = orig_h;
|
||||
if (sh_video->bih) {
|
||||
sh_video->bih->biWidth = sh_video->disp_w;
|
||||
sh_video->bih->biHeight = sh_video->disp_h;
|
||||
}
|
||||
continue; // try next...
|
||||
}
|
||||
// Yeah! We got it!
|
||||
sh_video->initialized = 1;
|
||||
sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
|
||||
sh_video->prev_sorted_pts = MP_NOPTS_VALUE;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
|
||||
char **video_fm_list)
|
||||
{
|
||||
char *vc_l_default[2] = { "", (char *) NULL };
|
||||
stringset_t selected;
|
||||
// hack:
|
||||
if (!video_codec_list)
|
||||
video_codec_list = vc_l_default;
|
||||
// Go through the codec.conf and find the best codec...
|
||||
sh_video->initialized = 0;
|
||||
stringset_init(&selected);
|
||||
while (!sh_video->initialized && *video_codec_list) {
|
||||
char *video_codec = *(video_codec_list++);
|
||||
if (video_codec[0]) {
|
||||
if (video_codec[0] == '-') {
|
||||
// disable this codec:
|
||||
stringset_add(&selected, video_codec + 1);
|
||||
} else {
|
||||
// forced codec by name:
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Forced video codec: %s\n",
|
||||
video_codec);
|
||||
init_video(sh_video, video_codec, NULL, -1, &selected);
|
||||
}
|
||||
} else {
|
||||
int status;
|
||||
// try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING.
|
||||
if (video_fm_list) {
|
||||
char **fmlist = video_fm_list;
|
||||
// try first the preferred codec families:
|
||||
while (!sh_video->initialized && *fmlist) {
|
||||
char *video_fm = *(fmlist++);
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Trying to force video codec driver family %s...\n",
|
||||
video_fm);
|
||||
for (status = CODECS_STATUS__MAX;
|
||||
status >= CODECS_STATUS__MIN; --status)
|
||||
if (init_video
|
||||
(sh_video, NULL, video_fm, status, &selected))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sh_video->initialized)
|
||||
for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN;
|
||||
--status)
|
||||
if (init_video(sh_video, NULL, NULL, status, &selected))
|
||||
break;
|
||||
}
|
||||
}
|
||||
stringset_free(&selected);
|
||||
|
||||
if (!sh_video->initialized) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Cannot find codec matching selected -vo and video format 0x%X.\n",
|
||||
sh_video->format);
|
||||
return 0; // failed
|
||||
sh_video->vd_driver = NULL;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Video decoder init failed for "
|
||||
"%s:%s\n", sel->family, sel->decoder);
|
||||
}
|
||||
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s [%s]\n",
|
||||
sh_video->codecname ? sh_video->codecname : sh_video->codec->info,
|
||||
sh_video->vd_driver->info->print_name ?
|
||||
sh_video->vd_driver->info->print_name :
|
||||
sh_video->vd_driver->info->short_name);
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_V,
|
||||
"Video codecs.conf entry: %s (%s) vfm: %s\n",
|
||||
sh_video->codec->name, sh_video->codec->info, sh_video->codec->drv);
|
||||
return 1; // success
|
||||
if (sh_video->initialized) {
|
||||
sh_video->gsh->decoder_desc =
|
||||
talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family,
|
||||
decoder->decoder);
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s\n",
|
||||
sh_video->gsh->decoder_desc);
|
||||
} else {
|
||||
mp_msg(MSGT_DECVIDEO, MSGL_ERR,
|
||||
"Failed to initialize a video decoder for codec '%s'.\n",
|
||||
sh_video->gsh->codec ? sh_video->gsh->codec : "<unknown>");
|
||||
}
|
||||
|
||||
talloc_free(list);
|
||||
return sh_video->initialized;
|
||||
}
|
||||
|
||||
void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
#include "demux/stheader.h"
|
||||
|
||||
struct osd_state;
|
||||
struct mp_decoder_list;
|
||||
|
||||
// dec_video.c:
|
||||
void vfm_help(void);
|
||||
struct mp_decoder_list *mp_video_decoder_list(void);
|
||||
|
||||
int init_best_video_codec(sh_video_t *sh_video, char** video_codec_list, char** video_fm_list);
|
||||
int init_best_video_codec(sh_video_t *sh_video, char* video_decoders);
|
||||
void uninit_video(sh_video_t *sh_video);
|
||||
|
||||
struct demux_packet;
|
||||
|
|
|
@ -18,7 +18,7 @@ typedef struct ffmpeg_ctx {
|
|||
int best_csp;
|
||||
AVRational last_sample_aspect_ratio;
|
||||
enum AVDiscard skip_frame;
|
||||
AVCodec *software_fallback;
|
||||
const char *software_fallback_decoder;
|
||||
struct FramePool *dr1_buffer_pool;
|
||||
struct mp_image_pool *non_dr1_pool;
|
||||
} vd_ffmpeg_ctx;
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "core/mp_msg.h"
|
||||
#include "core/options.h"
|
||||
|
||||
#include "core/codec-cfg.h"
|
||||
|
||||
#include "video/img_format.h"
|
||||
|
||||
#include "stream/stream.h"
|
||||
|
@ -114,7 +112,7 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt)
|
|||
sh->vfilter = vf;
|
||||
|
||||
// autodetect flipping
|
||||
bool flip = !!opts->flip != !!(sh->codec->flags & CODECS_FLAG_FLIP);
|
||||
bool flip = opts->flip;
|
||||
if (flip && !(sh->output_flags & VFCAP_FLIP)) {
|
||||
// we need to flip, but no flipping filter avail.
|
||||
vf_add_before_vo(&vf, "flip", NULL);
|
||||
|
|
|
@ -20,18 +20,17 @@
|
|||
#define MPLAYER_VD_H
|
||||
|
||||
#include "video/mp_image.h"
|
||||
#include "core/mpc_info.h"
|
||||
#include "demux/stheader.h"
|
||||
|
||||
typedef struct mp_codec_info vd_info_t;
|
||||
|
||||
struct demux_packet;
|
||||
struct mp_decoder_list;
|
||||
|
||||
/* interface of video decoder drivers */
|
||||
typedef struct vd_functions
|
||||
{
|
||||
const vd_info_t *info;
|
||||
int (*init)(sh_video_t *sh);
|
||||
const char *name;
|
||||
void (*add_decoders)(struct mp_decoder_list *list);
|
||||
int (*init)(sh_video_t *sh, const char *decoder);
|
||||
void (*uninit)(sh_video_t *sh);
|
||||
int (*control)(sh_video_t *sh, int cmd, void *arg);
|
||||
struct mp_image *(*decode)(struct sh_video *sh, struct demux_packet *pkt,
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "core/mp_msg.h"
|
||||
#include "core/options.h"
|
||||
#include "core/av_opts.h"
|
||||
#include "core/av_common.h"
|
||||
#include "core/codecs.h"
|
||||
|
||||
#include "compat/mpbswap.h"
|
||||
#include "video/fmt-conversion.h"
|
||||
|
@ -45,19 +47,9 @@
|
|||
#include "video/filter/vf.h"
|
||||
#include "demux/stheader.h"
|
||||
#include "demux/demux_packet.h"
|
||||
#include "core/codec-cfg.h"
|
||||
#include "osdep/numcores.h"
|
||||
#include "video/csputils.h"
|
||||
|
||||
static const vd_info_t info = {
|
||||
"libavcodec video codecs",
|
||||
"ffmpeg",
|
||||
"",
|
||||
"",
|
||||
"native codecs",
|
||||
.print_name = "libavcodec",
|
||||
};
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#include "lavc.h"
|
||||
|
||||
|
@ -67,7 +59,7 @@ static const vd_info_t info = {
|
|||
|
||||
#include "core/m_option.h"
|
||||
|
||||
static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec);
|
||||
static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec);
|
||||
static void uninit_avctx(sh_video_t *sh);
|
||||
static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
|
||||
static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic);
|
||||
|
@ -155,70 +147,53 @@ static enum AVDiscard str2AVDiscard(char *str)
|
|||
return AVDISCARD_DEFAULT;
|
||||
}
|
||||
|
||||
static int init(sh_video_t *sh)
|
||||
static int init(sh_video_t *sh, const char *decoder)
|
||||
{
|
||||
vd_ffmpeg_ctx *ctx;
|
||||
AVCodec *lavc_codec = NULL;
|
||||
|
||||
ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx);
|
||||
ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16));
|
||||
|
||||
if (sh->codec->dll) {
|
||||
lavc_codec = avcodec_find_decoder_by_name(sh->codec->dll);
|
||||
if (!lavc_codec) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR,
|
||||
"Cannot find codec '%s' in libavcodec...\n",
|
||||
sh->codec->dll);
|
||||
uninit(sh);
|
||||
return 0;
|
||||
}
|
||||
} else if (sh->libav_codec_id) {
|
||||
lavc_codec = avcodec_find_decoder(sh->libav_codec_id);
|
||||
if (!lavc_codec) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Libavcodec has no decoder "
|
||||
"for this codec\n");
|
||||
uninit(sh);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!lavc_codec) {
|
||||
uninit(sh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hwdec *hwdec = find_hwcodec(sh->opts->hwdec_api, lavc_codec->name);
|
||||
struct hwdec *hwdec = find_hwcodec(sh->opts->hwdec_api, decoder);
|
||||
if (hwdec) {
|
||||
AVCodec *lavc_hwcodec = avcodec_find_decoder_by_name(hwdec->hw_codec);
|
||||
if (lavc_hwcodec) {
|
||||
ctx->software_fallback = lavc_codec;
|
||||
lavc_codec = lavc_hwcodec;
|
||||
ctx->software_fallback_decoder = decoder;
|
||||
decoder = lavc_hwcodec->name;
|
||||
} else {
|
||||
hwdec = NULL;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Using software decoding.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_avctx(sh, lavc_codec, hwdec)) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware "
|
||||
"decoding, falling back to software decoding.\n");
|
||||
lavc_codec = ctx->software_fallback;
|
||||
ctx->software_fallback = NULL;
|
||||
if (!init_avctx(sh, lavc_codec, NULL)) {
|
||||
uninit(sh);
|
||||
return 0;
|
||||
if (!init_avctx(sh, decoder, hwdec)) {
|
||||
if (ctx->software_fallback_decoder) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware "
|
||||
"decoding, falling back to software decoding.\n");
|
||||
decoder = ctx->software_fallback_decoder;
|
||||
ctx->software_fallback_decoder = NULL;
|
||||
if (!init_avctx(sh, decoder, NULL)) {
|
||||
uninit(sh);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
|
||||
static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
|
||||
{
|
||||
vd_ffmpeg_ctx *ctx = sh->context;
|
||||
struct lavc_param *lavc_param = &sh->opts->lavc_param;
|
||||
bool mp_rawvideo = false;
|
||||
|
||||
sh->codecname = lavc_codec->long_name;
|
||||
if (!sh->codecname)
|
||||
sh->codecname = lavc_codec->name;
|
||||
if (strcmp(decoder, "mp-rawvideo") == 0) {
|
||||
mp_rawvideo = true;
|
||||
decoder = "rawvideo";
|
||||
}
|
||||
|
||||
AVCodec *lavc_codec = avcodec_find_decoder_by_name(decoder);
|
||||
if (!lavc_codec)
|
||||
return 0;
|
||||
|
||||
ctx->do_dr1 = ctx->do_hw_dr1 = 0;
|
||||
ctx->pix_fmt = PIX_FMT_NONE;
|
||||
|
@ -264,8 +239,8 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
|
|||
|
||||
avctx->flags |= lavc_param->bitexact;
|
||||
|
||||
avctx->coded_width = sh->disp_w;
|
||||
avctx->coded_height = sh->disp_h;
|
||||
avctx->coded_width = sh->bih ? sh->bih->biWidth : sh->disp_w;
|
||||
avctx->coded_height = sh->bih ? sh->bih->biHeight : sh->disp_h;
|
||||
avctx->workaround_bugs = lavc_param->workaround_bugs;
|
||||
if (lavc_param->gray)
|
||||
avctx->flags |= CODEC_FLAG_GRAY;
|
||||
|
@ -340,14 +315,6 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
|
|||
}
|
||||
break;
|
||||
|
||||
case MKTAG('M', 'P', 'v', 'f'):
|
||||
avctx->codec_tag = 0;
|
||||
avctx->pix_fmt = imgfmt2pixfmt(sh->imgfmt);
|
||||
break;
|
||||
case MKTAG('M', 'P', 'r', 'v'):
|
||||
avctx->codec_tag = sh->imgfmt;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!sh->bih || sh->bih->biSize <= sizeof(*sh->bih))
|
||||
break;
|
||||
|
@ -361,6 +328,11 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec)
|
|||
if (sh->bih)
|
||||
avctx->bits_per_coded_sample = sh->bih->biBitCount;
|
||||
|
||||
if (mp_rawvideo && sh->format >= IMGFMT_START && sh->format < IMGFMT_END) {
|
||||
avctx->pix_fmt = imgfmt2pixfmt(sh->format);
|
||||
avctx->codec_tag = 0;
|
||||
}
|
||||
|
||||
/* open it */
|
||||
if (avcodec_open2(avctx, lavc_codec, NULL) < 0) {
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n");
|
||||
|
@ -375,8 +347,6 @@ static void uninit_avctx(sh_video_t *sh)
|
|||
vd_ffmpeg_ctx *ctx = sh->context;
|
||||
AVCodecContext *avctx = ctx->avctx;
|
||||
|
||||
sh->codecname = NULL;
|
||||
|
||||
if (avctx) {
|
||||
if (avctx->codec && avcodec_close(avctx) < 0)
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not close codec.\n");
|
||||
|
@ -661,14 +631,14 @@ static struct mp_image *decode_with_fallback(struct sh_video *sh,
|
|||
return mpi;
|
||||
|
||||
// Failed hardware decoding? Try again in software.
|
||||
if (ctx->software_fallback) {
|
||||
if (ctx->software_fallback_decoder) {
|
||||
uninit_avctx(sh);
|
||||
sh->vf_initialized = 0;
|
||||
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error using hardware "
|
||||
"decoding, falling back to software decoding.\n");
|
||||
AVCodec *codec = ctx->software_fallback;
|
||||
ctx->software_fallback = NULL;
|
||||
if (init_avctx(sh, codec, NULL)) {
|
||||
const char *decoder = ctx->software_fallback_decoder;
|
||||
ctx->software_fallback_decoder = NULL;
|
||||
if (init_avctx(sh, decoder, NULL)) {
|
||||
mpi = NULL;
|
||||
decode(sh, packet, data, len, flags, reordered_pts, &mpi);
|
||||
return mpi;
|
||||
|
@ -700,8 +670,16 @@ static int control(sh_video_t *sh, int cmd, void *arg)
|
|||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
|
||||
static void add_decoders(struct mp_decoder_list *list)
|
||||
{
|
||||
mp_add_lavc_decoders(list, AVMEDIA_TYPE_VIDEO);
|
||||
mp_add_decoder(list, "lavc", "mp-rawvideo", "mp-rawvideo",
|
||||
"raw video");
|
||||
}
|
||||
|
||||
const struct vd_functions mpcodecs_vd_ffmpeg = {
|
||||
.info = &info,
|
||||
.name = "lavc",
|
||||
.add_decoders = add_decoders,
|
||||
.init = init,
|
||||
.uninit = uninit,
|
||||
.control = control,
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "video/mp_image.h"
|
||||
#include "core/mp_common.h"
|
||||
|
||||
#include "core/mpc_info.h"
|
||||
#include "video/vfcap.h"
|
||||
|
||||
struct MPOpts;
|
||||
|
|
|
@ -40,16 +40,6 @@
|
|||
|
||||
#define MP_FOURCC_MJPEG MP_FOURCC('M', 'J', 'P', 'G')
|
||||
|
||||
/* mplayer internal FourCCs
|
||||
* see codecs.conf/vd_lavc.c
|
||||
*/
|
||||
|
||||
// lavc raw video decoder uses fourcc specified in sh_video->imgfmt
|
||||
#define MP_FOURCC_RAWVIDEO MP_FOURCC('M', 'P', 'r', 'v')
|
||||
|
||||
// lavc raw video decoder uses image format (IMGFMT_*) in sh_video->imgfmt
|
||||
#define MP_FOURCC_IMGFMT MP_FOURCC('M', 'P', 'v', 'f')
|
||||
|
||||
// NOTE: no "HM12" decoder exists, as vd_hmblck has been removed
|
||||
// likely breaks video with some TV cards
|
||||
#define MP_FOURCC_HM12 0x32314D48
|
||||
|
|
Loading…
Reference in New Issue