From 68fcc67a169be357a6b820dd0f98fb20e753276c Mon Sep 17 00:00:00 2001 From: Ari Lemmetti Date: Tue, 18 Aug 2015 19:11:08 +0300 Subject: [PATCH] Add extraction of fields according to source scan type --- src/encmain.c | 39 +++++++++++++++++++++++++++------------ src/encoder.c | 5 ++++- src/yuv_io.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/yuv_io.h | 2 ++ 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/src/encmain.c b/src/encmain.c index 8c780e30..c4c3324f 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -169,27 +169,42 @@ int main(int argc, char *argv[]) uint32_t frames_done = 0; double psnr_sum[3] = { 0.0, 0.0, 0.0 }; + int8_t field_parity = 0; + kvz_picture *frame_in = NULL; + for (;;) { + kvz_picture *img_in = NULL; - if (!feof(input) && (opts->frames == 0 || frames_read < opts->frames)) { + + if (!feof(input) && (opts->frames == 0 || frames_read < opts->frames || field_parity == 1) ) { // Try to read an input frame. - img_in = api->picture_alloc(encoder->in.width, encoder->in.height); - if (!img_in) { + if(field_parity == 0) frame_in = api->picture_alloc(opts->config->width, opts->config->height); + if (!frame_in) { fprintf(stderr, "Failed to allocate image.\n"); goto exit_failure; } - if (yuv_io_read(input, opts->config->width, opts->config->height, img_in)) { - frames_read += 1; - } else { - // EOF or some error - api->picture_free(img_in); - img_in = NULL; - if (!feof(input)) { - fprintf(stderr, "Failed to read a frame %d\n", frames_read); - goto exit_failure; + if (field_parity == 0){ + if (yuv_io_read(input, opts->config->width, opts->config->height, frame_in)) { + frames_read += 1; + img_in = frame_in; + } else { + // EOF or some error + api->picture_free(img_in); + img_in = NULL; + if (!feof(input)) { + fprintf(stderr, "Failed to read a frame %d\n", frames_read); + goto exit_failure; + } } } + + if (encoder->cfg->source_scan_type != 0){ + img_in = api->picture_alloc(encoder->in.width, encoder->in.height); + yuv_io_extract_field(frame_in, encoder->cfg->source_scan_type, field_parity, img_in); + if (field_parity == 1) api->picture_free(frame_in); + field_parity ^= 1; //0->1 or 1->0 + } } kvz_data_chunk* chunks_out = NULL; diff --git a/src/encoder.c b/src/encoder.c index b01b300c..efe696c8 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -474,8 +474,11 @@ void encoder_control_free(encoder_control_t *const encoder) { } void encoder_control_input_init(encoder_control_t * const encoder, - const int32_t width, const int32_t height) + const int32_t width, int32_t height) { + // Halve for interlaced content + if (encoder->in.source_scan_type != 0) height /= 2; + encoder->in.width = width; encoder->in.height = height; encoder->in.real_width = width; diff --git a/src/yuv_io.c b/src/yuv_io.c index b375e2a3..efd62103 100644 --- a/src/yuv_io.c +++ b/src/yuv_io.c @@ -203,3 +203,44 @@ int yuv_io_write(FILE* file, return 1; } + +/** +* \brief Separate a single field from a frame. +* +* \param frame_in input frame to extract field from +* \param source_scan_type scan type of input material (0: progressive, 1:top field first, 2:bottom field first) +* \param field parity +* \param field_out +* +* \return 1 on success, 0 on failure +*/ +int yuv_io_extract_field(const kvz_picture *frame_in, unsigned source_scan_type, unsigned field_parity, kvz_picture *field_out) +{ + if ((source_scan_type != 1) && (source_scan_type != 2)) return 0; + if ((field_parity != 0) && (field_parity != 1)) return 0; + + unsigned offset = 0; + if (source_scan_type == 2) offset = frame_in->stride; + + //Luma + for (int i = 0; i < field_out->height; ++i){ + kvz_pixel *row_in = frame_in->y + CLIP(0, frame_in->height - 1, 2 * i) * frame_in->stride + offset; + kvz_pixel *row_out = field_out->y + i * field_out->stride + offset; + memcpy(row_out, row_in, sizeof(kvz_pixel) * frame_in->width); + } + + //Chroma + for (int i = 0; i < field_out->height / 2; ++i){ + kvz_pixel *row_in = frame_in->u + CLIP(0, frame_in->height / 2 - 1, 2 * i) * frame_in->stride / 2 + offset / 2; + kvz_pixel *row_out = field_out->u + i * field_out->stride / 2 + offset / 2; + memcpy(row_out, row_in, sizeof(kvz_pixel) * frame_in->width / 2); + } + + for (int i = 0; i < field_out->height / 2; ++i){ + kvz_pixel *row_in = frame_in->v + CLIP(0, frame_in->height / 2 - 1, 2 * i) * frame_in->stride / 2 + offset / 2; + kvz_pixel *row_out = field_out->v + i * field_out->stride / 2 + offset / 2; + memcpy(row_out, row_in, sizeof(kvz_pixel) * frame_in->width / 2); + } + + return 1; +} \ No newline at end of file diff --git a/src/yuv_io.h b/src/yuv_io.h index e953c3db..79b40e12 100644 --- a/src/yuv_io.h +++ b/src/yuv_io.h @@ -39,4 +39,6 @@ int yuv_io_write(FILE* file, const kvz_picture *img, unsigned output_width, unsigned output_height); +int yuv_io_extract_field(const kvz_picture *frame_in, unsigned source_scan_type, unsigned field_parity, kvz_picture *field_out); + #endif // YUV_IO_H_