Move input reading functions to yuv_input module.

Adds function read_yuv_frame and moves functions fill_after_frame and
read_and_fill_frame_data from encoderstate to yuv_input.
This commit is contained in:
Arttu Ylä-Outinen 2015-06-05 11:15:18 +03:00
parent 4a7b86a43b
commit 970d0ec182
6 changed files with 175 additions and 99 deletions

View file

@ -150,6 +150,7 @@
<ClCompile Include="..\..\src\sao.c" />
<ClCompile Include="..\..\src\scalinglist.c" />
<ClCompile Include="..\..\src\search.c" />
<ClCompile Include="..\..\src\yuv_input.c" />
<ClInclude Include="..\..\src\checkpoint.h" />
<ClInclude Include="..\..\src\cli.h" />
<ClInclude Include="..\..\src\cu.h" />

View file

@ -195,6 +195,9 @@
<ClCompile Include="..\..\src\rate_control.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\yuv_input.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\global.h">

View file

@ -107,6 +107,7 @@ OBJS = \
encoder_state-geometry.o \
image.o \
videoframe.o \
yuv_input.o \
strategies/strategies-picture.o \
strategies/strategies-nal.o \
strategies/strategies-dct.o \

View file

@ -25,7 +25,6 @@
#include "encoderstate.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
@ -44,6 +43,7 @@
#include "sao.h"
#include "rdo.h"
#include "rate_control.h"
#include "yuv_input.h"
int encoder_state_match_children_of_previous_frame(encoder_state_t * const state) {
int i;
@ -860,45 +860,6 @@ void encode_one_frame(encoder_state_t * const state)
//threadqueue_flush(main_state->encoder_control->threadqueue);
}
static void fill_after_frame(unsigned height, unsigned array_width,
unsigned array_height, pixel_t *data)
{
pixel_t* p = data + height * array_width;
pixel_t* end = data + array_width * array_height;
while (p < end) {
// Fill the line by copying the line above.
memcpy(p, p - array_width, array_width);
p += array_width;
}
}
static int read_and_fill_frame_data(FILE *file,
unsigned width, unsigned height,
unsigned array_width, pixel_t *data)
{
pixel_t* p = data;
pixel_t* end = data + array_width * height;
pixel_t fill_char;
unsigned i;
while (p < end) {
// Read the beginning of the line from input.
if (width != fread(p, sizeof(unsigned char), width, file))
return 0;
// Fill the rest with the last pixel value.
fill_char = p[width - 1];
for (i = width; i < array_width; ++i) {
p[i] = fill_char;
}
p += array_width;
}
return 1;
}
int read_one_frame(FILE* file, const encoder_state_t * const state, image_t *img_out)
{
unsigned width = state->encoder_control->in.real_width;
@ -924,45 +885,27 @@ int read_one_frame(FILE* file, const encoder_state_t * const state, image_t *img
}
// If GOP is present but no pictures found
if (state->global->frame &&
if (state->global->frame &&
state->encoder_control->cfg->gop_len &&
!gop_pictures_available) {
int i;
unsigned y_size = width * height;
unsigned uv_size = (width >> 1) * (height >> 1);
for (i = 0; i < state->encoder_control->cfg->gop_len; i++, gop_pictures_available++) {
if (state->encoder_control->cfg->frames && state->global->frame + gop_pictures_available >= state->encoder_control->cfg->frames) {
for (int i = 0; i < state->encoder_control->cfg->gop_len; i++, gop_pictures_available++) {
if (state->encoder_control->cfg->frames
&& state->global->frame + gop_pictures_available >= state->encoder_control->cfg->frames) {
if (gop_pictures_available) {
gop_skip_frames = state->encoder_control->cfg->gop_len - gop_pictures_available;
break;
}
else return 0;
}
if (width != array_width) {
// In the case of frames not being aligned on 8 bit borders, bits need to be copied to fill them in.
if(!read_and_fill_frame_data(file, width, height, array_width, gop_pictures[i].source->y) ||
!read_and_fill_frame_data(file, width >> 1, height >> 1, array_width >> 1, gop_pictures[i].source->u) ||
!read_and_fill_frame_data(file, width >> 1, height >> 1, array_width >> 1, gop_pictures[i].source->v)) {
if (gop_pictures_available) { gop_skip_frames = state->encoder_control->cfg->gop_len - gop_pictures_available; break; }
else return 0;
}
} else {
// Otherwise the data can be read directly to the array.
if(y_size != fread(gop_pictures[i].source->y, sizeof(unsigned char), y_size, file) ||
uv_size != fread(gop_pictures[i].source->u, sizeof(unsigned char), uv_size, file) ||
uv_size != fread(gop_pictures[i].source->v, sizeof(unsigned char), uv_size, file)) {
if (gop_pictures_available) { gop_skip_frames = state->encoder_control->cfg->gop_len - gop_pictures_available; break; }
else return 0;
if (!read_yuv_frame(file, width, height, array_width, array_height, gop_pictures[i].source)) {
if (gop_pictures_available) {
gop_skip_frames = state->encoder_control->cfg->gop_len - gop_pictures_available;
break;
} else {
return 0;
}
}
if (height != array_height) {
fill_after_frame(height, array_width, array_height, gop_pictures[i].source->y);
fill_after_frame(height >> 1, array_width >> 1, array_height >> 1, gop_pictures[i].source->u);
fill_after_frame(height >> 1, array_width >> 1, array_height >> 1, gop_pictures[i].source->v);
}
}
}
}
// If GOP is present, fetch the data from our GOP picture buffer
@ -984,37 +927,9 @@ int read_one_frame(FILE* file, const encoder_state_t * const state, image_t *img
memcpy(img_out->v, gop_pictures[cur_gop].source->v, (width >> 1) * (height >> 1));
gop_pictures_available--;
} else {
if (width != array_width) {
// In the case of frames not being aligned on 8 bit borders, bits need to be copied to fill them in.
if (!read_and_fill_frame_data(file, width, height, array_width,
img_out->y) ||
!read_and_fill_frame_data(file, width >> 1, height >> 1, array_width >> 1,
img_out->u) ||
!read_and_fill_frame_data(file, width >> 1, height >> 1, array_width >> 1,
img_out->v))
return 0;
} else {
// Otherwise the data can be read directly to the array.
unsigned y_size = width * height;
unsigned uv_size = (width >> 1) * (height >> 1);
if (y_size != fread(img_out->y, sizeof(unsigned char),
y_size, file) ||
uv_size != fread(img_out->u, sizeof(unsigned char),
uv_size, file) ||
uv_size != fread(img_out->v, sizeof(unsigned char),
uv_size, file))
return 0;
}
if (height != array_height) {
fill_after_frame(height, array_width, array_height,
img_out->y);
fill_after_frame(height >> 1, array_width >> 1, array_height >> 1,
img_out->u);
fill_after_frame(height >> 1, array_width >> 1, array_height >> 1,
img_out->v);
}
return read_yuv_frame(file, width, height, array_width, array_height, img_out);
}
return 1;
}

120
src/yuv_input.c Normal file
View file

@ -0,0 +1,120 @@
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2015 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
/*
* \file
*/
#include <string.h>
#include <stdio.h>
#include "yuv_input.h"
static void fill_after_frame(unsigned height, unsigned array_width,
unsigned array_height, pixel_t *data)
{
pixel_t* p = data + height * array_width;
pixel_t* end = data + array_width * array_height;
while (p < end) {
// Fill the line by copying the line above.
memcpy(p, p - array_width, array_width);
p += array_width;
}
}
static int read_and_fill_frame_data(FILE *file,
unsigned width, unsigned height,
unsigned array_width, pixel_t *data)
{
pixel_t* p = data;
pixel_t* end = data + array_width * height;
pixel_t fill_char;
unsigned i;
while (p < end) {
// Read the beginning of the line from input.
if (width != fread(p, sizeof(unsigned char), width, file))
return 0;
// Fill the rest with the last pixel value.
fill_char = p[width - 1];
for (i = width; i < array_width; ++i) {
p[i] = fill_char;
}
p += array_width;
}
return 1;
}
/**
* \brief Read a single frame from a file.
*
* Read luma and chroma values from file. Extend pixels if the image buffer
* is larger than the input image.
*
* \param file input file
* \param input_width width of the input video in pixels
* \param input_height height of the input video in pixels
* \param array_width width of the image buffer in pixels
* \param array_height height of the image buffer in pixels
* \param img_out image buffer
*
* \return 1 on success, 0 on failure
*/
int read_yuv_frame(FILE* file,
unsigned input_width, unsigned input_height,
unsigned array_width, unsigned array_height,
image_t *img_out)
{
const unsigned y_size = input_width * input_height;
const unsigned uv_input_width = input_width / 2;
const unsigned uv_input_height = input_height / 2;
const unsigned uv_size = uv_input_width * uv_input_height;
const unsigned uv_array_width = array_width / 2;
const unsigned uv_array_height = array_height / 2;
if (input_width == array_width) {
// No need to extend pixels.
const size_t pixel_size = sizeof(unsigned char);
if (fread(img_out->y, pixel_size, y_size, file) != y_size) return 0;
if (fread(img_out->u, pixel_size, uv_size, file) != uv_size) return 0;
if (fread(img_out->v, pixel_size, uv_size, file) != uv_size) return 0;
} else {
// Need to copy pixels to fill the image in horizontal direction.
if (!read_and_fill_frame_data(file, input_width, input_height, array_width, img_out->y)) return 0;
if (!read_and_fill_frame_data(file, uv_input_width, uv_input_height, uv_array_width, img_out->u)) return 0;
if (!read_and_fill_frame_data(file, uv_input_width, uv_input_height, uv_array_width, img_out->v)) return 0;
}
if (input_height != array_height) {
// Need to copy pixels to fill the image in vertical direction.
fill_after_frame(input_height, array_width, array_height, img_out->y);
fill_after_frame(uv_input_height, uv_array_width, uv_array_height, img_out->u);
fill_after_frame(uv_input_height, uv_array_width, uv_array_height, img_out->v);
}
return 1;
}

36
src/yuv_input.h Normal file
View file

@ -0,0 +1,36 @@
/*****************************************************************************
* This file is part of Kvazaar HEVC encoder.
*
* Copyright (C) 2013-2015 Tampere University of Technology and others (see
* COPYING file).
*
* Kvazaar is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with Kvazaar. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef YUV_INPUT_H_
#define YUV_INPUT_H_
/*
* \file
* \brief Functions related to reading YUV input.
*/
#include "global.h"
int read_yuv_frame(FILE* file,
unsigned input_width, unsigned input_height,
unsigned array_width, unsigned array_height,
image_t *img_out);
#endif // YUV_INPUT_H_