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
This commit is contained in:
Родитель
f7fa367094
Коммит
8dd8287e16
|
@ -250,6 +250,7 @@ EXPERIMENT_LIST="
|
|||
multiple_arf
|
||||
code_zerogroup
|
||||
sb8x8
|
||||
non420
|
||||
"
|
||||
CONFIG_LIST="
|
||||
external_build
|
||||
|
|
|
@ -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 */
|
||||
|
|
11
vpxenc.c
11
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;
|
||||
|
|
111
y4minput.c
111
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче