summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Koleszar <jkoleszar@google.com>2013-05-06 11:01:35 -0700
committerJohn Koleszar <jkoleszar@google.com>2013-05-06 14:35:19 -0700
commit8dd8287e16d3afc037a4ad5a18863107868ff5ef (patch)
tree8c232ba8ad467197cffae4e6b00d0adaae6f7c8f
parentf7fa367094250ecaad8b6463ab877ca6e59ce62d (diff)
downloadlibvpx-8dd8287e16d3afc037a4ad5a18863107868ff5ef.tar
libvpx-8dd8287e16d3afc037a4ad5a18863107868ff5ef.tar.gz
libvpx-8dd8287e16d3afc037a4ad5a18863107868ff5ef.tar.bz2
libvpx-8dd8287e16d3afc037a4ad5a18863107868ff5ef.zip
Y4M input support for 4:2:2, 4:4:4, 4:4:4:4
Adds a new experiment CONFIG_NON420 that allows other chroma subsamplings to be passed to the codec. This commit allows the data to be passed from a y4m input file through vpxenc to the codec, where they're currently rejected. Later commits will finish support for this inside the codec. Change-Id: Ib3aac604d8cad9e24cef395fa1067f16ba7e8e43
-rwxr-xr-xconfigure1
-rw-r--r--vpx/vpx_image.h8
-rw-r--r--vpxenc.c11
-rw-r--r--y4minput.c111
-rw-r--r--y4minput.h5
5 files changed, 96 insertions, 40 deletions
diff --git a/configure b/configure
index 6e60af176..573ec36a9 100755
--- a/configure
+++ b/configure
@@ -250,6 +250,7 @@ EXPERIMENT_LIST="
multiple_arf
code_zerogroup
sb8x8
+ non420
"
CONFIG_LIST="
external_build
diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h
index 809fa38d0..c304bacd0 100644
--- a/vpx/vpx_image.h
+++ b/vpx/vpx_image.h
@@ -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_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_VPXI420 = VPX_IMG_FMT_PLANAR | 4 /** < planar 4:2:0 format with vpx color space */
- }
- vpx_img_fmt_t; /**< alias for enum vpx_img_fmt */
+ VPX_IMG_FMT_VPXI420 = VPX_IMG_FMT_PLANAR | 4,
+ VPX_IMG_FMT_I422 = VPX_IMG_FMT_PLANAR | 5,
+ 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
#define IMG_FMT_PLANAR VPX_IMG_FMT_PLANAR /**< \deprecated Use #VPX_IMG_FMT_PLANAR */
diff --git a/vpxenc.c b/vpxenc.c
index 95c6cf2b1..33a56a43b 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -326,6 +326,7 @@ struct input_state {
unsigned int h;
struct vpx_rational framerate;
int use_i420;
+ int only_i420;
};
@@ -1793,7 +1794,8 @@ void open_input_file(struct input_state *input) {
if (input->detect.buf_read == 4
&& 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->w = input->y4m.pic_w;
input->h = input->y4m.pic_h;
@@ -2517,6 +2519,7 @@ int main(int argc, const char **argv_) {
input.framerate.num = 30;
input.framerate.den = 1;
input.use_i420 = 1;
+ input.only_i420 = 1;
/* First parse the global configuration values, because we want to apply
* 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)
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++) {
int frames_in = 0, seen_frames = 0;
int64_t estimated_time_left = -1;
diff --git a/y4minput.c b/y4minput.c
index 24f0c154f..47f005a95 100644
--- a/y4minput.c
+++ b/y4minput.c
@@ -659,7 +659,8 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst,
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];
int ret;
int i;
@@ -701,6 +702,8 @@ int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip) {
"Only progressive scan handled.\n");
return -1;
}
+ _y4m->vpx_fmt = VPX_IMG_FMT_I420;
+ _y4m->vpx_bps = 12;
if (strcmp(_y4m->chroma_type, "420") == 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;
@@ -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->convert = y4m_convert_422jpeg_420jpeg;
} 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->dst_c_dec_v = 2;
- _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
- /*Chroma filter required: read into the aux buf first.
- We need to make two filter passes, so we need some extra space in the
- aux buffer.*/
- _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;
+ if (only_420) {
+ _y4m->dst_c_dec_h = 2;
+ _y4m->dst_c_dec_v = 2;
+ _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
+ /*Chroma filter required: read into the aux buf first.
+ We need to make two filter passes, so we need some extra space in the
+ aux buffer.*/
+ _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) {
_y4m->src_c_dec_h = 4;
_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;
} else if (strcmp(_y4m->chroma_type, "444") == 0) {
_y4m->src_c_dec_h = 1;
- _y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 1;
- _y4m->dst_c_dec_v = 2;
- _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
- /*Chroma filter required: read into the aux buf first.
- We need to make two filter passes, so we need some extra space in the
- aux buffer.*/
- _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;
+ if (only_420) {
+ _y4m->dst_c_dec_h = 2;
+ _y4m->dst_c_dec_v = 2;
+ _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
+ /*Chroma filter required: read into the aux buf first.
+ We need to make two filter passes, so we need some extra space in the
+ aux buffer.*/
+ _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) {
_y4m->src_c_dec_h = 1;
- _y4m->dst_c_dec_h = 2;
_y4m->src_c_dec_v = 1;
- _y4m->dst_c_dec_v = 2;
- _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
- /*Chroma filter required: read into the aux buf first.
- We need to make two filter passes, so we need some extra space in the
- aux buffer.
- The extra plane also gets read into the aux buf.
- 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;
+ if (only_420) {
+ _y4m->dst_c_dec_h = 2;
+ _y4m->dst_c_dec_v = 2;
+ _y4m->dst_buf_read_sz = _y4m->pic_w * _y4m->pic_h;
+ /*Chroma filter required: read into the aux buf first.
+ We need to make two filter passes, so we need some extra space in the
+ aux buffer.
+ The extra plane also gets read into the aux buf.
+ 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) {
_y4m->src_c_dec_h = _y4m->src_c_dec_v = 0;
_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.*/
memset(_img, 0, sizeof(*_img));
/*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->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 = 1;
- _img->y_chroma_shift = 1;
- _img->bps = 12;
+ _img->x_chroma_shift = _y4m->dst_c_dec_h >> 1;
+ _img->y_chroma_shift = _y4m->dst_c_dec_v >> 1;
+ _img->bps = _y4m->vpx_bps;
+
/*Set up the buffer pointers.*/
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_h = (_y4m->pic_h + _y4m->dst_c_dec_v - 1) / _y4m->dst_c_dec_v;
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->planes[PLANE_Y] = _y4m->dst_buf;
_img->planes[PLANE_U] = _y4m->dst_buf + pic_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;
}
diff --git a/y4minput.h b/y4minput.h
index 2fa3767c9..b2a390cfe 100644
--- a/y4minput.h
+++ b/y4minput.h
@@ -51,9 +51,12 @@ struct y4m_input {
y4m_convert_func convert;
unsigned char *dst_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);
int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, vpx_image_t *img);