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