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;