📄 yuvscaler_resample.c
字号:
#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <math.h>#include <signal.h>#include "yuv4mpeg.h"#include "mjpeg_types.h"#include "yuvscaler.h"// From outide MAIN : global variablesextern unsigned int input_width;extern unsigned int output_width;// Downscaling ratiosextern unsigned int input_height_slice;extern unsigned int output_height_slice;extern unsigned int input_width_slice;extern unsigned int output_width_slice;extern int interlaced; extern unsigned int output_active_width;extern unsigned int output_active_height;extern int line_switching;extern unsigned int specific;extern unsigned int out_nb_col_slice, out_nb_line_slice;extern uint8_t *divide;// From inside MAIN function// *************************************************************************************intaverage_coeff (unsigned int input_length, unsigned int output_length, unsigned int *coeff){ // This function calculates multiplicative coeeficients to average an input (vector of) length // input_length into an output (vector of) length output_length; // We sequentially store the number-of-non-zero-coefficients, followed by the coefficients // themselvesc, and that, output_length time int last_coeff = 0, remaining_coeff, still_to_go = 0, in, out, non_zero = 0, nb; unsigned int *non_zero_p = NULL; unsigned int *pointer; if ((output_length > input_length) || (input_length == 0) || (output_length == 0) || (coeff == NULL)) { mjpeg_error ("Function average_coeff : arguments are wrong"); mjpeg_error ("input length = %d, output length = %d, input = %p", input_length, output_length, coeff); exit (1); }#ifdef DEBUG mjpeg_debug ("Function average_coeff : input length = %d, output length = %d, input = %p", input_length, output_length, coeff);#endif pointer = coeff; if (output_length == 1) { *pointer = input_length; pointer++; for (in = 0; in < input_length; in++) { *pointer = 1; pointer++; } } else { for (in = 0; in < output_length; in++) { non_zero = 0; non_zero_p = pointer; pointer++; still_to_go = input_length; if (last_coeff > 0) { remaining_coeff = output_length - last_coeff; *pointer = remaining_coeff; pointer++; non_zero++; still_to_go -= remaining_coeff; } nb = (still_to_go / output_length);#ifdef DEBUG mjpeg_debug ("in=%d,nb=%d,stgo=%d ol=%d", in, nb, still_to_go, output_length);#endif for (out = 0; out < nb; out++) { *pointer = output_length; pointer++; } still_to_go -= nb * output_length; non_zero += nb; if ((last_coeff = still_to_go) != 0) { *pointer = last_coeff;#ifdef DEBUG mjpeg_debug ("non_zero=%d,last_coeff=%d", non_zero, last_coeff);#endif pointer++; // now pointer points onto the next number-of-non_zero-coefficients non_zero++; *non_zero_p = non_zero; } else { if (in != output_length - 1) { mjpeg_error ("There is a common divider between %d and %d\n This should not be the case", input_length, output_length); exit (1); } } } *non_zero_p = non_zero; if (still_to_go != 0) { mjpeg_error ("Function average_coeff : calculus doesn't stop right : %d", still_to_go); } }#ifdef DEBUG if (verbose == 2) { int i, j; for (i = 0; i < output_length; i++) { mjpeg_debug ("line=%d", i); non_zero = *coeff; coeff++; mjpeg_debug (" "); for (j = 0; j < non_zero; j++) { fprintf (stderr, "%d : %d ", j, *coeff); coeff++; } fprintf (stderr, "\n"); } }#endif return (0);}// *************************************************************************************// *************************************************************************************intaverage (uint8_t * input, uint8_t * output, unsigned int *height_coeff, unsigned int *width_coeff, unsigned int half){ // This function average an input matrix of name input and of size local_input_width*(local_out_nb_line_slice*input_height_slice) // into an output matrix of name output and of size local_output_width*(local_out_nb_line_slice+output_height_slice) // input and output images are interleaved // if half==1 => we are dealing with an U or V component => height and width are / 2 => for speed sake, we use >>half unsigned int local_input_width = input_width >> half; unsigned int local_output_width = output_width >> half; unsigned int local_out_nb_col_slice = out_nb_col_slice >> half; unsigned int local_out_nb_line_slice = out_nb_line_slice >> half; uint8_t *input_line_p[input_height_slice]; uint8_t *output_line_p[output_height_slice]; unsigned int *H_var, *W_var, *H, *W; uint8_t *u_c_p; int j, nb_H, nb_W, in_line, first_line, out_line; int out_col_slice, out_col; int out_line_slice; int current_line, last_line; unsigned long int value = 0; //Init mjpeg_debug ("Start of average"); //End of INIT if (interlaced == Y4M_ILACE_NONE) { mjpeg_debug ("Non-interlaced downscaling"); // output frames are not interlaced => averaging will generate output lines is growing order, // output_height_slice lines per output_height_slice lines. // More important is the following question : // is input frames CONTENT interlaced or not (input frames are then said progressives). If content is interlaced (odd lines corresponds to time t // and even lines to another time t+dt with dt=1/(2*frame_rate)), then input frames should be DEINTERLACED prior to averaging // So, if input frames are interlaced, we will suppose they are progressives // TO BE PROGRAMMED, cf. FlaskMPEG for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + out_line_slice * input_height_slice * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += local_input_width; } u_c_p = output + out_line_slice * output_height_slice * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { H_var = H + 1; nb_W = *W; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) { W_var = W + 1; // we average nb_W columns of input : we increment input_line_p[current_line] and W_var each time, except for the last value where // input_line_p[current_line] and W_var do not need to be incremented, but H_var does for (j = 0; j < nb_W - 1; j++) value += (*H_var) * (*W_var++) * (*input_line_p[current_line]++); value += (*H_var++) * (*W_var) * (*input_line_p[current_line]); } // Straiforward implementation is // *(output_line_p[out_line]++)=value/diviseur; // round_off_error=value%diviseur; // Here, we speed up things but using the pretabulated nearest integral parts *(output_line_p[out_line]++) = divide[value]; W += nb_W + 1; } H += nb_H + 1; first_line += nb_H - 1; input_line_p[first_line] -= input_width_slice - 1; // If last line of input is to be reused in next loop, // make the pointer points at the correct place } input_line_p[first_line] += input_width_slice - 1; for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } else { // output frames are interlaced, line numbers gioes from 0 to n-1. // Therefore, downscaling is done between odd lines, then between even lines, but we do not mix odd and even lines. // So, we have to calculate the even and odd part of out_line_slice. // If the odd part is naturally out_line_slice % 2, the even part is (out_line_slice/2)*2. For speed reason, // the even part will be xritten as out_line_slice & ~(unsigned int) 1 mjpeg_debug ("Interlaced downscaling"); for (out_line_slice = 0; out_line_slice < local_out_nb_line_slice; out_line_slice++) { u_c_p = input + ((out_line_slice & ~(unsigned int) 1) * input_height_slice + out_line_slice % 2) * local_input_width; for (in_line = 0; in_line < input_height_slice; in_line++) { input_line_p[in_line] = u_c_p; u_c_p += 2 * local_input_width; } u_c_p = output + ((out_line_slice & ~(unsigned int) 1) * output_height_slice + out_line_slice % 2) * local_output_width; for (out_line = 0; out_line < output_height_slice; out_line++) { output_line_p[out_line] = u_c_p; u_c_p += 2 * local_output_width; } for (out_col_slice = 0; out_col_slice < local_out_nb_col_slice; out_col_slice++) { H = height_coeff; first_line = 0; for (out_line = 0; out_line < output_height_slice; out_line++) { nb_H = *H; W = width_coeff; for (out_col = 0; out_col < output_width_slice; out_col++) { H_var = H + 1; nb_W = *W; value = 0; last_line = first_line + nb_H; for (current_line = first_line; current_line < last_line; current_line++) { W_var = W + 1; // we average nb_W columns of input : we increment input_line_p[current_line] and W_var each time, except for the last value where // input_line_p[current_line] and W_var do not need to be incremented, but H_var does for (j = 0; j < nb_W - 1; j++) value += (*H_var) * (*W_var++) * (*input_line_p[current_line]++); value += (*H_var++) * (*W_var) * (*input_line_p[current_line]); } // Straiforward implementation is // *(output_line_p[out_line]++)=value/diviseur; // round_off_error=value%diviseur; // Here, we speed up things but using the pretabulated integral parts *(output_line_p[out_line]++) = divide[value]; W += nb_W + 1; } H += nb_H + 1; first_line += nb_H - 1; input_line_p[first_line] -= input_width_slice - 1; // If last line of input is to be reused in next loop, // make the pointer points at the correct place } input_line_p[first_line] += input_width_slice - 1; for (in_line = 0; in_line < input_height_slice; in_line++) input_line_p[in_line]++; } } } mjpeg_debug ("End of average"); return (0);}// *************************************************************************************// *************************************************************************************intaverage_specific (uint8_t * input, uint8_t * output, unsigned int *height_coeff, unsigned int *width_coeff, unsigned int half)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -