📄 yuvscaler.c
字号:
output_height = output_active_height > display_height ? output_active_height : display_height; if (interlaced == Y4M_ILACE_NONE) { if ((output_active_width % 2 !=0) || (output_active_height % 2 != 0) || (display_width % 2 != 0) || (display_height % 2 != 0)) mjpeg_error_exit1 ("Output sizes are not multiple of 2 !!! %ux%u, %ux%u being displayed", output_active_width, output_active_height, display_width, display_height); } else { if ((output_active_width % 2 != 0) || (output_active_height % 4 != 0) || (display_width % 2 != 0) || (display_height % 4 != 0)) mjpeg_error_exit1 ("Output sizes are not multiple of 2 on width and 4 on height (interlaced)! %ux%u, %ux%u being displayed", output_active_width, output_active_height, display_width, display_height); } // Skip and black initialisations // if (output_active_width > display_width) { skip = 1; skip_col = 1; // output_skip_col_right and output_skip_col_left must be even numbers output_skip_col_right = ((output_active_width - display_width) / 4)*2; output_skip_col_left = output_active_width - display_width - output_skip_col_right; } if (output_active_width < display_width) { black = 1; black_col = 1; // output_black_col_right and output_black_col_left must be even numbers output_black_col_right = ((display_width - output_active_width) / 4)*2; output_black_col_left = display_width - output_active_width - output_black_col_right; } if (output_active_height > display_height) { skip = 1; skip_line = 1; // output_skip_line_above and output_skip_line_under must be even numbers output_skip_line_above = ((output_active_height - display_height) / 4)*2; output_skip_line_under = output_active_height - display_height - output_skip_line_above; } if (output_active_height < display_height) { black = 1; black_line = 1; // output_black_line_above and output_black_line_under must be even numbers output_black_line_above = ((display_height - output_active_height) / 4)*2; output_black_line_under = display_height - output_active_height - output_black_line_above; }}// *************************************************************************************// MAIN// *************************************************************************************intmain (int argc, char *argv[]){ int input_fd = 0; int output_fd = 1;// DDD and time use// int input_fd = open("./yuvscaler.input",O_RDONLY);// int output_fd = open("./yuvscaler.output",O_WRONLY);// DDD use int err = Y4M_OK, nb; unsigned long int i, j, h, w; long int frame_num = 0; unsigned int *height_coeff = NULL, *width_coeff = NULL; uint8_t *input = NULL, *output = NULL, *padded_input = NULL, *padded_bottom = NULL, *padded_top = NULL; uint8_t *input_y, *input_u, *input_v; uint8_t *output_y, *output_u, *output_v; uint8_t *frame_y, *frame_u, *frame_v; uint8_t **frame_y_p = NULL, **frame_u_p = NULL, **frame_v_p = NULL; // size is not yet known => pointer of pointer uint8_t *u_c_p; //u_c_p = uint8_t pointer unsigned int divider; // SPECIFIC TO BICUBIC unsigned int *in_line = NULL, *in_col = NULL, out_line, out_col; unsigned long int somme; float *a = NULL, *b = NULL; int16_t *cspline_w=NULL,*cspline_h=NULL; uint16_t width_offset=0,height_offset=0,left_offset=0,top_offset=0,right_offset=0,bottom_offset=0; uint16_t height_pad=0,width_pad=0,width_neighbors=0,height_neighbors=0; // On constate que souvent, le dernier coeff cspline est nul => // pas la peine de le prendre en compte dans les calculs // Attention ! optimisation vitesse yuvscaler_bicubic.c suppose que zero_width_neighbors=0 ou 1 seulement uint8_t zero_width_neighbors=1,zero_height_neighbors=1; float width_scale,height_scale; int16_t cspline_value = 0; int16_t *pointer; // SPECIFIC TO YUV4MPEG unsigned long int nb_pixels; y4m_frame_info_t frameinfo; y4m_stream_info_t in_streaminfo; y4m_stream_info_t out_streaminfo; y4m_ratio_t frame_rate = y4m_fps_UNKNOWN; // Information output mjpeg_info ("yuvscaler "LAVPLAY_VERSION" ("yuvscaler_VERSION") is a general scaling utility for yuv frames"); mjpeg_info ("(C) 2001-2004 Xavier Biquard <xbiquard@free.fr>, yuvscaler -h for help, or man yuvscaler"); // Initialisation of global variables that are independent of the input stream, input_file in particular handle_args_global (argc, argv); // mjpeg tools global initialisations mjpeg_default_handler_verbosity (verbose); y4m_init_stream_info (&in_streaminfo); y4m_init_stream_info (&out_streaminfo); y4m_init_frame_info (&frameinfo); // *************************************************************** // Get video stream informations (size, framerate, interlacing, sample aspect ratio). // The in_streaminfo structure is filled in accordingly // *************************************************************** if (y4m_read_stream_header (input_fd, &in_streaminfo) != Y4M_OK) mjpeg_error_exit1 ("Could'nt read YUV4MPEG header!"); input_width = y4m_si_get_width (&in_streaminfo); input_height = y4m_si_get_height (&in_streaminfo); frame_rate = y4m_si_get_framerate (&in_streaminfo); interlaced = y4m_si_get_interlace (&in_streaminfo); // *************************************************************** // INITIALISATIONS // Norm determination from header (this has precedence over user's specification through the -n flag) if (Y4M_RATIO_EQL (frame_rate, y4m_fps_PAL)) norm = 0; if (Y4M_RATIO_EQL (frame_rate, y4m_fps_NTSC)) norm = 1; if (norm < 0) { mjpeg_warn ("Could not infer norm (PAL/SECAM or NTSC) from input data (frame size=%dx%d, frame rate=%d:%d fps)!!", input_width, input_height, frame_rate.n, frame_rate.d); } // Deal with args that depend on input stream handle_args_dependent (argc, argv); // Scaling algorithm determination if ((algorithm == 0) || (algorithm == -1)) { // Coherences check: resample can only downscale not upscale if ((input_useful_width < output_active_width) || (input_useful_height < output_active_height)) { if (algorithm == 0) mjpeg_info ("Resampling algorithm can only downscale, not upscale => switching to bicubic algorithm"); algorithm = 1; } else algorithm = 0; } // USER'S INFORMATION OUTPUT yuvscaler_print_information (in_streaminfo, frame_rate); divider = pgcd (input_useful_width, output_active_width); input_width_slice = input_useful_width / divider; output_width_slice = output_active_width / divider; mjpeg_debug ("divider,i_w_s,o_w_s = %d,%d,%d", divider, input_width_slice, output_width_slice); divider = pgcd (input_useful_height, output_active_height); input_height_slice = input_useful_height / divider; output_height_slice = output_active_height / divider; mjpeg_debug ("divider,i_w_s,o_w_s = %d,%d,%d", divider, input_height_slice, output_height_slice); diviseur = input_height_slice * input_width_slice; mjpeg_debug ("Diviseur=%ld", diviseur); mjpeg_info ("Scaling ratio for width is %u to %u", input_width_slice, output_width_slice); mjpeg_info ("and is %u to %u for height", input_height_slice, output_height_slice); // Now that we know about scaling ratios, we can optimize treatment of an active input zone: // we must also check final new size is multiple of 2 on width and 2 or 4 on height if (input_black == 1) { if (((nb = input_black_line_above / input_height_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { if (interlaced == Y4M_ILACE_NONE) { input_useful = 1; black = 1; black_line = 1; output_black_line_above += nb * output_height_slice; input_black_line_above -= nb * input_height_slice; input_discard_line_above += nb * input_height_slice; } if ((interlaced != Y4M_ILACE_NONE) && ((nb * input_height_slice) % 4 == 0)) { input_useful = 1; black = 1; black_line = 1; output_black_line_above += nb * output_height_slice; input_black_line_above -= nb * input_height_slice; input_discard_line_above += nb * input_height_slice; } } if (((nb = input_black_line_under / input_height_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { if (interlaced == Y4M_ILACE_NONE) { input_useful = 1; black = 1; black_line = 1; output_black_line_under += nb * output_height_slice; input_black_line_under -= nb * input_height_slice; input_discard_line_under += nb * input_height_slice; } if ((interlaced != Y4M_ILACE_NONE) && ((nb * input_height_slice) % 4 == 0)) { input_useful = 1; black = 1; black_line = 1; output_black_line_under += nb * output_height_slice; input_black_line_under -= nb * input_height_slice; input_discard_line_under += nb * input_height_slice; } } if (((nb = input_black_col_left / input_width_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { input_useful = 1; black = 1; black_col = 1; output_black_col_left += nb * output_width_slice; input_black_col_left -= nb * input_width_slice; input_discard_col_left += nb * input_width_slice; } if (((nb = input_black_col_right / input_width_slice) > 0) && ((nb * input_height_slice) % 2 == 0)) { input_useful = 1; black = 1; black_col = 1; output_black_col_right += nb * output_width_slice; input_black_col_right -= nb * input_width_slice; input_discard_col_right += nb * input_width_slice; } input_useful_height = input_height - input_discard_line_above - input_discard_line_under; input_useful_width = input_width - input_discard_col_left - input_discard_col_right; input_active_width = input_useful_width - input_black_col_left - input_black_col_right; input_active_height = input_useful_height - input_black_line_above - input_black_line_under; if ((input_active_width == input_useful_width) && (input_active_height == input_useful_height)) input_black = 0; // black zone doesn't go beyong useful zone output_active_width = (input_useful_width / input_width_slice) * output_width_slice; output_active_height = (input_useful_height / input_height_slice) * output_height_slice; // USER'S INFORMATION OUTPUT mjpeg_info (" --- Newly speed optimized parameters ---"); yuvscaler_print_information (in_streaminfo, frame_rate); } // Take care of the case where ratios are 1:1 and 1:1 => in the resample algorithm category by convention if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 1) && (input_width_slice == 1)) algorithm =0; // RESAMPLE RESAMPLE RESAMPLE if (algorithm == 0) { // SPECIFIC // Is a specific downscaling speed enhanced treatment available? if ((output_width_slice == 1) && (input_width_slice == 1)) specific = 5; if ((output_width_slice == 1) && (input_width_slice == 1) && (input_height_slice == 4) && (output_height_slice == 3)) specific = 7; if ((input_height_slice == 2) && (output_height_slice == 1)) specific = 3; if ((output_height_slice == 1) && (input_height_slice == 1)) specific = 1; if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 2) && (input_width_slice == 3)) specific = 6; if ((output_height_slice == 1) && (input_height_slice == 1) && (output_width_slice == 1) && (input_width_slice == 1)) specific = 4; if ((input_height_slice == 2) && (output_height_slice == 1) && (input_width_slice == 2) && (output_width_slice == 1)) specific = 2; if ((input_height_slice == 8) && (output_height_slice == 3)) specific = 9; if ((input_height_slice == 8) && (output_height_slice == 3) && (input_width_slice == 2) && (output_width_slice == 1)) specific = 8; if (specific) mjpeg_info ("Specific downscaling routing number %u", specific); // To determine scaled value of pixels in the case of the resample algorithm, we have to divide a long int by // the long int "diviseur". So, to speed up downscaling, we tabulate all possible results of this division // using the divide vector and the function yuvscaler_nearest_integer_division. if (! (divide = (uint8_t *) malloc ((1 + 255 * diviseur) * sizeof (uint8_t) + ALIGNEMENT))) mjpeg_error_exit1 ("Could not allocate memory for divide table. STOP!"); mjpeg_debug ("before alignement: divide=%p", divide); // alignement instructions if (((unsigned long) divide % ALIGNEMENT) != 0) divide = (uint8_t *) ((((unsigned long) divide / ALIGNEMENT) + 1) * ALIGNEMENT); mjpeg_debug ("after alignement: divide=%p", divide); u_c_p = divide; for (i = 0; i <= 255 * diviseur; i++) *(u_c_p++) = yuvscaler_nearest_integer_division (i, diviseur); // Calculate averaging coefficient // For the height height_coeff = malloc ((input_height_slice + 1) * output_height_slice * sizeof (unsigned int)); average_coeff (input_height_slice, output_height_slice, height_coeff); // For the width width_coeff = malloc ((input_width_slice + 1) * output_width_slice * sizeof (unsigned int)); average_coeff (input_width_slice, output_width_slice, width_coeff);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -