Add extraction of fields according to source scan type

This commit is contained in:
Ari Lemmetti 2015-08-18 19:11:08 +03:00
parent 581ff95412
commit 68fcc67a16
4 changed files with 74 additions and 13 deletions

View file

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

View file

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

View file

@ -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;
}

View file

@ -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_