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 + -
显示快捷键?