Merge "Y4M input support for 4:2:2, 4:4:4, 4:4:4:4" into experimental

This commit is contained in:
John Koleszar 2013-05-06 22:20:00 -07:00 committed by Gerrit Code Review
commit f46fb71eb6
5 changed files with 96 additions and 40 deletions

1
configure vendored
View File

@ -250,6 +250,7 @@ EXPERIMENT_LIST="
multiple_arf multiple_arf
code_zerogroup code_zerogroup
sb8x8 sb8x8
non420
" "
CONFIG_LIST=" CONFIG_LIST="
external_build external_build

View File

@ -55,9 +55,11 @@ extern "C" {
VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */ VPX_IMG_FMT_YV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 1, /**< planar YVU */
VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2, VPX_IMG_FMT_I420 = VPX_IMG_FMT_PLANAR | 2,
VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */ VPX_IMG_FMT_VPXYV12 = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_UV_FLIP | 3, /** < planar 4:2:0 format with vpx color space */
VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4 /** < planar 4:2:0 format with vpx color space */ VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4,
} VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5,
vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */ VPX_IMG_FMT_I444 = VPX_IMG_FMT_PLANAR | 6,
VPX_IMG_FMT_444A = VPX_IMG_FMT_PLANAR | VPX_IMG_FMT_HAS_ALPHA | 7
} vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
#if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT #if !defined(VPX_CODEC_DISABLE_COMPAT) || !VPX_CODEC_DISABLE_COMPAT
#define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR /**< \deprecated Use #VPX_IMG_FMT_PLANAR */ #define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR /**< \deprecated Use #VPX_IMG_FMT_PLANAR */

View File

@ -326,6 +326,7 @@ struct input_state {
unsigned int h; unsigned int h;
struct vpx_rational framerate; struct vpx_rational framerate;
int use_i420; int use_i420;
int only_i420;
}; };
@ -1793,7 +1794,8 @@ void open_input_file(struct input_state *input) {
if (input->detect.buf_read == 4 if (input->detect.buf_read == 4
&& file_is_y4m(input->file, &input->y4m, input->detect.buf)) { && file_is_y4m(input->file, &input->y4m, input->detect.buf)) {
if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4) >= 0) { if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
input->only_i420) >= 0) {
input->file_type = FILE_TYPE_Y4M; input->file_type = FILE_TYPE_Y4M;
input->w = input->y4m.pic_w; input->w = input->y4m.pic_w;
input->h = input->y4m.pic_h; input->h = input->y4m.pic_h;
@ -2517,6 +2519,7 @@ int main(int argc, const char **argv_) {
input.framerate.num = 30; input.framerate.num = 30;
input.framerate.den = 1; input.framerate.den = 1;
input.use_i420 = 1; input.use_i420 = 1;
input.only_i420 = 1;
/* First parse the global configuration values, because we want to apply /* First parse the global configuration values, because we want to apply
* other parameters on top of the default configuration provided by the * other parameters on top of the default configuration provided by the
@ -2551,6 +2554,12 @@ int main(int argc, const char **argv_) {
if (!input.fn) if (!input.fn)
usage_exit(); usage_exit();
#if CONFIG_NON420
/* Decide if other chroma subsamplings than 4:2:0 are supported */
if (global.codec->fourcc == VP9_FOURCC)
input.only_i420 = 0;
#endif
for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) { for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
int frames_in = 0, seen_frames = 0; int frames_in = 0, seen_frames = 0;
int64_t estimated_time_left = -1; int64_t estimated_time_left = -1;

View File

@ -659,7 +659,8 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
unsigned char *_aux) { unsigned char *_aux) {
} }
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip) { int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
int only_420) {
char buffer[80]; char buffer[80];
int ret; int ret;
int i; int i;
@ -701,6 +702,8 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip) {
"Only progressive scan handled.\n"); "Only progressive scan handled.\n");
return -1; return -1;
} }
_y4m->vpx_fmt = VPX_IMG_FMT_I420;
_y4m->vpx_bps = 12;
if (strcmp(_y4m->chroma_type, "420") == 0 || if (strcmp(_y4m->chroma_type, "420") == 0 ||
strcmp(_y4m->chroma_type, "420jpeg") == 0) { strcmp(_y4m->chroma_type, "420jpeg") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = _y4m->dst_c_dec_v = 2; _y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v = _y4m->dst_c_dec_v = 2;
@ -734,16 +737,30 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip) {
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; _y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_422jpeg_420jpeg; _y4m->convert = y4m_convert_422jpeg_420jpeg;
} else if (strcmp(_y4m->chroma_type, "422") == 0) { } else if (strcmp(_y4m->chroma_type, "422") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = 2; _y4m->src_c_dec_h = 2;
_y4m->src_c_dec_v = 1; _y4m->src_c_dec_v = 1;
_y4m->dst_c_dec_v = 2; if (only_420) {
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_c_dec_h = 2;
/*Chroma filter required: read into the aux buf first. _y4m->dst_c_dec_v = 2;
We need to make two filter passes, so we need some extra space in the _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
aux buffer.*/ /*Chroma filter required: read into the aux buf first.
_y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; We need to make two filter passes, so we need some extra space in the
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; aux buffer.*/
_y4m->convert = y4m_convert_422_420jpeg; _y4m->aux_buf_read_sz = 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz +
((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_422_420jpeg;
} else {
_y4m->vpx_fmt = VPX_IMG_FMT_I422;
_y4m->vpx_bps = 16;
_y4m->dst_c_dec_h = _y4m->src_c_dec_h;
_y4m->dst_c_dec_v = _y4m->src_c_dec_v;
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h
+ 2 * ((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
/*Natively supported: no conversion required.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null;
}
} else if (strcmp(_y4m->chroma_type, "411") == 0) { } else if (strcmp(_y4m->chroma_type, "411") == 0) {
_y4m->src_c_dec_h = 4; _y4m->src_c_dec_h = 4;
_y4m->dst_c_dec_h = 2; _y4m->dst_c_dec_h = 2;
@ -758,29 +775,52 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip) {
_y4m->convert = y4m_convert_411_420jpeg; _y4m->convert = y4m_convert_411_420jpeg;
} else if (strcmp(_y4m->chroma_type, "444") == 0) { } else if (strcmp(_y4m->chroma_type, "444") == 0) {
_y4m->src_c_dec_h = 1; _y4m->src_c_dec_h = 1;
_y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 1; _y4m->src_c_dec_v = 1;
_y4m->dst_c_dec_v = 2; if (only_420) {
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_c_dec_h = 2;
/*Chroma filter required: read into the aux buf first. _y4m->dst_c_dec_v = 2;
We need to make two filter passes, so we need some extra space in the _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
aux buffer.*/ /*Chroma filter required: read into the aux buf first.
_y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h; We need to make two filter passes, so we need some extra space in the
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz + ((_y4m->pic_w + 1) / 2) * _y4m->pic_h; aux buffer.*/
_y4m->convert = y4m_convert_444_420jpeg; _y4m->aux_buf_read_sz = 2 * _y4m->pic_w * _y4m->pic_h;
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz +
((_y4m->pic_w + 1) / 2) * _y4m->pic_h;
_y4m->convert = y4m_convert_444_420jpeg;
} else {
_y4m->vpx_fmt = VPX_IMG_FMT_I444;
_y4m->vpx_bps = 24;
_y4m->dst_c_dec_h = _y4m->src_c_dec_h;
_y4m->dst_c_dec_v = _y4m->src_c_dec_v;
_y4m->dst_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
/*Natively supported: no conversion required.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null;
}
} else if (strcmp(_y4m->chroma_type, "444alpha") == 0) { } else if (strcmp(_y4m->chroma_type, "444alpha") == 0) {
_y4m->src_c_dec_h = 1; _y4m->src_c_dec_h = 1;
_y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 1; _y4m->src_c_dec_v = 1;
_y4m->dst_c_dec_v = 2; if (only_420) {
_y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h; _y4m->dst_c_dec_h = 2;
/*Chroma filter required: read into the aux buf first. _y4m->dst_c_dec_v = 2;
We need to make two filter passes, so we need some extra space in the _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
aux buffer. /*Chroma filter required: read into the aux buf first.
The extra plane also gets read into the aux buf. We need to make two filter passes, so we need some extra space in the
It will be discarded.*/ aux buffer.
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h; The extra plane also gets read into the aux buf.
_y4m->convert = y4m_convert_444_420jpeg; It will be discarded.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 3 * _y4m->pic_w * _y4m->pic_h;
_y4m->convert = y4m_convert_444_420jpeg;
} else {
_y4m->vpx_fmt = VPX_IMG_FMT_444A;
_y4m->vpx_bps = 32;
_y4m->dst_c_dec_h = _y4m->src_c_dec_h;
_y4m->dst_c_dec_v = _y4m->src_c_dec_v;
_y4m->dst_buf_read_sz = 4 * _y4m->pic_w * _y4m->pic_h;
/*Natively supported: no conversion required.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null;
}
} else if (strcmp(_y4m->chroma_type, "mono") == 0) { } else if (strcmp(_y4m->chroma_type, "mono") == 0) {
_y4m->src_c_dec_h = _y4m->src_c_dec_v = 0; _y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
_y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2; _y4m->dst_c_dec_h = _y4m->dst_c_dec_v = 2;
@ -847,22 +887,23 @@ int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *_img) {
sizes, which would require a separate fread call for every row.*/ sizes, which would require a separate fread call for every row.*/
memset(_img, 0, sizeof(*_img)); memset(_img, 0, sizeof(*_img));
/*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/ /*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/
_img->fmt = IMG_FMT_I420; _img->fmt = _y4m->vpx_fmt;
_img->w = _img->d_w = _y4m->pic_w; _img->w = _img->d_w = _y4m->pic_w;
_img->h = _img->d_h = _y4m->pic_h; _img->h = _img->d_h = _y4m->pic_h;
/*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/ _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
_img->x_chroma_shift = 1; _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
_img->y_chroma_shift = 1; _img->bps = _y4m->vpx_bps;
_img->bps = 12;
/*Set up the buffer pointers.*/ /*Set up the buffer pointers.*/
pic_sz = _y4m->pic_w * _y4m->pic_h; pic_sz = _y4m->pic_w * _y4m->pic_h;
c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h; c_w = (_y4m->pic_w + _y4m->dst_c_dec_h - 1) / _y4m->dst_c_dec_h;
c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v; c_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
c_sz = c_w * c_h; c_sz = c_w * c_h;
_img->stride[PLANE_Y] = _y4m->pic_w; _img->stride[PLANE_Y] = _img->stride[PLANE_ALPHA] = _y4m->pic_w;
_img->stride[PLANE_U] = _img->stride[PLANE_V] = c_w; _img->stride[PLANE_U] = _img->stride[PLANE_V] = c_w;
_img->planes[PLANE_Y] = _y4m->dst_buf; _img->planes[PLANE_Y] = _y4m->dst_buf;
_img->planes[PLANE_U] = _y4m->dst_buf + pic_sz; _img->planes[PLANE_U] = _y4m->dst_buf + pic_sz;
_img->planes[PLANE_V] = _y4m->dst_buf + pic_sz + c_sz; _img->planes[PLANE_V] = _y4m->dst_buf + pic_sz + c_sz;
_img->planes[PLANE_ALPHA] = _y4m->dst_buf + pic_sz + 2 * c_sz;
return 1; return 1;
} }

View File

@ -51,9 +51,12 @@ struct y4m_input {
y4m_convert_func convert; y4m_convert_func convert;
unsigned char *dst_buf; unsigned char *dst_buf;
unsigned char *aux_buf; unsigned char *aux_buf;
enum vpx_img_fmt vpx_fmt;
int vpx_bps;
}; };
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip); int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
int only_420);
void y4m_input_close(y4m_input *_y4m); void y4m_input_close(y4m_input *_y4m);
int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img); int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img);