mirror of https://github.com/mpv-player/mpv
video: use libavutil pixel format descriptors
Replace the internal pixel format stuff with code that queries the libavutil list of pixel format descriptors. Trying to map IMGFMT_IS_RGB() etc. turned out extremely hacky.
This commit is contained in:
parent
6e0b730044
commit
00653a3eb0
|
@ -16,122 +16,18 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <libavutil/pixfmt.h>
|
||||||
|
#include <libavutil/pixdesc.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "video/img_format.h"
|
#include "video/img_format.h"
|
||||||
#include "stdio.h"
|
#include "video/mp_image.h"
|
||||||
#include "compat/mpbswap.h"
|
#include "video/fmt-conversion.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
const char *vo_format_name(int format)
|
|
||||||
{
|
|
||||||
const char *name = mp_imgfmt_to_name(format);
|
|
||||||
if (name)
|
|
||||||
return name;
|
|
||||||
static char unknown_format[20];
|
|
||||||
snprintf(unknown_format, 20, "Unknown 0x%04x", format);
|
|
||||||
return unknown_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mp_get_chroma_shift(int format, int *x_shift, int *y_shift,
|
|
||||||
int *component_bits)
|
|
||||||
{
|
|
||||||
int xs = 0, ys = 0;
|
|
||||||
int bpp;
|
|
||||||
int err = 0;
|
|
||||||
int bits = 8;
|
|
||||||
if ((format & 0xff0000f0) == 0x34000050)
|
|
||||||
format = bswap_32(format);
|
|
||||||
if ((format & 0xf00000ff) == 0x50000034) {
|
|
||||||
switch (format >> 24) {
|
|
||||||
case 0x50:
|
|
||||||
break;
|
|
||||||
case 0x51:
|
|
||||||
bits = 16;
|
|
||||||
break;
|
|
||||||
case 0x55:
|
|
||||||
bits = 14;
|
|
||||||
break;
|
|
||||||
case 0x54:
|
|
||||||
bits = 12;
|
|
||||||
break;
|
|
||||||
case 0x52:
|
|
||||||
bits = 10;
|
|
||||||
break;
|
|
||||||
case 0x53:
|
|
||||||
bits = 9;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (format & 0x00ffffff) {
|
|
||||||
case 0x00343434: // 444
|
|
||||||
xs = 0;
|
|
||||||
ys = 0;
|
|
||||||
break;
|
|
||||||
case 0x00323234: // 422
|
|
||||||
xs = 1;
|
|
||||||
ys = 0;
|
|
||||||
break;
|
|
||||||
case 0x00303234: // 420
|
|
||||||
xs = 1;
|
|
||||||
ys = 1;
|
|
||||||
break;
|
|
||||||
case 0x00313134: // 411
|
|
||||||
xs = 2;
|
|
||||||
ys = 0;
|
|
||||||
break;
|
|
||||||
case 0x00303434: // 440
|
|
||||||
xs = 0;
|
|
||||||
ys = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
switch (format) {
|
|
||||||
case IMGFMT_420A:
|
|
||||||
case IMGFMT_I420:
|
|
||||||
case IMGFMT_IYUV:
|
|
||||||
case IMGFMT_YV12:
|
|
||||||
xs = 1;
|
|
||||||
ys = 1;
|
|
||||||
break;
|
|
||||||
case IMGFMT_IF09:
|
|
||||||
case IMGFMT_YVU9:
|
|
||||||
xs = 2;
|
|
||||||
ys = 2;
|
|
||||||
break;
|
|
||||||
case IMGFMT_Y8:
|
|
||||||
case IMGFMT_Y800:
|
|
||||||
xs = 31;
|
|
||||||
ys = 31;
|
|
||||||
break;
|
|
||||||
case IMGFMT_Y16BE:
|
|
||||||
case IMGFMT_Y16LE:
|
|
||||||
bits = 16;
|
|
||||||
xs = 31;
|
|
||||||
ys = 31;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (x_shift)
|
|
||||||
*x_shift = xs;
|
|
||||||
if (y_shift)
|
|
||||||
*y_shift = ys;
|
|
||||||
if (component_bits)
|
|
||||||
*component_bits = bits;
|
|
||||||
bpp = 8 + ((16 >> xs) >> ys);
|
|
||||||
if (format == IMGFMT_420A)
|
|
||||||
bpp += 8;
|
|
||||||
bpp *= (bits + 7) >> 3;
|
|
||||||
return err ? 0 : bpp;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mp_imgfmt_entry mp_imgfmt_list[] = {
|
struct mp_imgfmt_entry mp_imgfmt_list[] = {
|
||||||
{"444p16le", IMGFMT_444P16_LE},
|
{"444p16le", IMGFMT_444P16_LE},
|
||||||
{"444p16be", IMGFMT_444P16_BE},
|
{"444p16be", IMGFMT_444P16_BE},
|
||||||
|
@ -237,6 +133,32 @@ struct mp_imgfmt_entry mp_imgfmt_list[] = {
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *vo_format_name(int format)
|
||||||
|
{
|
||||||
|
const char *name = mp_imgfmt_to_name(format);
|
||||||
|
if (name)
|
||||||
|
return name;
|
||||||
|
static char unknown_format[20];
|
||||||
|
snprintf(unknown_format, 20, "Unknown 0x%04x", format);
|
||||||
|
return unknown_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mp_get_chroma_shift(int format, int *x_shift, int *y_shift,
|
||||||
|
int *component_bits)
|
||||||
|
{
|
||||||
|
struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(format);
|
||||||
|
if (fmt.id && (fmt.flags & MP_IMGFLAG_YUV_P)) {
|
||||||
|
if (x_shift)
|
||||||
|
*x_shift = fmt.xs[1];
|
||||||
|
if (y_shift)
|
||||||
|
*y_shift = fmt.ys[1];
|
||||||
|
if (component_bits)
|
||||||
|
*component_bits = fmt.plane_bits;
|
||||||
|
return fmt.avg_bpp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int mp_imgfmt_from_name(bstr name, bool allow_hwaccel)
|
unsigned int mp_imgfmt_from_name(bstr name, bool allow_hwaccel)
|
||||||
{
|
{
|
||||||
if (bstr_startswith0(name, "0x")) {
|
if (bstr_startswith0(name, "0x")) {
|
||||||
|
@ -264,3 +186,171 @@ const char *mp_imgfmt_to_name(unsigned int fmt)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int comp_bit_order(const AVPixFmtDescriptor *pd, int bpp, int c)
|
||||||
|
{
|
||||||
|
int el_size = (pd->flags & PIX_FMT_BITSTREAM) ? 1 : 8;
|
||||||
|
// NOTE: offset_plus1 can be 0
|
||||||
|
int offset = (((int)pd->comp[c].offset_plus1) - 1) * el_size;
|
||||||
|
int read_depth = pd->comp[c].shift + pd->comp[c].depth_minus1 + 1;
|
||||||
|
if (read_depth <= 8 && !(pd->flags & PIX_FMT_BITSTREAM))
|
||||||
|
offset += 8 * !!(pd->flags & PIX_FMT_BE);
|
||||||
|
offset += pd->comp[c].shift;
|
||||||
|
// revert ffmpeg's bullshit hack that mixes byte and bit access
|
||||||
|
if ((pd->flags & PIX_FMT_BE) && bpp <= 16 && read_depth <= 8)
|
||||||
|
offset = (8 + offset) % 16;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mp_imgfmt_desc get_avutil_fmt(enum PixelFormat fmt)
|
||||||
|
{
|
||||||
|
const AVPixFmtDescriptor *pd = &av_pix_fmt_descriptors[fmt];
|
||||||
|
int mpfmt = pixfmt2imgfmt(fmt);
|
||||||
|
if (!pd || !mpfmt)
|
||||||
|
return (struct mp_imgfmt_desc) {0};
|
||||||
|
|
||||||
|
struct mp_imgfmt_desc desc = {
|
||||||
|
.id = mpfmt,
|
||||||
|
.avformat = fmt,
|
||||||
|
.name = mp_imgfmt_to_name(desc.id),
|
||||||
|
.chroma_xs = pd->log2_chroma_w,
|
||||||
|
.chroma_ys = pd->log2_chroma_h,
|
||||||
|
};
|
||||||
|
|
||||||
|
int planedepth[4] = {0};
|
||||||
|
int xs[4] = {0, pd->log2_chroma_w, pd->log2_chroma_w, 0};
|
||||||
|
int ys[4] = {0, pd->log2_chroma_h, pd->log2_chroma_h, 0};
|
||||||
|
int el_size = (pd->flags & PIX_FMT_BITSTREAM) ? 1 : 8;
|
||||||
|
for (int c = 0; c < pd->nb_components; c++) {
|
||||||
|
AVComponentDescriptor d = pd->comp[c];
|
||||||
|
// multiple components per plane -> Y is definitive, ignore chroma
|
||||||
|
if (!desc.bpp[d.plane])
|
||||||
|
desc.bpp[d.plane] = (d.step_minus1 + 1) * el_size;
|
||||||
|
planedepth[d.plane] += d.depth_minus1 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int avgbpp16 = 0;
|
||||||
|
for (int p = 0; p < 4; p++)
|
||||||
|
avgbpp16 += (16 * desc.bpp[p]) >> xs[p] >> ys[p];
|
||||||
|
desc.avg_bpp = avgbpp16 / 16;
|
||||||
|
//assert(desc.avg_bpp == av_get_padded_bits_per_pixel(pd));
|
||||||
|
|
||||||
|
for (int p = 0; p < 4; p++) {
|
||||||
|
if (desc.bpp[p])
|
||||||
|
desc.num_planes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.bpp[0] <= 8 || !(pd->flags & PIX_FMT_BE))
|
||||||
|
desc.flags |= MP_IMGFLAG_NE;
|
||||||
|
|
||||||
|
desc.plane_bits = planedepth[0];
|
||||||
|
|
||||||
|
if (!(pd->flags & PIX_FMT_RGB) && !(pd->flags & PIX_FMT_HWACCEL) &&
|
||||||
|
fmt != PIX_FMT_MONOWHITE && fmt != PIX_FMT_MONOBLACK &&
|
||||||
|
fmt != PIX_FMT_PAL8)
|
||||||
|
{
|
||||||
|
desc.flags |= MP_IMGFLAG_YUV;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PIX_FMT_ALPHA
|
||||||
|
if (pd->flags & PIX_FMT_ALPHA)
|
||||||
|
desc.flags |= MP_IMGFLAG_ALPHA;
|
||||||
|
#else
|
||||||
|
if (desc.num_planes > 3)
|
||||||
|
desc.flags |= MP_IMGFLAG_ALPHA;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (desc.num_planes > 1)
|
||||||
|
desc.flags |= MP_IMGFLAG_PLANAR;
|
||||||
|
|
||||||
|
if (desc.flags & MP_IMGFLAG_YUV) {
|
||||||
|
bool same_depth = true;
|
||||||
|
for (int p = 0; p < desc.num_planes; p++) {
|
||||||
|
same_depth &= planedepth[p] == planedepth[0] &&
|
||||||
|
desc.bpp[p] == desc.bpp[0];
|
||||||
|
}
|
||||||
|
if (same_depth && pd->nb_components == desc.num_planes)
|
||||||
|
desc.flags |= MP_IMGFLAG_YUV_P;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pd->flags & PIX_FMT_RGB) && desc.num_planes == 1
|
||||||
|
&& pd->nb_components >= 3)
|
||||||
|
{
|
||||||
|
// RGB vs. BGR component order, as distinguished by mplayer:
|
||||||
|
// - for byte accessed formats (RGB24, RGB48), the order of bytes
|
||||||
|
// determines RGB/BGR (e.g. R is first byte -> RGB)
|
||||||
|
// - for bit accessed formats (RGB32, RGB16, etc.), the order of bits
|
||||||
|
// determines BGR/RGB (e.g. R is LSB -> RGB)
|
||||||
|
// - formats like IMGFMT_RGBA are aliases to allow byte access to bit-
|
||||||
|
// accessed formats (IMGFMT_RGBA is RGB32 on LE, BGR32|128 on BE)
|
||||||
|
// (ffmpeg does it the other way around, and defines bit-access
|
||||||
|
// aliases to byte-accessed formats)
|
||||||
|
int b = desc.bpp[0];
|
||||||
|
bool swap = comp_bit_order(pd, b, 0) > comp_bit_order(pd, b, 1);
|
||||||
|
if ((desc.bpp[0] == 24 || desc.bpp[0] > 32) && BYTE_ORDER == BIG_ENDIAN)
|
||||||
|
swap = !swap; // byte accessed
|
||||||
|
if (swap)
|
||||||
|
desc.flags |= MP_IMGFLAG_SWAPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compatibility with old mp_image_setfmt()
|
||||||
|
|
||||||
|
switch (desc.id) {
|
||||||
|
case IMGFMT_I420:
|
||||||
|
case IMGFMT_IYUV:
|
||||||
|
desc.flags |= MP_IMGFLAG_SWAPPED; // completely pointless
|
||||||
|
break;
|
||||||
|
case IMGFMT_UYVY:
|
||||||
|
desc.flags |= MP_IMGFLAG_SWAPPED; // for vf_mpi_clear()
|
||||||
|
/* fallthrough */
|
||||||
|
case IMGFMT_YUY2:
|
||||||
|
desc.chroma_ys = 1; // ???
|
||||||
|
break;
|
||||||
|
case IMGFMT_Y8:
|
||||||
|
case IMGFMT_Y800:
|
||||||
|
case IMGFMT_Y16LE:
|
||||||
|
case IMGFMT_Y16BE:
|
||||||
|
// probably for vo_opengl, and possibly more code using Y8
|
||||||
|
desc.chroma_xs = desc.chroma_ys = 31;
|
||||||
|
break;
|
||||||
|
case IMGFMT_NV12:
|
||||||
|
desc.flags |= MP_IMGFLAG_SWAPPED; // completely pointless
|
||||||
|
/* fallthrough */
|
||||||
|
case IMGFMT_NV21:
|
||||||
|
// some hack to make cropping code etc. work? (doesn't work anyway)
|
||||||
|
desc.chroma_xs = 0;
|
||||||
|
desc.chroma_ys = 1;
|
||||||
|
break;
|
||||||
|
case IMGFMT_RGB4:
|
||||||
|
case IMGFMT_BGR4:
|
||||||
|
case IMGFMT_BGR1:
|
||||||
|
desc.flags ^= MP_IMGFLAG_SWAPPED; // ???
|
||||||
|
break;
|
||||||
|
case IMGFMT_BGR0:
|
||||||
|
desc.flags &= ~MP_IMGFLAG_SWAPPED; // not covered by IS_RGB/IS_BGR
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pd->flags & PIX_FMT_HWACCEL)
|
||||||
|
desc.chroma_xs = desc.chroma_ys = 0;
|
||||||
|
|
||||||
|
for (int p = 0; p < desc.num_planes; p++) {
|
||||||
|
desc.xs[p] = (p == 1 || p == 2) ? desc.chroma_xs : 0;
|
||||||
|
desc.ys[p] = (p == 1 || p == 2) ? desc.chroma_ys : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mp_imgfmt_desc mp_imgfmt_get_desc(unsigned int out_fmt)
|
||||||
|
{
|
||||||
|
struct mp_imgfmt_desc fmt = {0};
|
||||||
|
enum PixelFormat avfmt = imgfmt2pixfmt(out_fmt);
|
||||||
|
if (avfmt != PIX_FMT_NONE)
|
||||||
|
fmt = get_avutil_fmt(avfmt);
|
||||||
|
if (!fmt.id) {
|
||||||
|
mp_msg(MSGT_DECVIDEO, MSGL_V, "mp_image: unknown out_fmt: 0x%X\n",
|
||||||
|
out_fmt);
|
||||||
|
}
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,46 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "core/bstr.h"
|
#include "core/bstr.h"
|
||||||
|
|
||||||
|
#define MP_MAX_PLANES 4
|
||||||
|
|
||||||
|
// set if (possibly) alpha is included (might be not definitive for packed RGB)
|
||||||
|
#define MP_IMGFLAG_ALPHA 0x80
|
||||||
|
// set if number of planes > 1
|
||||||
|
#define MP_IMGFLAG_PLANAR 0x100
|
||||||
|
// set if it's YUV colorspace
|
||||||
|
#define MP_IMGFLAG_YUV 0x200
|
||||||
|
// set if it's swapped (BGR or YVU) plane/byteorder
|
||||||
|
#define MP_IMGFLAG_SWAPPED 0x400
|
||||||
|
// set if you want memory for palette allocated and managed by vf_get_image etc.
|
||||||
|
#define MP_IMGFLAG_RGB_PALETTE 0x800
|
||||||
|
// set if the format is standard YUV format:
|
||||||
|
// - planar and yuv colorspace
|
||||||
|
// - chroma shift 0-2
|
||||||
|
// - 1-4 planes (1: gray, 2: gray/alpha, 3: yuv, 4: yuv/alpha)
|
||||||
|
// - 8-16 bit per pixel/plane, all planes have same depth
|
||||||
|
#define MP_IMGFLAG_YUV_P 0x1000
|
||||||
|
// set if format is in native endian, or <= 8 bit per pixel/plane
|
||||||
|
#define MP_IMGFLAG_NE 0x2000
|
||||||
|
|
||||||
|
#define MP_IMGFLAG_FMT_MASK 0x3FFF
|
||||||
|
|
||||||
|
struct mp_imgfmt_desc {
|
||||||
|
int id; // IMGFMT_*
|
||||||
|
int avformat; // AV_PIX_FMT_* (or AV_PIX_FMT_NONE)
|
||||||
|
const char *name; // e.g. "420p16"
|
||||||
|
int flags; // MP_IMGFLAG_* bitfield
|
||||||
|
int num_planes;
|
||||||
|
int chroma_xs, chroma_ys; // chroma shift (i.e. log2 of chroma pixel size)
|
||||||
|
int avg_bpp;
|
||||||
|
int bpp[MP_MAX_PLANES];
|
||||||
|
int plane_bits; // number of bits in use for plane 0
|
||||||
|
// chroma shifts per plane (provided for convenience with planar formats)
|
||||||
|
int xs[MP_MAX_PLANES];
|
||||||
|
int ys[MP_MAX_PLANES];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mp_imgfmt_desc mp_imgfmt_get_desc(unsigned int out_fmt);
|
||||||
|
|
||||||
/* RGB/BGR Formats */
|
/* RGB/BGR Formats */
|
||||||
|
|
||||||
#define IMGFMT_RGB_MASK 0xFFFFFF00
|
#define IMGFMT_RGB_MASK 0xFFFFFF00
|
||||||
|
@ -95,14 +135,26 @@
|
||||||
#define IMGFMT_RG4B IMGFMT_RGB4_CHAR
|
#define IMGFMT_RG4B IMGFMT_RGB4_CHAR
|
||||||
#define IMGFMT_BG4B IMGFMT_BGR4_CHAR
|
#define IMGFMT_BG4B IMGFMT_BGR4_CHAR
|
||||||
|
|
||||||
#define IMGFMT_IS_RGB(fmt) (((fmt)&IMGFMT_RGB_MASK)==IMGFMT_RGB)
|
|
||||||
#define IMGFMT_IS_BGR(fmt) (((fmt)&IMGFMT_BGR_MASK)==IMGFMT_BGR)
|
|
||||||
|
|
||||||
#define IMGFMT_RGB_DEPTH(fmt) ((fmt)&0x3F)
|
|
||||||
#define IMGFMT_BGR_DEPTH(fmt) ((fmt)&0x3F)
|
|
||||||
|
|
||||||
// AV_PIX_FMT_BGR0
|
// AV_PIX_FMT_BGR0
|
||||||
#define IMGFMT_BGR0 0x1DC70000
|
#define IMGFMT_BGR0 0x1DC70000
|
||||||
|
|
||||||
|
static inline bool IMGFMT_IS_RGB(unsigned int fmt)
|
||||||
|
{
|
||||||
|
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
|
||||||
|
return !(desc.flags & MP_IMGFLAG_YUV) && !(desc.flags & MP_IMGFLAG_SWAPPED)
|
||||||
|
&& desc.num_planes == 1 && desc.id != IMGFMT_BGR0;
|
||||||
|
}
|
||||||
|
static inline bool IMGFMT_IS_BGR(unsigned int fmt)
|
||||||
|
{
|
||||||
|
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
|
||||||
|
return !(desc.flags & MP_IMGFLAG_YUV) && (desc.flags & MP_IMGFLAG_SWAPPED)
|
||||||
|
&& desc.num_planes == 1 && desc.id != IMGFMT_BGR0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IMGFMT_RGB_DEPTH(fmt) (mp_imgfmt_get_desc(fmt).plane_bits)
|
||||||
|
#define IMGFMT_BGR_DEPTH(fmt) (mp_imgfmt_get_desc(fmt).plane_bits)
|
||||||
|
|
||||||
// AV_PIX_FMT_GRAY16LE
|
// AV_PIX_FMT_GRAY16LE
|
||||||
#define IMGFMT_Y16LE 0x1DC70001
|
#define IMGFMT_Y16LE 0x1DC70001
|
||||||
// AV_PIX_FMT_GRAY16BE
|
// AV_PIX_FMT_GRAY16BE
|
||||||
|
@ -203,9 +255,20 @@
|
||||||
#define IMGFMT_IS_YUVP16_NE(fmt) IMGFMT_IS_YUVP16_LE(fmt)
|
#define IMGFMT_IS_YUVP16_NE(fmt) IMGFMT_IS_YUVP16_LE(fmt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// These macros are misnamed - they actually match 9 to 16 bits (inclusive)
|
// These functions are misnamed - they actually match 9 to 16 bits (inclusive)
|
||||||
#define IMGFMT_IS_YUVP16_LE(fmt) (((fmt - 0x51000034) & 0xf80000ff) == 0 || fmt == IMGFMT_Y16LE)
|
static inline bool IMGFMT_IS_YUVP16_LE(int fmt) {
|
||||||
#define IMGFMT_IS_YUVP16_BE(fmt) (((fmt - 0x34000051) & 0xff0000f8) == 0 || fmt == IMGFMT_Y16BE)
|
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
|
||||||
|
bool le_is_ne = BYTE_ORDER == LITTLE_ENDIAN;
|
||||||
|
return (desc.flags & MP_IMGFLAG_YUV_P) && desc.plane_bits > 8 &&
|
||||||
|
(le_is_ne == !!(desc.flags & MP_IMGFLAG_NE));
|
||||||
|
}
|
||||||
|
static inline bool IMGFMT_IS_YUVP16_BE(int fmt) {
|
||||||
|
struct mp_imgfmt_desc desc = mp_imgfmt_get_desc(fmt);
|
||||||
|
bool be_is_ne = BYTE_ORDER == BIG_ENDIAN;
|
||||||
|
return (desc.flags & MP_IMGFLAG_YUV_P) && desc.plane_bits > 8 &&
|
||||||
|
(be_is_ne == !!(desc.flags & MP_IMGFLAG_NE));
|
||||||
|
}
|
||||||
|
|
||||||
#define IMGFMT_IS_YUVP16(fmt) (IMGFMT_IS_YUVP16_LE(fmt) || IMGFMT_IS_YUVP16_BE(fmt))
|
#define IMGFMT_IS_YUVP16(fmt) (IMGFMT_IS_YUVP16_LE(fmt) || IMGFMT_IS_YUVP16_BE(fmt))
|
||||||
|
|
||||||
/* Packed YUV Formats */
|
/* Packed YUV Formats */
|
||||||
|
|
149
video/mp_image.c
149
video/mp_image.c
|
@ -23,16 +23,16 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <libavutil/mem.h>
|
||||||
|
#include <libavutil/common.h>
|
||||||
|
|
||||||
#include "talloc.h"
|
#include "talloc.h"
|
||||||
|
|
||||||
#include "video/img_format.h"
|
#include "video/img_format.h"
|
||||||
#include "video/mp_image.h"
|
#include "video/mp_image.h"
|
||||||
#include "video/sws_utils.h"
|
#include "video/sws_utils.h"
|
||||||
#include "video/filter/vf.h"
|
#include "video/filter/vf.h"
|
||||||
|
|
||||||
#include "video/memcpy_pic.h"
|
#include "video/memcpy_pic.h"
|
||||||
#include "libavutil/mem.h"
|
|
||||||
#include "libavutil/common.h"
|
|
||||||
|
|
||||||
struct m_refcount {
|
struct m_refcount {
|
||||||
void *arg;
|
void *arg;
|
||||||
|
@ -161,129 +161,18 @@ void mp_image_copy_attributes(struct mp_image *dmpi, struct mp_image *mpi)
|
||||||
vf_clone_mpi_attributes(dmpi, mpi);
|
vf_clone_mpi_attributes(dmpi, mpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt){
|
void mp_image_setfmt(struct mp_image *mpi, unsigned int out_fmt)
|
||||||
mpi->flags&=~(MP_IMGFLAG_PLANAR|MP_IMGFLAG_YUV|MP_IMGFLAG_SWAPPED);
|
{
|
||||||
mpi->imgfmt=out_fmt;
|
mpi->flags &= ~MP_IMGFLAG_FMT_MASK;
|
||||||
// compressed formats
|
struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(out_fmt);
|
||||||
if(IMGFMT_IS_HWACCEL(out_fmt)){
|
mpi->fmt = fmt;
|
||||||
mpi->bpp=0;
|
mpi->flags |= fmt.flags;
|
||||||
return;
|
mpi->imgfmt = fmt.id;
|
||||||
}
|
mpi->bpp = fmt.avg_bpp;
|
||||||
mpi->num_planes=1;
|
mpi->chroma_x_shift = fmt.chroma_xs;
|
||||||
if (IMGFMT_IS_RGB(out_fmt)) {
|
mpi->chroma_y_shift = fmt.chroma_ys;
|
||||||
if (IMGFMT_RGB_DEPTH(out_fmt) < 8 && !(out_fmt&128))
|
mpi->num_planes = fmt.num_planes;
|
||||||
mpi->bpp = IMGFMT_RGB_DEPTH(out_fmt);
|
mp_image_set_size(mpi, mpi->w, mpi->h);
|
||||||
else
|
|
||||||
mpi->bpp=(IMGFMT_RGB_DEPTH(out_fmt)+7)&(~7);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IMGFMT_IS_BGR(out_fmt)) {
|
|
||||||
if (IMGFMT_BGR_DEPTH(out_fmt) < 8 && !(out_fmt&128))
|
|
||||||
mpi->bpp = IMGFMT_BGR_DEPTH(out_fmt);
|
|
||||||
else
|
|
||||||
mpi->bpp=(IMGFMT_BGR_DEPTH(out_fmt)+7)&(~7);
|
|
||||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (out_fmt) {
|
|
||||||
case IMGFMT_BGR0:
|
|
||||||
mpi->bpp = 32;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mpi->num_planes=3;
|
|
||||||
if (out_fmt == IMGFMT_GBRP) {
|
|
||||||
mpi->bpp=24;
|
|
||||||
mpi->flags|=MP_IMGFLAG_PLANAR;
|
|
||||||
mpi->chroma_x_shift = 0;
|
|
||||||
mpi->chroma_y_shift = 0;
|
|
||||||
mpi->chroma_width=mpi->w;
|
|
||||||
mpi->chroma_height=mpi->h;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mpi->flags|=MP_IMGFLAG_YUV;
|
|
||||||
if (mp_get_chroma_shift(out_fmt, NULL, NULL, NULL)) {
|
|
||||||
mpi->flags|=MP_IMGFLAG_PLANAR;
|
|
||||||
mpi->bpp = mp_get_chroma_shift(out_fmt, &mpi->chroma_x_shift, &mpi->chroma_y_shift, NULL);
|
|
||||||
mpi->chroma_width = mpi->w >> mpi->chroma_x_shift;
|
|
||||||
mpi->chroma_height = mpi->h >> mpi->chroma_y_shift;
|
|
||||||
}
|
|
||||||
switch(out_fmt){
|
|
||||||
case IMGFMT_I420:
|
|
||||||
case IMGFMT_IYUV:
|
|
||||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
|
||||||
case IMGFMT_YV12:
|
|
||||||
return;
|
|
||||||
case IMGFMT_420A:
|
|
||||||
case IMGFMT_IF09:
|
|
||||||
mpi->num_planes=4;
|
|
||||||
case IMGFMT_YVU9:
|
|
||||||
case IMGFMT_444P:
|
|
||||||
case IMGFMT_422P:
|
|
||||||
case IMGFMT_411P:
|
|
||||||
case IMGFMT_440P:
|
|
||||||
case IMGFMT_444P16_LE:
|
|
||||||
case IMGFMT_444P16_BE:
|
|
||||||
case IMGFMT_444P14_LE:
|
|
||||||
case IMGFMT_444P14_BE:
|
|
||||||
case IMGFMT_444P12_LE:
|
|
||||||
case IMGFMT_444P12_BE:
|
|
||||||
case IMGFMT_444P10_LE:
|
|
||||||
case IMGFMT_444P10_BE:
|
|
||||||
case IMGFMT_444P9_LE:
|
|
||||||
case IMGFMT_444P9_BE:
|
|
||||||
case IMGFMT_422P16_LE:
|
|
||||||
case IMGFMT_422P16_BE:
|
|
||||||
case IMGFMT_422P14_LE:
|
|
||||||
case IMGFMT_422P14_BE:
|
|
||||||
case IMGFMT_422P12_LE:
|
|
||||||
case IMGFMT_422P12_BE:
|
|
||||||
case IMGFMT_422P10_LE:
|
|
||||||
case IMGFMT_422P10_BE:
|
|
||||||
case IMGFMT_422P9_LE:
|
|
||||||
case IMGFMT_422P9_BE:
|
|
||||||
case IMGFMT_420P16_LE:
|
|
||||||
case IMGFMT_420P16_BE:
|
|
||||||
case IMGFMT_420P14_LE:
|
|
||||||
case IMGFMT_420P14_BE:
|
|
||||||
case IMGFMT_420P12_LE:
|
|
||||||
case IMGFMT_420P12_BE:
|
|
||||||
case IMGFMT_420P10_LE:
|
|
||||||
case IMGFMT_420P10_BE:
|
|
||||||
case IMGFMT_420P9_LE:
|
|
||||||
case IMGFMT_420P9_BE:
|
|
||||||
return;
|
|
||||||
case IMGFMT_Y800:
|
|
||||||
case IMGFMT_Y8:
|
|
||||||
case IMGFMT_Y16LE:
|
|
||||||
case IMGFMT_Y16BE:
|
|
||||||
/* they're planar ones, but for easier handling use them as packed */
|
|
||||||
mpi->flags&=~MP_IMGFLAG_PLANAR;
|
|
||||||
mpi->num_planes=1;
|
|
||||||
return;
|
|
||||||
case IMGFMT_UYVY:
|
|
||||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
|
||||||
case IMGFMT_YUY2:
|
|
||||||
mpi->chroma_x_shift = 1;
|
|
||||||
mpi->chroma_y_shift = 1;
|
|
||||||
mpi->chroma_width=(mpi->w>>1);
|
|
||||||
mpi->chroma_height=(mpi->h>>1);
|
|
||||||
mpi->bpp=16;
|
|
||||||
mpi->num_planes=1;
|
|
||||||
return;
|
|
||||||
case IMGFMT_NV12:
|
|
||||||
mpi->flags|=MP_IMGFLAG_SWAPPED;
|
|
||||||
case IMGFMT_NV21:
|
|
||||||
mpi->flags|=MP_IMGFLAG_PLANAR;
|
|
||||||
mpi->bpp=12;
|
|
||||||
mpi->num_planes=2;
|
|
||||||
mpi->chroma_width=(mpi->w>>0);
|
|
||||||
mpi->chroma_height=(mpi->h>>1);
|
|
||||||
mpi->chroma_x_shift=0;
|
|
||||||
mpi->chroma_y_shift=1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mp_msg(MSGT_DECVIDEO,MSGL_WARN,"mp_image: unknown out_fmt: 0x%X\n",out_fmt);
|
|
||||||
mpi->bpp=0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mp_image_destructor(void *ptr)
|
static int mp_image_destructor(void *ptr)
|
||||||
|
@ -318,8 +207,12 @@ void mp_image_set_size(struct mp_image *mpi, int w, int h)
|
||||||
{
|
{
|
||||||
mpi->w = w;
|
mpi->w = w;
|
||||||
mpi->h = h;
|
mpi->h = h;
|
||||||
mpi->chroma_width = mpi->w >> mpi->chroma_x_shift;
|
for (int n = 0; n < mpi->num_planes; n++) {
|
||||||
mpi->chroma_height = mpi->h >> mpi->chroma_y_shift;
|
mpi->plane_w[n] = mpi->w >> mpi->fmt.xs[n];
|
||||||
|
mpi->plane_h[n] = mpi->h >> mpi->fmt.ys[n];
|
||||||
|
}
|
||||||
|
mpi->chroma_width = mpi->plane_w[1];
|
||||||
|
mpi->chroma_height = mpi->plane_h[1];
|
||||||
mpi->display_w = mpi->display_h = 0;
|
mpi->display_w = mpi->display_h = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,26 +26,14 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "core/mp_msg.h"
|
#include "core/mp_msg.h"
|
||||||
#include "csputils.h"
|
#include "csputils.h"
|
||||||
|
#include "video/img_format.h"
|
||||||
|
|
||||||
// Minimum stride alignment in pixels
|
// Minimum stride alignment in pixels
|
||||||
#define MP_STRIDE_ALIGNMENT 32
|
#define MP_STRIDE_ALIGNMENT 32
|
||||||
|
|
||||||
//--------- color info (filled by mp_image_setfmt() ) -----------
|
|
||||||
// set if number of planes > 1
|
|
||||||
#define MP_IMGFLAG_PLANAR 0x100
|
|
||||||
// set if it's YUV colorspace
|
|
||||||
#define MP_IMGFLAG_YUV 0x200
|
|
||||||
// set if it's swapped (BGR or YVU) plane/byteorder
|
|
||||||
#define MP_IMGFLAG_SWAPPED 0x400
|
|
||||||
// set if you want memory for palette allocated and managed by vf_get_image etc.
|
|
||||||
#define MP_IMGFLAG_RGB_PALETTE 0x800
|
|
||||||
|
|
||||||
|
|
||||||
// set if buffer is allocated (used in destination images):
|
// set if buffer is allocated (used in destination images):
|
||||||
#define MP_IMGFLAG_ALLOCATED 0x4000
|
#define MP_IMGFLAG_ALLOCATED 0x4000
|
||||||
|
|
||||||
#define MP_MAX_PLANES 4
|
|
||||||
|
|
||||||
#define MP_IMGFIELD_ORDERED 0x01
|
#define MP_IMGFIELD_ORDERED 0x01
|
||||||
#define MP_IMGFIELD_TOP_FIRST 0x02
|
#define MP_IMGFIELD_TOP_FIRST 0x02
|
||||||
#define MP_IMGFIELD_REPEAT_FIRST 0x04
|
#define MP_IMGFIELD_REPEAT_FIRST 0x04
|
||||||
|
@ -71,23 +59,32 @@
|
||||||
*/
|
*/
|
||||||
typedef struct mp_image {
|
typedef struct mp_image {
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
struct mp_imgfmt_desc fmt;
|
||||||
|
|
||||||
|
// fields redundant to fmt, for convenience or compatibility
|
||||||
unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
|
unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
|
||||||
unsigned int imgfmt;
|
unsigned int imgfmt;
|
||||||
|
int num_planes;
|
||||||
|
int chroma_x_shift; // horizontal
|
||||||
|
int chroma_y_shift; // vertical
|
||||||
|
|
||||||
int w,h; // visible dimensions
|
int w,h; // visible dimensions
|
||||||
int display_w,display_h; // if set (!= 0), anamorphic size
|
int display_w,display_h; // if set (!= 0), anamorphic size
|
||||||
uint8_t *planes[MP_MAX_PLANES];
|
uint8_t *planes[MP_MAX_PLANES];
|
||||||
int stride[MP_MAX_PLANES];
|
int stride[MP_MAX_PLANES];
|
||||||
|
|
||||||
char * qscale;
|
char * qscale;
|
||||||
int qstride;
|
int qstride;
|
||||||
int pict_type; // 0->unknown, 1->I, 2->P, 3->B
|
int pict_type; // 0->unknown, 1->I, 2->P, 3->B
|
||||||
int fields;
|
int fields;
|
||||||
int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
|
int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
|
||||||
int num_planes;
|
|
||||||
/* these are only used by planar formats Y,U(Cb),V(Cr) */
|
/* redundant */
|
||||||
int chroma_width;
|
int chroma_width;
|
||||||
int chroma_height;
|
int chroma_height;
|
||||||
int chroma_x_shift; // horizontal
|
int plane_w[MP_MAX_PLANES];
|
||||||
int chroma_y_shift; // vertical
|
int plane_h[MP_MAX_PLANES];
|
||||||
|
|
||||||
enum mp_csp colorspace;
|
enum mp_csp colorspace;
|
||||||
enum mp_csp_levels levels;
|
enum mp_csp_levels levels;
|
||||||
/* only inside filter chain */
|
/* only inside filter chain */
|
||||||
|
|
Loading…
Reference in New Issue