stretch.c
来自「linux下的MPEG1」· C语言 代码 · 共 697 行 · 第 1/2 页
C
697 行
/* * Copyright (C) 2000-2004 the xine project * * This file is part of xine, a free video player. * * xine 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. * * xine 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * Time stretch by a given factor, optionally preserving pitch * * $Id: stretch.c,v 1.8 2006/01/27 07:46:12 tmattern Exp $ * */#include <stdio.h>#include "xine_internal.h"#include "xineutils.h"#include "post.h"#include "dsp.h"#include "resample.h"#include "audio_filters.h"#define AUDIO_FRAGMENT 120/1000 /* ms of audio */#define CLIP_INT16(s) ((s) < INT16_MIN) ? INT16_MIN : \ (((s) > INT16_MAX) ? INT16_MAX : (s))/* * *************************************************** * stretchable unix System Clock Reference * use stretch factor to calculate speed * *************************************************** */struct stretchscr_s { scr_plugin_t scr; struct timeval cur_time; int64_t cur_pts; int xine_speed; double speed_factor; double *stretch_factor; pthread_mutex_t lock;};typedef struct stretchscr_s stretchscr_t;static int stretchscr_get_priority (scr_plugin_t *scr) { return 10; /* high priority */}/* Only call this when already mutex locked */static void stretchscr_set_pivot (stretchscr_t *this) { struct timeval tv; int64_t pts; double pts_calc; xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc;/* This next part introduces a one off inaccuracy * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; this->cur_pts=pts; return ;}static int stretchscr_set_speed (scr_plugin_t *scr, int speed) { stretchscr_t *this = (stretchscr_t*) scr; pthread_mutex_lock (&this->lock); stretchscr_set_pivot( this ); this->xine_speed = speed; this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL / (*this->stretch_factor); pthread_mutex_unlock (&this->lock); return speed;}static void stretchscr_adjust (scr_plugin_t *scr, int64_t vpts) { stretchscr_t *this = (stretchscr_t*) scr; struct timeval tv; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; this->cur_pts = vpts; pthread_mutex_unlock (&this->lock);}static void stretchscr_start (scr_plugin_t *scr, int64_t start_vpts) { stretchscr_t *this = (stretchscr_t*) scr; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&this->cur_time, NULL); this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); stretchscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL);}static int64_t stretchscr_get_current (scr_plugin_t *scr) { stretchscr_t *this = (stretchscr_t*) scr; struct timeval tv; int64_t pts; double pts_calc; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; pthread_mutex_unlock (&this->lock); return pts;}static void stretchscr_exit (scr_plugin_t *scr) { stretchscr_t *this = (stretchscr_t*) scr; pthread_mutex_destroy (&this->lock); free(this);}static stretchscr_t* stretchscr_init (double *stretch_factor) { stretchscr_t *this; this = (stretchscr_t *) xine_xmalloc(sizeof(stretchscr_t)); this->scr.interface_version = 3; this->scr.get_priority = stretchscr_get_priority; this->scr.set_fine_speed = stretchscr_set_speed; this->scr.adjust = stretchscr_adjust; this->scr.start = stretchscr_start; this->scr.get_current = stretchscr_get_current; this->scr.exit = stretchscr_exit; pthread_mutex_init (&this->lock, NULL); this->stretch_factor = stretch_factor; stretchscr_set_speed (&this->scr, XINE_SPEED_PAUSE); return this;}/*****************************************************/typedef struct post_plugin_stretch_s post_plugin_stretch_t;typedef struct post_class_stretch_s post_class_stretch_t;struct post_class_stretch_s { post_class_t post_class; xine_t *xine;};typedef struct stretch_parameters_s { int preserve_pitch; double factor;} stretch_parameters_t;/* * description of params struct */START_PARAM_DESCR( stretch_parameters_t )PARAM_ITEM( POST_PARAM_TYPE_BOOL, preserve_pitch, NULL, 0, 1, 0, "Preserve pitch" )PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, factor, NULL, 0.5, 1.5, 0, "Time stretch factor (<1.0 shorten duration)" )END_PARAM_DESCR( param_descr )/* plugin structure */struct post_plugin_stretch_s { post_plugin_t post; stretchscr_t* scr; /* private data */ stretch_parameters_t params; xine_post_in_t params_input; int params_changed; int channels; int bytes_per_frame; int16_t *audiofrag; /* audio fragment to work on */ int16_t *outfrag; /* processed audio fragment */ _ftype_t *w; int frames_per_frag; int frames_per_outfrag; int num_frames; /* current # of frames on audiofrag */ int16_t last_sample[RESAMPLE_MAX_CHANNELS]; int64_t pts; /* pts for audiofrag */ pthread_mutex_t lock;};/************************************************************************** * stretch parameters functions *************************************************************************/static int set_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_stretch_t *this = (post_plugin_stretch_t *)this_gen; stretch_parameters_t *param = (stretch_parameters_t *)param_gen; pthread_mutex_lock (&this->lock); memcpy( &this->params, param, sizeof(stretch_parameters_t) ); this->params_changed = 1; pthread_mutex_unlock (&this->lock); return 1;}static int get_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_stretch_t *this = (post_plugin_stretch_t *)this_gen; stretch_parameters_t *param = (stretch_parameters_t *)param_gen; pthread_mutex_lock (&this->lock); memcpy( param, &this->params, sizeof(stretch_parameters_t) ); pthread_mutex_unlock (&this->lock); return 1;}static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr;}static char * get_help (void) { return _("This filter will perform a time stretch, playing the " "stream faster or slower by a factor. Pitch is optionally " "preserved, so it is possible, for example, to use it to " "watch a movie in less time than it was originaly shot.\n" );}static xine_post_api_t post_api = { set_parameters, get_parameters, get_param_descr, get_help,};/************************************************************************** * xine audio post plugin functions *************************************************************************/static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode) { post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; int64_t time; _x_post_rewire(&this->post); _x_post_inc_usage(port); port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; /* register our own scr provider */ time = port->stream->xine->clock->get_current_time(port->stream->xine->clock); this->scr = stretchscr_init(&this->params.factor); this->scr->scr.start(&this->scr->scr, time); port->stream->xine->clock->register_scr(port->stream->xine->clock, &this->scr->scr); /* force updating on stretch_port_put_buffer */ this->params_changed = 1; return (port->original_port->open) (port->original_port, stream, bits, rate, mode);}static void stretch_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream ) { post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; if (this->scr) { port->stream->xine->clock->unregister_scr(port->stream->xine->clock, &this->scr->scr); this->scr->scr.exit(&this->scr->scr); } if(this->audiofrag) { free(this->audiofrag); this->audiofrag = NULL; } if(this->outfrag) { free(this->outfrag); this->outfrag = NULL; } if(this->w) { free(this->w); this->w = NULL; } port->stream = NULL; port->original_port->close(port->original_port, stream ); _x_post_dec_usage(port);}static void stretch_process_fragment( post_audio_port_t *port, xine_stream_t *stream, extra_info_t *extra_info ){ post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?