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:
wm4 2013-02-09 15:15:19 +01:00
parent bb8da97205
commit 4d016a92c8
54 changed files with 1229 additions and 3935 deletions

1
.gitignore vendored
View File

@ -10,7 +10,6 @@
/mpv
/mpv.app
/version.h
/core/codecs.conf.h
/core/input/input_conf.h
/tags
/TAGS

View File

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

View File

@ -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
=================================== ===================================

View File

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

View File

@ -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.

View File

@ -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.

View File

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

View File

@ -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
};

View File

@ -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,

View File

@ -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,\

View File

@ -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");
}

View File

@ -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");
}

View File

@ -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");
}
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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.

24
configure vendored
View File

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

130
core/av_common.c Normal file
View File

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

30
core/av_common.h Normal file
View File

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

View File

@ -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),

View File

@ -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);
}
}

View File

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

147
core/codecs.c Normal file
View File

@ -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");
}

43
core/codecs.h Normal file
View File

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

View File

@ -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 },

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

379
demux/codec_tags.c Normal file
View File

@ -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;
}

31
demux/codec_tags.h Normal file
View File

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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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 *

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

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