aomenc: respect chroma-sample-position for Y4M
BUG=aomedia:2096
Change-Id: I838eb98b6183563fcdf69db9d9b3c95874d5748d
diff --git a/apps/aomenc.c b/apps/aomenc.c
index a9c6f78..06fb480 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -845,14 +845,17 @@
if (!rat->den) die("Error: %s has zero denominator\n", msg);
}
-static void parse_global_config(struct AvxEncoderConfig *global, int *argc,
+/* Parses global config arguments into the AvxEncoderConfig. Note that
+ * argv is modified and overwrites all parsed arguments.
+ */
+static void parse_global_config(struct AvxEncoderConfig *global, int argc,
char ***argv) {
char **argi, **argj;
struct arg arg;
const int num_encoder = get_aom_encoder_count();
char **argv_local = (char **)*argv;
#if CONFIG_FILEOPTIONS
- int argc_local = *argc;
+ int argc_local = argc;
#endif
if (num_encoder < 1) die("Error: no valid encoder available\n");
@@ -861,6 +864,7 @@
global->codec = get_aom_encoder_by_index(num_encoder - 1);
global->passes = 0;
global->color_type = I420;
+ global->csp = AOM_CSP_UNKNOWN;
#if CONFIG_FILEOPTIONS
const char *cfg = NULL;
@@ -900,6 +904,10 @@
if (global->pass < 1 || global->pass > 2)
die("Error: Invalid pass selected (%d)\n", global->pass);
+ } else if (arg_match(&arg, &input_chroma_sample_position, argi)) {
+ global->csp = arg_parse_enum(&arg);
+ /* Flag is used by later code as well, preserve it. */
+ argj++;
} else if (arg_match(&arg, &usage, argi))
global->usage = arg_parse_uint(&arg);
else if (arg_match(&arg, &good_dl, argi))
@@ -963,7 +971,8 @@
}
}
-static void open_input_file(struct AvxInputContext *input) {
+static void open_input_file(struct AvxInputContext *input,
+ aom_chroma_sample_position_t csp) {
/* Parse certain options from the input file, if possible */
input->file = strcmp(input->filename, "-") ? fopen(input->filename, "rb")
: set_binary_mode(stdin);
@@ -989,7 +998,7 @@
input->detect.position = 0;
if (input->detect.buf_read == 4 && file_is_y4m(input->detect.buf)) {
- if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
+ if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4, csp,
input->only_i420) >= 0) {
input->file_type = FILE_TYPE_Y4M;
input->width = input->y4m.pic_w;
@@ -1914,7 +1923,7 @@
* codec.
*/
argv = argv_dup(argc - 1, argv_ + 1);
- parse_global_config(&global, &argc, &argv);
+ parse_global_config(&global, argc, &argv);
#if CONFIG_FILEOPTIONS
if (argc < 2) usage_exit();
@@ -1970,7 +1979,7 @@
int64_t average_rate = -1;
int64_t lagged_count = 0;
- open_input_file(&input);
+ open_input_file(&input, global.csp);
/* If the input file doesn't specify its w/h (raw files), try to get
* the data from the first stream's configuration.
diff --git a/apps/aomenc.h b/apps/aomenc.h
index 7c23df0..5e59c1a 100644
--- a/apps/aomenc.h
+++ b/apps/aomenc.h
@@ -53,6 +53,7 @@
int disable_warnings;
int disable_warning_prompt;
int experimental_bitstream;
+ aom_chroma_sample_position_t csp;
};
#ifdef __cplusplus
diff --git a/common/y4minput.c b/common/y4minput.c
index eca8b1b..20b2310 100644
--- a/common/y4minput.c
+++ b/common/y4minput.c
@@ -109,7 +109,8 @@
if (!got_par) _y4m->par_n = _y4m->par_d = 0;
/*Chroma-type is not specified in older files, e.g., those generated by
mplayer.*/
- if (!got_chroma) strcpy(_y4m->chroma_type, "420");
+ if (!got_chroma)
+ snprintf(_y4m->chroma_type, sizeof(_y4m->chroma_type), "420");
return 0;
}
@@ -778,7 +779,7 @@
}
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
- int only_420) {
+ aom_chroma_sample_position_t csp, int only_420) {
char buffer[80] = { 0 };
int ret;
int i;
@@ -831,6 +832,10 @@
_y4m->dst_buf_read_sz =
_y4m->pic_w * _y4m->pic_h +
2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
+ if (csp == AOM_CSP_VERTICAL) {
+ fprintf(stderr, "Unsupported conversion from 420jpeg to 420mpeg2\n");
+ return -1;
+ }
/* Natively supported: no conversion required. */
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz = 0;
_y4m->convert = y4m_convert_null;
@@ -877,7 +882,11 @@
/*Chroma filter required: read into the aux buf first.*/
_y4m->aux_buf_sz = _y4m->aux_buf_read_sz =
2 * ((_y4m->pic_w + 1) / 2) * ((_y4m->pic_h + 1) / 2);
- _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
+ _y4m->convert = y4m_convert_null;
+ if (csp != AOM_CSP_VERTICAL) {
+ _y4m->convert = y4m_convert_42xmpeg2_42xjpeg;
+ snprintf(_y4m->chroma_type, sizeof(_y4m->chroma_type), "420");
+ }
} else if (strcmp(_y4m->chroma_type, "420paldv") == 0) {
_y4m->src_c_dec_h = _y4m->dst_c_dec_h = _y4m->src_c_dec_v =
_y4m->dst_c_dec_v = 2;
diff --git a/common/y4minput.h b/common/y4minput.h
index 01b9ce9..f6c5a3d 100644
--- a/common/y4minput.h
+++ b/common/y4minput.h
@@ -57,8 +57,14 @@
unsigned int bit_depth;
};
+/**
+ * Open the input file, treating it as Y4M. y4m_input is filled in after
+ * reading it. Note that chroma-sample-position should only be set for 420
+ * input, and the input chroma is shifted if necessary. The code does not
+ * support the conversion from co-located to vertical.
+ */
int y4m_input_open(y4m_input *_y4m, FILE *_fin, char *_skip, int _nskip,
- int only_420);
+ aom_chroma_sample_position_t csp, int only_420);
void y4m_input_close(y4m_input *_y4m);
int y4m_input_fetch_frame(y4m_input *_y4m, FILE *_fin, aom_image_t *img);
diff --git a/test/y4m_video_source.h b/test/y4m_video_source.h
index 3dea901..42dee69 100644
--- a/test/y4m_video_source.h
+++ b/test/y4m_video_source.h
@@ -41,7 +41,8 @@
virtual void ReadSourceToStart() {
ASSERT_TRUE(input_file_ != NULL);
- ASSERT_FALSE(y4m_input_open(&y4m_, input_file_, NULL, 0, 0));
+ ASSERT_FALSE(
+ y4m_input_open(&y4m_, input_file_, NULL, 0, AOM_CSP_UNKNOWN, 0));
framerate_numerator_ = y4m_.fps_n;
framerate_denominator_ = y4m_.fps_d;
frame_ = 0;