📄 yuvfps.c
字号:
/* * yuvfps.c * Copyright (C) 2002 Alfonso Garcia-Pati駉 Barbolani <barbolani@jazzfree.com> * * Upsamples or downsamples a yuv stream to a specified frame rate * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include <sys/types.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include "yuv4mpeg.h"#include "mpegconsts.h"#define YUVFPS_VERSION "0.1"static void print_usage() { fprintf (stderr, "usage: yuvfps -r [NewFpsNum:NewFpsDen] [-s [InputFpsNum:InputFpsDen]] [-c] [-n] [-v -h]\n" "yuvfps resamples a yuv video stream read from stdin to a new stream, identical\n" "to the source with frames repeated/copied/removed written to stdout.\n" "\n" "\t -r Frame rate for the resulting stream (in X:Y fractional form)\n" "\t -s Assume this source frame rate ignoring source YUV header\n" "\t -c Change only the output header frame rate, does not modify stream\n" "\t -n don't try to normalize the input framerate\n" "\t -v Verbosity degree : 0=quiet, 1=normal, 2=verbose/debug\n" "\t -h print this help\n" );}//// Resamples the video stream coming from fdIn and writes it// to fdOut.// There are two variations of the same theme://// Upsampling: frames are duplicated when needed// Downsampling: frames from the original are skipped//// Parameters://// fdIn,fdOut : File descriptors for reading and writing the stream// inStream, outStream: stream handlers for the source and destination streams.// It is assumed that they are correctly initialized from/to// their respective file I/O streams with the desired sample rates.//// src_frame_rate, frame_rate: ratios for source and destination frame rate// (note that this may not match the information contained// in the stream itself due to command line options // )// // In both cases a Bresenham - style algorithm is used.//static void resample( int fdIn , y4m_stream_info_t *inStrInfo , y4m_ratio_t src_frame_rate , int fdOut , y4m_stream_info_t *outStrInfo , y4m_ratio_t frame_rate , int not_normalize ){ y4m_frame_info_t in_frame ; uint8_t *yuv_data[3] ; int read_error_code ; int write_error_code ; int src_frame_counter ; int dest_frame_counter ; // To perform bresenham resampling long long srcInc ; long long dstInc ; long long currCount ; y4m_ratio_t normalized_ratio; // Allocate memory for the YUV channels yuv_data[0] = (uint8_t *)malloc(y4m_si_get_plane_length(inStrInfo, 0)); yuv_data[1] = (uint8_t *)malloc(y4m_si_get_plane_length(inStrInfo, 1)); yuv_data[2] = (uint8_t *)malloc(y4m_si_get_plane_length(inStrInfo, 2)); if( !yuv_data[0] || !yuv_data[1] || !yuv_data[2] ) mjpeg_error_exit1 ("Could'nt allocate memory for the YUV4MPEG data!"); if (not_normalize == 0) { /* Trying to normalize the values */ normalized_ratio = mpeg_conform_framerate( (double)src_frame_rate.n/(double)src_frame_rate.d ); mjpeg_warn( "Original framerate: %d:%d, Normalized framerate: %d:%d", src_frame_rate.n, src_frame_rate.d, normalized_ratio.n, normalized_ratio.d ); src_frame_rate.n = normalized_ratio.n; src_frame_rate.d = normalized_ratio.d; } mjpeg_warn( "Converting from %d:%d to %d:%d", src_frame_rate.n,src_frame_rate.d,frame_rate.n,frame_rate.d ); /* Initialize counters */ srcInc = (long long)src_frame_rate.n * (long long)frame_rate.d ; dstInc = (long long)frame_rate.n * (long long)src_frame_rate.d ; write_error_code = Y4M_OK ; src_frame_counter = 0 ; dest_frame_counter = 0 ; y4m_init_frame_info( &in_frame ); read_error_code = y4m_read_frame(fdIn,inStrInfo,&in_frame,yuv_data ); ++src_frame_counter ; currCount = 0 ; while( Y4M_ERR_EOF != read_error_code && write_error_code == Y4M_OK ) { write_error_code = y4m_write_frame( fdOut, outStrInfo, &in_frame, yuv_data ); mjpeg_info( "Writing source frame %d at dest frame %d", src_frame_counter,++dest_frame_counter ); currCount += srcInc ; while( currCount >= dstInc && Y4M_ERR_EOF != read_error_code ) { currCount -= dstInc ; ++src_frame_counter ; y4m_fini_frame_info( &in_frame ); y4m_init_frame_info( &in_frame ); read_error_code = y4m_read_frame(fdIn, inStrInfo,&in_frame,yuv_data ); } } // Clean-up regardless an error happened or not y4m_fini_frame_info( &in_frame ); free( yuv_data[0] ); free( yuv_data[1] ); free( yuv_data[2] ); if( read_error_code != Y4M_ERR_EOF ) mjpeg_error_exit1 ("Error reading from input stream!"); if( write_error_code != Y4M_OK ) mjpeg_error_exit1 ("Error writing output stream!");}// *************************************************************************************// MAIN// *************************************************************************************int main (int argc, char *argv[]){ int verbose = LOG_ERROR ; int change_header_only = 0 ; int not_normalize = 0; int fdIn = 0 ; int fdOut = 1 ; y4m_stream_info_t in_streaminfo, out_streaminfo ; y4m_ratio_t frame_rate, src_frame_rate ; const static char *legal_flags = "r:s:cnv:h"; int c ; src_frame_rate.d = 0; while ((c = getopt (argc, argv, legal_flags)) != -1) { switch (c) { /* New frame rate */ case 'r': if( Y4M_OK != y4m_parse_ratio(&frame_rate, optarg) ) mjpeg_error_exit1 ("Syntax for frame rate should be Numerator:Denominator"); break; /* Assumed frame rate for source (useful when the header contains an invalid frame rate) */ case 's': if( Y4M_OK != y4m_parse_ratio(&src_frame_rate,optarg) ) mjpeg_error_exit1 ("Syntax for frame rate should be Numerator:Denominator"); break ; /* Only change header frame-rate, not the stream itself */ case 'c': change_header_only = 1 ; case 'n': not_normalize = 1; break; case 'v': verbose = atoi (optarg); if (verbose < 0 || verbose > 2) mjpeg_error_exit1 ("Verbose level must be [0..2]"); break; case 'h': case '?': print_usage (argv); return 0 ; break; } } y4m_accept_extensions(1); /* mjpeg tools global initialisations */ mjpeg_default_handler_verbosity (verbose); /* Initialize input streams */ y4m_init_stream_info (&in_streaminfo); y4m_init_stream_info (&out_streaminfo); // *************************************************************** // Get video stream informations (size, framerate, interlacing, aspect ratio). // The streaminfo structure is filled in // *************************************************************** // INPUT comes from stdin, we check for a correct file header if (y4m_read_stream_header (fdIn, &in_streaminfo) != Y4M_OK) mjpeg_error_exit1 ("Could'nt read YUV4MPEG header!"); if (y4m_si_get_plane_count(&in_streaminfo) != 3) mjpeg_error_exit1("Only 3 plane formats supported"); /* Prepare output stream */ if (src_frame_rate.d == 0) src_frame_rate = y4m_si_get_framerate( &in_streaminfo ); y4m_copy_stream_info( &out_streaminfo, &in_streaminfo ); /* Information output */ mjpeg_info ("yuv2fps (version " YUVFPS_VERSION ") is a general frame resampling utility for yuv streams"); mjpeg_info ("(C) 2002 Alfonso Garcia-Patino Barbolani <barbolani@jazzfree.com>"); mjpeg_info ("yuvfps -h for help, or man yuvfps"); y4m_si_set_framerate( &out_streaminfo, frame_rate ); y4m_write_stream_header(fdOut,&out_streaminfo); if( change_header_only ) frame_rate = src_frame_rate ; /* in that function we do all the important work */ resample( fdIn,&in_streaminfo, src_frame_rate, fdOut,&out_streaminfo, frame_rate, not_normalize ); y4m_fini_stream_info (&in_streaminfo); y4m_fini_stream_info (&out_streaminfo); return 0;}/* * Local variables: * tab-width: 8 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -