transrate.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,148 行 · 第 1/5 页
C
2,148 行
/***************************************************************************** * transrate.c: MPEG2 video transrating module ***************************************************************************** * Copyright (C) 2003 VideoLAN * Copyright (C) 2003 Freebox S.A. * Copyright (C) 2003 Antoine Missout * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * $Id: transrate.c,v 1.6 2004/01/25 14:34:25 gbazin Exp $ * * Authors: Christophe Massiot <massiot@via.ecp.fr> * Laurent Aimar <fenrir@via.ecp.fr> * Antoine Missout * Michel Lespinasse <walken@zoy.org> * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdio.h>#include <stdlib.h>#define NDEBUG 1#include <assert.h>#include <math.h>#include <vlc/vlc.h>#include <vlc/sout.h>#include <vlc/input.h>/***************************************************************************** * Exported prototypes *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );static int Del ( sout_stream_t *, sout_stream_id_t * );static int Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );static int transrate_video_process( sout_stream_t *, sout_stream_id_t *, sout_buffer_t *, sout_buffer_t ** );/***************************************************************************** * Module descriptor *****************************************************************************/vlc_module_begin(); set_description( _("MPEG2 video transrating stream output") ); set_capability( "sout stream", 50 ); add_shortcut( "transrate" ); set_callbacks( Open, Close );vlc_module_end();struct sout_stream_sys_t{ sout_stream_t *p_out; int i_vbitrate; mtime_t i_first_frame; mtime_t i_dts, i_pts;};/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){ sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_sys_t *p_sys; char *val; p_sys = malloc( sizeof( sout_stream_sys_t ) ); p_sys->p_out = sout_stream_new( p_stream->p_sout, p_stream->psz_next ); p_sys->i_vbitrate = 0; if( ( val = sout_cfg_find_value( p_stream->p_cfg, "vb" ) ) ) { p_sys->i_vbitrate = atoi( val ); if( p_sys->i_vbitrate < 16000 ) { p_sys->i_vbitrate *= 1000; } } else { p_sys->i_vbitrate = 3000000; } p_sys->i_first_frame = 0; msg_Dbg( p_stream, "codec video %dkb/s", p_sys->i_vbitrate / 1024 ); if( !p_sys->p_out ) { msg_Err( p_stream, "cannot create chain" ); free( p_sys ); return VLC_EGENERIC; } p_stream->pf_add = Add; p_stream->pf_del = Del; p_stream->pf_send = Send; p_stream->p_sys = p_sys; p_stream->p_sout->i_padding += 200; return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t * p_this ){ sout_stream_t *p_stream = (sout_stream_t *)p_this; sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_delete( p_sys->p_out ); free( p_sys );}/***************************************************************************** * sout_stream_id_t: *****************************************************************************/typedef struct{ uint8_t run; short level;} RunLevel;typedef struct{ uint8_t *p_c; uint8_t *p_r; uint8_t *p_w; uint8_t *p_ow; uint8_t *p_rw; int i_bit_in; int i_bit_out; uint32_t i_bit_in_cache; uint32_t i_bit_out_cache; uint32_t i_byte_in; uint32_t i_byte_out;} bs_transrate_t;typedef struct{ bs_transrate_t bs; /* MPEG2 state */ // seq header unsigned int horizontal_size_value; unsigned int vertical_size_value; // pic header unsigned int picture_coding_type; // pic code ext unsigned int f_code[2][2]; /* unsigned int intra_dc_precision; */ unsigned int picture_structure; unsigned int frame_pred_frame_dct; unsigned int concealment_motion_vectors; unsigned int q_scale_type; unsigned int intra_vlc_format; /* unsigned int alternate_scan; */ // slice or mb // quantizer_scale_code unsigned int quantizer_scale; unsigned int new_quantizer_scale; unsigned int last_coded_scale; int h_offset, v_offset; // mb double quant_corr, fact_x, current_fact_x; int level_i, level_p; ssize_t i_current_gop_size, i_wanted_gop_size, i_new_gop_size;} transrate_t;struct sout_stream_id_t{ void *id; vlc_bool_t b_transrate; sout_buffer_t *p_current_buffer; sout_buffer_t *p_next_gop; mtime_t i_next_gop_duration; size_t i_next_gop_size; transrate_t tr;};static sout_stream_id_t * Add( sout_stream_t *p_stream, es_format_t *p_fmt ){ sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_t *id; id = malloc( sizeof( sout_stream_id_t ) ); id->id = NULL; if( p_fmt->i_cat == VIDEO_ES && p_fmt->i_codec == VLC_FOURCC('m', 'p', 'g', 'v') ) { msg_Dbg( p_stream, "creating video transrating for fcc=`%4.4s'", (char*)&p_fmt->i_codec ); id->p_current_buffer = NULL; id->p_next_gop = NULL; id->i_next_gop_duration = 0; id->i_next_gop_size = 0; memset( &id->tr, 0, sizeof( transrate_t ) ); id->tr.bs.i_byte_in = id->tr.bs.i_byte_out = 0; id->tr.fact_x = 1.0; /* open output stream */ id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt ); id->b_transrate = VLC_TRUE; } else { msg_Dbg( p_stream, "not transrating a stream (fcc=`%4.4s')", (char*)&p_fmt->i_codec ); id->id = p_sys->p_out->pf_add( p_sys->p_out, p_fmt ); id->b_transrate = VLC_FALSE; if( id->id == NULL ) { free( id ); return NULL; } } return id;}static int Del ( sout_stream_t *p_stream, sout_stream_id_t *id ){ sout_stream_sys_t *p_sys = p_stream->p_sys; if( id->id ) { p_sys->p_out->pf_del( p_sys->p_out, id->id ); } free( id ); return VLC_SUCCESS;}static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer ){ sout_stream_sys_t *p_sys = p_stream->p_sys; if( id->b_transrate ) { sout_buffer_t *p_buffer_out; transrate_video_process( p_stream, id, p_buffer, &p_buffer_out ); if( p_buffer_out ) { return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer_out ); } return VLC_SUCCESS; } else if( id->id != NULL ) { return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer ); } else { sout_BufferDelete( p_stream->p_sout, p_buffer ); return VLC_EGENERIC; }}/**************************************************************************** * transrater, code from M2VRequantizer http://www.metakine.com/ ****************************************************************************//* This is awful magic --Meuuh *///#define REACT_DELAY (1024.0*128.0)#define REACT_DELAY (256.0)#define QUANT_I (1.7)#define QUANT_P (1.4)#define QUANT_P_INC (0.1)#define B_HANDICAP 5// notes://// - intra block:// - the quantiser is increment by one step//// - non intra block:// - in P_FRAME we keep the original quantiser but drop the last coefficient// if there is more than one// - in B_FRAME we multiply the quantiser by a factor//// - I_FRAME is recoded when we're 5.0 * REACT_DELAY late// - P_FRAME is recoded when we're 2.5 * REACT_DELAY late// - B_FRAME are always recoded// if we're getting *very* late (60 * REACT_DELAY)//// - intra blocks quantiser is incremented two step// - drop a few coefficients but always keep the first one// useful constantsenum{ I_TYPE = 1, P_TYPE = 2, B_TYPE = 3};// gcc#ifdef HAVE_BUILTIN_EXPECT#define likely(x) __builtin_expect ((x) != 0, 1)#define unlikely(x) __builtin_expect ((x) != 0, 0)#else#define likely(x) (x)#define unlikely(x) (x)#endif#define BITS_IN_BUF (8)#define LOG(msg) fprintf (stderr, msg)#define LOGF(format, args...) fprintf (stderr, format, args)static inline void bs_write( bs_transrate_t *s, unsigned int val, int n){ assert(n < 32); assert(!(val & (0xffffffffU << n))); while (unlikely(n >= s->i_bit_out)) { s->p_w[0] = (s->i_bit_out_cache << s->i_bit_out ) | (val >> (n - s->i_bit_out)); s->p_w++; n -= s->i_bit_out; s->i_bit_out_cache = 0; val &= ~(0xffffffffU << n); s->i_bit_out = BITS_IN_BUF; } if (likely(n)) { s->i_bit_out_cache = (s->i_bit_out_cache << n) | val; s->i_bit_out -= n; } assert(s->i_bit_out > 0); assert(s->i_bit_out <= BITS_IN_BUF);}static inline void bs_refill( bs_transrate_t *s ){ assert((s->p_r - s->p_c) >= 1); s->i_bit_in_cache |= s->p_c[0] << (24 - s->i_bit_in); s->i_bit_in += 8; s->p_c++;}static inline void bs_flush( bs_transrate_t *s, unsigned int n ){ assert(s->i_bit_in >= n); s->i_bit_in_cache <<= n; s->i_bit_in -= n; assert( (!n) || ((n>0) && !(s->i_bit_in_cache & 0x1)) ); while (unlikely(s->i_bit_in < 24)) bs_refill( s );}static inline unsigned int bs_read( bs_transrate_t *s, unsigned int n){ unsigned int Val = ((unsigned int)s->i_bit_in_cache) >> (32 - n); bs_flush( s, n ); return Val;}static inline unsigned int bs_copy( bs_transrate_t *s, unsigned int n){ unsigned int Val = bs_read( s, n); bs_write(s, Val, n); return Val;}static inline void bs_flush_read( bs_transrate_t *s ){ int i = s->i_bit_in & 0x7; if( i ) { assert(((unsigned int)bs->i_bit_in_cache) >> (32 - i) == 0); s->i_bit_in_cache <<= i; s->i_bit_in -= i; } s->p_c += -1 * (s->i_bit_in >> 3); s->i_bit_in = 0;}static inline void bs_flush_write( bs_transrate_t *s )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?