mirror of https://github.com/mpv-player/mpv
spelling/grammar/wording/whitespace
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@28304 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
0ccbcc55a7
commit
656660e560
|
@ -12,7 +12,7 @@ The VIDEO path:
|
|||
|
||||
[MPlayer core]
|
||||
| (1)
|
||||
______V_____ (2) /~~~~~~~~~~\ (3,4) |~~~~~~|
|
||||
______V______ (2) /~~~~~~~~~~\ (3,4) |~~~~~~|
|
||||
| | -----> | vd_XXX.c | -------> | vd.c |
|
||||
| dec_video | \__________/ <-(3a)-- |______|
|
||||
| | -----, ,.............(3a,4a).....:
|
||||
|
@ -27,54 +27,56 @@ The VIDEO path:
|
|||
|
||||
Short description of video path:
|
||||
1. MPlayer/MEncoder core requests the decoding of a compressed video frame:
|
||||
calls dec_video.c::decode_video()
|
||||
calls dec_video.c::decode_video().
|
||||
|
||||
2. decode_video() calls the previously ( init_video() ) selected video codec
|
||||
2. decode_video() calls the video codec previously selected in init_video().
|
||||
(vd_XXX.c file, where XXX == vfm name, see the 'driver' line of codecs.conf)
|
||||
|
||||
3. The codec should initialize the output device before decoding the first
|
||||
frame, it may happen in init() or at the middle of the first decode(), see
|
||||
frame. It may happen in init() or at the middle of the first decode(), see
|
||||
3a. It means calling vd.c::mpcodecs_config_vo() with the image dimensions,
|
||||
and the _preferred_ (mean: internal, native, best) colorspace.
|
||||
NOTE: This colorspace may not be equal to the actually used colorspace, it's
|
||||
just a _hint_ for the csp matching algorithm, and mainly used _only_ when
|
||||
csp conversion is required, as input format of the converter.
|
||||
and the _preferred_ (meaning: internal, native, best) colorspace.
|
||||
NOTE: This colorspace may not be equal to the colorspace that is actually
|
||||
used. It's just a _hint_ for the colorspace matching algorithm and mainly
|
||||
used as input format of the converter, but _only_ when colorspace
|
||||
conversion is required,
|
||||
|
||||
3a. Selecting the best output colorspace:
|
||||
The vd.c::mpcodecs_config_vo() function will go through the outfmt list
|
||||
defined by codecs.conf's 'out' lines, and query both vd (codec) and vo
|
||||
(output device/filter/encoder) if it's supported or not.
|
||||
defined by the 'out' lines in codecs.conf and query both vd (codec) and
|
||||
vo (output device/filter/encoder) if the format is supported or not.
|
||||
|
||||
For the vo, it calls the query_format() function of vf_XXX.c or ve_XXX.c.
|
||||
It should return a set of feature flags, the most important ones for this
|
||||
stage are: VFCAP_CSP_SUPPORTED (csp supported directly or by conversion)
|
||||
and VFCAP_CSP_SUPPORTED_BY_HW (csp supported WITHOUT any conversion).
|
||||
stage are: VFCAP_CSP_SUPPORTED (colorspace supported directly or by
|
||||
conversion) and VFCAP_CSP_SUPPORTED_BY_HW (colorspace supported
|
||||
WITHOUT any conversion).
|
||||
|
||||
For the vd (codec), control() with VDCTRL_QUERY_FORMAT will be called.
|
||||
If it doesn't implement VDCTRL_QUERY_FORMAT, (i.e. answers CONTROL_UNKNOWN
|
||||
or CONTROL_NA), it will be assumed to be CONTROL_TRUE (csp supported)!
|
||||
If it does not implement VDCTRL_QUERY_FORMAT, (i.e. answers CONTROL_UNKNOWN
|
||||
or CONTROL_NA), it is assumed to be CONTROL_TRUE (colorspace supported)!
|
||||
|
||||
So, by default, if the list of supported colorspaces is constant, doesn't
|
||||
depend on the actual file's/stream's header, it's enough to list them
|
||||
in codecs.conf ('out' field), and don't implement VDCTRL_QUERY_FORMAT.
|
||||
So, by default, if the list of supported colorspaces is constant and does
|
||||
not depend on the actual file/stream header, then it is enough to list the
|
||||
formats in codecs.conf ('out' field) and not implement VDCTRL_QUERY_FORMAT.
|
||||
This is the case for most codecs.
|
||||
|
||||
If the supported csp list depends on the file being decoded, list the
|
||||
possible out formats (colorspaces) in codecs.conf, and implement the
|
||||
VDCTRL_QUERY_FORMAT to test the availability of the given csp for the
|
||||
given video file/stream.
|
||||
If the supported colorspace list depends on the file being decoded, list
|
||||
the possible out formats (colorspaces) in codecs.conf and implement the
|
||||
VDCTRL_QUERY_FORMAT to test the availability of the given colorspace for
|
||||
the given video file/stream.
|
||||
|
||||
The vd.c core will find the best matching colorspace, depending on the
|
||||
VFCAP_CSP_SUPPORTED_BY_HW flag (see vfcap.h). If no match at all, it
|
||||
will try again with the 'scale' filter inserted between vd and vo.
|
||||
If still no match, it will fail :(
|
||||
VFCAP_CSP_SUPPORTED_BY_HW flag (see vfcap.h). If no match can be found,
|
||||
it will try again with the 'scale' filter inserted between vd and vo.
|
||||
If this is unsuccessful, it will fail :(
|
||||
|
||||
4. Requesting buffer for the decoded frame:
|
||||
The codec has to call mpcodecs_get_image() with proper imgtype & imgflag.
|
||||
It will find the optimal buffering setup (preferred stride, alignment etc)
|
||||
and return a pointer to the allocated and filled up mpi (mp_image_t*) struct.
|
||||
The 'imgtype' controls the buffering setup, i.e. STATIC (just one buffer,
|
||||
it 'remembers' its contents between frames), TEMP (write-only, full update),
|
||||
The 'imgtype' controls the buffering setup, i.e. STATIC (just one buffer that
|
||||
'remembers' its content between frames), TEMP (write-only, full update),
|
||||
EXPORT (memory allocation is done by the codec, not recommended) and so on.
|
||||
The 'imgflags' set up the limits for the buffer, i.e. stride limitations,
|
||||
readability, remembering content etc. See mp_image.h for the short
|
||||
|
@ -88,11 +90,11 @@ Short description of video path:
|
|||
Also take care of other imgflags, like MP_IMGFLAG_PRESERVE and
|
||||
MP_IMGFLAG_READABLE, MP_IMGFLAG_COMMON_STRIDE and MP_IMGFLAG_COMMON_PLANE!
|
||||
The file mp_image.h contains flag descriptions in comments, read it!
|
||||
Ask for help on dev-eng, describing the behaviour your codec, if unsure.
|
||||
Ask for help on dev-eng, describing the behavior of your codec, if unsure.
|
||||
|
||||
4.a. buffer allocation, vd.c::mpcodecs_get_image():
|
||||
If the requested buffer imgtype!=EXPORT, then vd.c will try to do
|
||||
direct rendering, i.e. asks the next filter/vo for the buffer allocation.
|
||||
direct rendering, i.e. ask the next filter/vo for the buffer allocation.
|
||||
It's done by calling get_image() of the vf_XXX.c file.
|
||||
If it was successful, the imgflag MP_IMGFLAG_DIRECT will be set, and one
|
||||
memcpy() will be saved when passing the data from vd to the next filter/vo.
|
||||
|
@ -149,8 +151,8 @@ vf_info_t* info;
|
|||
|
||||
const char *info; // description of the filter
|
||||
const char *name; // short name of the filter, must be FILTERNAME
|
||||
const char *author; // name and email/url of the author(s)
|
||||
const char *comment; // comment, url to papers describing algo etc.
|
||||
const char *author; // name and email/URL of the author(s)
|
||||
const char *comment; // comment, URL to papers describing algorithm etc.
|
||||
int (*open)(struct vf_instance_s* vf,char* args);
|
||||
// pointer to the open() function:
|
||||
|
||||
|
@ -171,24 +173,25 @@ The open() function:
|
|||
char* string. Note that encoders (ve_*) and vo wrapper (vf_vo.c) have
|
||||
non-string arg, but it's specially handled by MPlayer/MEncoder.
|
||||
|
||||
The open() function should fill the vf_instance_t structure, with the
|
||||
The open() function should fill the vf_instance_t structure with the
|
||||
implemented functions' pointers (see below).
|
||||
It can optionally allocate memory for its internal data (vf_priv_t) and
|
||||
store the pointer in vf->priv.
|
||||
|
||||
The open() func should parse (or at least check syntax) of parameters,
|
||||
and fail (return 0) if error.
|
||||
The open() function should parse (or at least check syntax of) parameters,
|
||||
and fail (return 0) on error.
|
||||
|
||||
Sample:
|
||||
|
||||
static int open(vf_instance_t *vf, char* args){
|
||||
vf->query_format=query_format;
|
||||
vf->config=config;
|
||||
vf->put_image=put_image;
|
||||
static int open(vf_instance_t *vf, char* args)
|
||||
{
|
||||
vf->query_format = query_format;
|
||||
vf->config = config;
|
||||
vf->put_image = put_image;
|
||||
// allocate local storage:
|
||||
vf->priv=malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->w=
|
||||
vf->priv->h=-1;
|
||||
vf->priv = malloc(sizeof(struct vf_priv_s));
|
||||
vf->priv->w =
|
||||
vf->priv->h = -1;
|
||||
if(args) // parse args:
|
||||
if(sscanf(args, "%d:%d", &vf->priv->w, &vf->priv->h)!=2) return 0;
|
||||
return 1;
|
||||
|
@ -200,8 +203,7 @@ NOTE: All these are optional, their function pointer is either NULL or points
|
|||
to a default implementation. If you implement them, don't forget to set
|
||||
vf->FUNCNAME in your open() !
|
||||
|
||||
int (*query_format)(struct vf_instance_s* vf,
|
||||
unsigned int fmt);
|
||||
int (*query_format)(struct vf_instance_s* vf, unsigned int fmt);
|
||||
|
||||
The query_format() function is called one or more times before the config(),
|
||||
to find out the capabilities and/or support status of a given colorspace (fmt).
|
||||
|
@ -214,7 +216,8 @@ next filter will accept at least one of your possible output colorspaces!
|
|||
|
||||
Sample:
|
||||
|
||||
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
|
||||
static int query_format(struct vf_instance_s* vf, unsigned int fmt)
|
||||
{
|
||||
switch(fmt){
|
||||
case IMGFMT_YV12:
|
||||
case IMGFMT_I420:
|
||||
|
@ -225,7 +228,7 @@ static int query_format(struct vf_instance_s* vf, unsigned int fmt){
|
|||
return 0;
|
||||
}
|
||||
|
||||
For the more complex case, when you have an N->M colorspace mapping matrix,
|
||||
For the more complex case, when you have an N -> M colorspace mapping matrix,
|
||||
see vf_scale or vf_rgb2bgr for examples.
|
||||
|
||||
|
||||
|
@ -237,7 +240,7 @@ The config() is called to initialize/configure the filter before using it.
|
|||
Its parameters are already well-known from libvo:
|
||||
width, height: size of the coded image
|
||||
d_width, d_height: wanted display size (usually aspect corrected w/h)
|
||||
Filters should use width,height as input image dimension, but the
|
||||
Filters should use width, height as input image dimension, but the
|
||||
resizing filters (crop, expand, scale, rotate, etc) should update
|
||||
d_width/d_height (display size) to preserve the correct aspect ratio!
|
||||
Filters should not rely on d_width, d_height as input parameters,
|
||||
|
@ -255,11 +258,14 @@ Its parameters are already well-known from libvo:
|
|||
Sample:
|
||||
|
||||
static int config(struct vf_instance_s* vf,
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt){
|
||||
// use d_width/d_height if not set by user:
|
||||
if(vf->priv->w==-1) vf->priv->w=d_width;
|
||||
if(vf->priv->h==-1) vf->priv->h=d_height;
|
||||
int width, int height, int d_width, int d_height,
|
||||
unsigned int flags, unsigned int outfmt)
|
||||
{
|
||||
// use d_width/d_height if not set by the user:
|
||||
if (vf->priv->w == -1)
|
||||
vf->priv->w = d_width;
|
||||
if (vf->priv->h == -1)
|
||||
vf->priv->h = d_height;
|
||||
// initialize your filter code
|
||||
...
|
||||
// OK now config the rest of the filter chain, with our output parameters:
|
||||
|
@ -268,11 +274,10 @@ static int config(struct vf_instance_s* vf,
|
|||
|
||||
void (*uninit)(struct vf_instance_s* vf);
|
||||
|
||||
Okey, uninit() is the simplest, it's called at the end. You can free your
|
||||
Okay, uninit() is the simplest, it's called at the end. You can free your
|
||||
private buffers etc here.
|
||||
|
||||
int (*put_image)(struct vf_instance_s* vf,
|
||||
mp_image_t *mpi);
|
||||
int (*put_image)(struct vf_instance_s* vf, mp_image_t *mpi);
|
||||
|
||||
Ah, put_image(). This is the main filter function, it should convert/filter/
|
||||
transform the image data from one format/size/color/whatever to another.
|
||||
|
@ -286,27 +291,26 @@ NEVER pass the mpi as-is, it's local to the filters and may cause trouble.
|
|||
|
||||
If you completely copy/transform the image, then you probably want this:
|
||||
|
||||
dmpi=vf_get_image(vf->next,mpi->imgfmt,
|
||||
MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
|
||||
vf->priv->w, vf->priv->h);
|
||||
dmpi = vf_get_image(vf->next,mpi->imgfmt, MP_IMGTYPE_TEMP,
|
||||
MP_IMGFLAG_ACCEPT_STRIDE, vf->priv->w, vf->priv->h);
|
||||
|
||||
It will allocate a new image, and return an mp_image structure filled by
|
||||
It will allocate a new image and return an mp_image structure filled by
|
||||
buffer pointers and stride (bytes per line) values, in size of vf->priv->w
|
||||
times vf->priv->h. If your filter cannot handle stride, then leave out
|
||||
MP_IMGFLAG_ACCEPT_STRIDE. Note that you can do this, but it isn't recommended,
|
||||
the whole video path is designed to use strides to get optimal throughput.
|
||||
If your filter allocates output image buffers, then use MP_IMGTYPE_EXPORT,
|
||||
If your filter allocates output image buffers, then use MP_IMGTYPE_EXPORT
|
||||
and fill the returned dmpi's planes[], stride[] with your buffer parameters.
|
||||
Note, it is not recommended (no direct rendering), so if you can, use
|
||||
vf_get_image() for buffer allocation!
|
||||
For other image types and flags see mp_image.h, it has comments.
|
||||
If you are unsure, feel free to ask on the -dev-eng mailing list. Please
|
||||
If you are unsure, feel free to ask on the dev-eng mailing list. Please
|
||||
describe the behavior of your filter, and its limitations, so we can
|
||||
suggest the optimal buffer type + flags for your code.
|
||||
|
||||
Now that you have the input (mpi) and output (dmpi) buffers, you can do
|
||||
the conversion. If you didn't notice yet, mp_image has some useful info
|
||||
fields, may help you a lot creating if() or for() structures:
|
||||
fields. They may help you a lot creating if() or for() structures:
|
||||
flags: MP_IMGFLAG_PLANAR, MP_IMGFLAG_YUV, MP_IMGFLAG_SWAPPED
|
||||
helps you to handle various pixel formats in single code.
|
||||
bpp: bits per pixel
|
||||
|
@ -317,9 +321,9 @@ fields, may help you a lot creating if() or for() structures:
|
|||
It's 1 for 1bpp, 9 for YVU9, and is 12 for YV12 mode. Get it?
|
||||
For planar formats, you also have chroma_width, chroma_height and
|
||||
chroma_x_shift, chroma_y_shift too, they specify the chroma subsampling
|
||||
for yuv formats:
|
||||
chroma_width = luma_width >>chroma_x_shift;
|
||||
chroma_height= luma_height>>chroma_y_shift;
|
||||
for YUV formats:
|
||||
chroma_width = luma_width >> chroma_x_shift;
|
||||
chroma_height = luma_height >> chroma_y_shift;
|
||||
|
||||
If you're done, call the rest of the filter chain to process your output
|
||||
image:
|
||||
|
@ -328,24 +332,22 @@ image:
|
|||
|
||||
Ok, the rest is for advanced functionality only:
|
||||
|
||||
int (*control)(struct vf_instance_s* vf,
|
||||
int request, void* data);
|
||||
int (*control)(struct vf_instance_s* vf, int request, void* data);
|
||||
|
||||
You can control the filter at runtime from MPlayer/MEncoder/dec_video:
|
||||
#define VFCTRL_QUERY_MAX_PP_LEVEL 4 /* test for postprocessing support (max level) */
|
||||
#define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
|
||||
#define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
|
||||
#define VFCTRL_GET_EQUALIZER 8 /* get color options (brightness,contrast etc) */
|
||||
#define VFCTRL_DRAW_OSD 7
|
||||
#define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
|
||||
#define VFCTRL_SET_PP_LEVEL 5 /* set postprocessing level */
|
||||
#define VFCTRL_SET_EQUALIZER 6 /* set color options (brightness,contrast etc) */
|
||||
#define VFCTRL_GET_EQUALIZER 8 /* get color options (brightness,contrast etc) */
|
||||
#define VFCTRL_DRAW_OSD 7
|
||||
#define VFCTRL_CHANGE_RECTANGLE 9 /* Change the rectangle boundaries */
|
||||
|
||||
|
||||
void (*get_image)(struct vf_instance_s* vf,
|
||||
mp_image_t *mpi);
|
||||
void (*get_image)(struct vf_instance_s* vf, mp_image_t *mpi);
|
||||
|
||||
This is for direct rendering support, works the same way as in libvo drivers.
|
||||
It makes in-place pixel modifications possible.
|
||||
If you implement it (vf->get_image!=NULL) then it will be called to do the
|
||||
If you implement it (vf->get_image!=NULL), then it will be called to do the
|
||||
buffer allocation. You SHOULD check the buffer restrictions (stride, type,
|
||||
readability etc) and if everything is OK, then allocate the requested buffer
|
||||
using the vf_get_image() function and copying the buffer pointers.
|
||||
|
@ -357,8 +359,8 @@ order, while put_image is called for display) so the only safe place to save
|
|||
it is in the mpi struct itself: mpi->priv=(void*)dmpi;
|
||||
|
||||
|
||||
void (*draw_slice)(struct vf_instance_s* vf,
|
||||
unsigned char** src, int* stride, int w,int h, int x, int y);
|
||||
void (*draw_slice)(struct vf_instance_s* vf, unsigned char** src,
|
||||
int* stride, int w,int h, int x, int y);
|
||||
|
||||
It's the good old draw_slice callback, already known from libvo.
|
||||
If your filter can operate on partial images, you can implement this one
|
||||
|
@ -373,8 +375,8 @@ the automatic colorspace/stride matching code (vf_next_config()).
|
|||
unsigned int default_reqs; // used by default config()
|
||||
|
||||
BTW, you should avoid using global or static variables to store filter instance
|
||||
specific stuff, as filters might be used multiple times & in the future even
|
||||
multiple streams might be possible
|
||||
specific stuff, as filters might be used multiple times and in the future even
|
||||
multiple streams might be possible.
|
||||
|
||||
|
||||
The AUDIO path:
|
||||
|
|
Loading…
Reference in New Issue