uvg266/src/encmain.c

188 lines
6 KiB
C
Raw Normal View History

/**
* HEVC Encoder
* - Marko Viitanen ( fador at iki.fi ), Tampere University of Technology, Department of Computer Systems.
*/
/*! \file decmain.c
\brief main file for the Decoder
\author Marko Viitanen
\date 2012-05
This file contains main() function
*/
/*! \mainpage HEVC Encoder
*
* \section Coding style
*
* Coding style is explained in it's own document.
*
* \section usage_sec Usage
*
* \subsection encode_subsec Basic Decoding:
* Use encmain.exe -i input.yuv -o output.hevc
*
* \subsection options_subsec All program options:
* - -i <filename>: input
* - -o <filename>: output
* - -w <width>: frame width
* - -h <height>: frame height
* - -n <n>: encode only n frames
*/
/* Suppress some windows warnings */
#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
#include "config.h"
2012-06-01 12:31:06 +00:00
#include "encoder.h"
2012-06-04 10:47:12 +00:00
#include "cabac.h"
#include "picture.h"
#include "transform.h"
/*!
\brief Program main function.
\param argc Argument count from commandline
\param argv Argument list
\return Program exit state
*/
int main(int argc, char* argv[])
{
uint32_t curFrame = 0;
config *cfg = NULL; /* Global configuration */
FILE *input = NULL;
FILE *output = NULL;
double PSNR[3] = { 0.0, 0.0, 0.0 };
2013-03-11 14:26:09 +00:00
#ifdef _DEBUG
FILE *recout = fopen("encrec.yuv","wb");
2013-03-11 14:26:09 +00:00
#endif
2012-06-04 10:47:12 +00:00
encoder_control* encoder = (encoder_control*)malloc(sizeof(encoder_control));;
/* Handle configuration */
cfg = config_alloc();
/* If problem with configuration, shutdown */
if(!config_init(cfg) || !config_read(cfg,argc,argv))
{
fprintf(stderr, "/***********************************************/\r\n");
fprintf(stderr, " * HEVC Encoder v. " VERSION_STRING "*\r\n");
fprintf(stderr, " * Tampere University of Technology 2013 *\r\n");
fprintf(stderr, "/***********************************************/\r\n\r\n");
fprintf(stderr, "Usage:\r\n");
fprintf(stderr, "encmain -i <input> -w <width> -h <height> -o <output>\r\n");
fprintf(stderr, "Optional parameters:\r\n");
fprintf(stderr, " -n <frames> : number of frames to decode\r\n");
fprintf(stderr, " -s <frames> : number of frames to skip from the beginning\r\n");
config_destroy(cfg);
return EXIT_FAILURE;
}
2012-06-04 10:47:12 +00:00
2012-06-05 14:45:17 +00:00
printf("Input: %s, output: %s\n", cfg->input, cfg->output);
printf(" Video size: %dx%d\n", cfg->width, cfg->height);
/* Open input file and check that it was opened correctly */
input = fopen(cfg->input, "rb");
if(input == NULL)
{
2012-06-05 14:45:17 +00:00
fprintf(stderr, "Could not open input file, shutting down!\n");
config_destroy(cfg);
return EXIT_FAILURE;
}
/* Open output file and check that it was opened correctly */
output = fopen(cfg->output, "wb");
if(output == NULL)
{
2012-06-05 14:45:17 +00:00
fprintf(stderr, "Could not open output file, shutting down!\n");
config_destroy(cfg);
return EXIT_FAILURE;
}
2012-06-04 10:47:12 +00:00
/* Initialization */
init_tables();
init_exp_golomb(4096*8);
2012-06-04 10:47:12 +00:00
cabac_init(&cabac);
scalinglist_init();
init_encoder_control(encoder, (bitstream*)malloc(sizeof(bitstream)));
/* Init bitstream */
bitstream_init(encoder->stream);
encoder->stream->buffer_pos = 0;
2012-06-05 14:45:17 +00:00
encoder->stream->output = 0;
/* Alloc 1MB */
bitstream_alloc(encoder->stream, 1024*1024);
/* Config pointer to encoder struct */
encoder->cfg = cfg;
/* Set output file */
encoder->output = output;
/* Set CABAC output bitstream */
cabac.stream = encoder->stream;
/* input init (ToDo: read from commandline / config) */
2013-02-06 14:31:01 +00:00
encoder->bitdepth = 8;
encoder->frame = 0;
encoder->QP = 36;
encoder->in.video_format = FORMAT_420;
init_encoder_input(&encoder->in, input, cfg->width, cfg->height);
/* Start coding cycle */
while(!feof(input) && (!cfg->frames || encoder->frame < cfg->frames))
{
/* Read one frame from the input */
fread(encoder->in.cur_pic.yData, cfg->width*cfg->height,1,input);
fread(encoder->in.cur_pic.uData, cfg->width*cfg->height>>2,1,input);
fread(encoder->in.cur_pic.vData, cfg->width*cfg->height>>2,1,input);
/* Clear reconstruction buffers */
memset(encoder->in.cur_pic.yRecData, 0, cfg->width*cfg->height);
memset(encoder->in.cur_pic.uRecData, 128, cfg->width*cfg->height>>2);
memset(encoder->in.cur_pic.vRecData, 128, cfg->width*cfg->height>>2);
/* /////////////THE ACTUAL CODING HAPPENDS HERE\\\\\\\\\\\\\\\\\\\ */
encode_one_frame(encoder);
2013-03-11 14:26:09 +00:00
#ifdef _DEBUG
/* Write reconstructed frame out */
fwrite(encoder->in.cur_pic.yRecData,cfg->width*cfg->height,1,recout);
fwrite(encoder->in.cur_pic.uRecData,cfg->width*cfg->height>>2,1,recout);
fwrite(encoder->in.cur_pic.vRecData,cfg->width*cfg->height>>2,1,recout);
2013-03-11 14:26:09 +00:00
#endif
{
double temp_PSNR[3];
temp_PSNR[0] = imagePSNR(encoder->in.cur_pic.yData,encoder->in.cur_pic.yRecData,cfg->width,cfg->height);
temp_PSNR[1] = imagePSNR(encoder->in.cur_pic.uData,encoder->in.cur_pic.uRecData,cfg->width>>1,cfg->height>>1);
temp_PSNR[2] = imagePSNR(encoder->in.cur_pic.vData,encoder->in.cur_pic.vRecData,cfg->width>>1,cfg->height>>1);
printf("[%d] %c-frame PSNR: %2.2f %2.2f %2.2f\n", encoder->frame, "IPB"[encoder->in.cur_pic.type%3],
temp_PSNR[0],temp_PSNR[1],temp_PSNR[2]);
PSNR[0]+=temp_PSNR[0];
PSNR[1]+=temp_PSNR[1];
PSNR[2]+=temp_PSNR[2];
}
encoder->frame++;
}
/* Coding finished */
printf(" Processed %d frames, AVG PSNR: %2.2f %2.2f %2.2f\n", encoder->frame,PSNR[0]/encoder->frame,PSNR[1]/encoder->frame,PSNR[2]/encoder->frame);
2012-06-04 10:47:12 +00:00
fclose(input);
fclose(output);
2013-03-11 14:26:09 +00:00
#ifdef _DEBUG
fclose(recout);
2013-03-11 14:26:09 +00:00
#endif
/* Deallocating */
config_destroy(cfg);
scalinglist_destroy();
return EXIT_SUCCESS;
}