H.264 source codes

源代码在线查看: codec.c

软件大小: 641 K
上传用户: pzf_zj_cn
关键词: nbsp source codes 264
下载地址: 免注册下载 普通下载 VIP

相关代码

				/*****************************************************************************				 * codec.c: vfw x264 encoder				 *****************************************************************************				 * Copyright (C) 2003 Laurent Aimar				 * $Id: codec.c,v 1.1 2004/06/03 19:27:09 fenrir Exp $				 *				 * Authors: Justin Clay				 *          Laurent Aimar 				 *				 * 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.				 *****************************************************************************/								#include "x264vfw.h"								#include  /* debug only */				#include 								#define X264_MAX(a,b) ( (a)>(b) ? (a) : (b) )				#define X264_MIN(a,b) ( (a)								/* get_csp:				 *  return a valid x264 CSP or X264_CSP_NULL if unsuported */				static int get_csp( BITMAPINFOHEADER *hdr )				{				    switch( hdr->biCompression )				    {				        case FOURCC_I420:				        case FOURCC_IYUV:				            return X264_CSP_I420;								        case FOURCC_YV12:				            return X264_CSP_YV12;								        case FOURCC_YUYV:				        case FOURCC_YUY2:				            return X264_CSP_YUYV;								        case BI_RGB:				        {				            int i_vflip = hdr->biHeight < 0 ? 0 : X264_CSP_VFLIP;								            if( hdr->biBitCount == 24 )				                return X264_CSP_BGR | i_vflip;				            if( hdr->biBitCount == 32 )				                return X264_CSP_BGRA | i_vflip;				            else				                return X264_CSP_NONE;				        }								        default:				            return X264_CSP_NONE;				    }				}								/* Test that we can do the compression */				LRESULT compress_query( CODEC *codec, BITMAPINFO *lpbiInput, BITMAPINFO *lpbiOutput )				{				    BITMAPINFOHEADER *inhdr = &lpbiInput->bmiHeader;				    BITMAPINFOHEADER *outhdr = &lpbiOutput->bmiHeader;				    CONFIG           *config = &codec->config;								    if( get_csp( inhdr ) == X264_CSP_NONE )				        return ICERR_BADFORMAT;								    if( lpbiOutput == NULL )				        return ICERR_OK;								    if( inhdr->biWidth != outhdr->biWidth ||				        inhdr->biHeight != outhdr->biHeight )				        return ICERR_BADFORMAT;								    /* We need x16 width/height */				    if( inhdr->biWidth % 16 != 0 || inhdr->biHeight % 16 != 0 )				        return ICERR_BADFORMAT;												    if( inhdr->biCompression != mmioFOURCC( config->fcc[0], config->fcc[1],				                                            config->fcc[2], config->fcc[3] ) )				        return ICERR_BADFORMAT;								    return ICERR_OK;				}								/* */				LRESULT compress_get_format( CODEC *codec, BITMAPINFO *lpbiInput, BITMAPINFO *lpbiOutput )				{				    BITMAPINFOHEADER *inhdr = &lpbiInput->bmiHeader;				    BITMAPINFOHEADER *outhdr = &lpbiOutput->bmiHeader;				    CONFIG           *config = &codec->config;								    if( get_csp( inhdr ) == X264_CSP_NONE )				        return ICERR_BADFORMAT;								    if( lpbiOutput == NULL )				        return sizeof(BITMAPINFOHEADER);								    memcpy( outhdr, inhdr, sizeof( BITMAPINFOHEADER ) );				    outhdr->biSize = sizeof( BITMAPINFOHEADER );				    outhdr->biSizeImage = compress_get_size( codec, lpbiInput, lpbiOutput );				    outhdr->biXPelsPerMeter = 0;				    outhdr->biYPelsPerMeter = 0;				    outhdr->biClrUsed = 0;				    outhdr->biClrImportant = 0;				    outhdr->biCompression = mmioFOURCC( config->fcc[0], config->fcc[1],				                                        config->fcc[2], config->fcc[3] );								    return ICERR_OK;				}								/* */				LRESULT compress_get_size( CODEC *codec, BITMAPINFO *lpbiInput, BITMAPINFO *lpbiOutput )				{				    return 2 * lpbiOutput->bmiHeader.biWidth * lpbiOutput->bmiHeader.biHeight * 3;				}								/* */				LRESULT compress_frames_info(CODEC * codec, ICCOMPRESSFRAMES * icf )				{				    codec->fincr = icf->dwScale;				    codec->fbase = icf->dwRate;				    return ICERR_OK;				}								static void x264_log_vfw( void *p_private, int i_level, const char *psz_fmt, va_list arg )				{ 				    char error_msg[1024];				    int idx;				    HWND *hCons = p_private;								    vsprintf( error_msg, psz_fmt, arg );				    				    /* strip final linefeeds (required) */				    idx=strlen( error_msg ) - 1;				    while( idx >= 0 && error_msg[idx] == '\n' )				        error_msg[idx--] = 0;								    if(!( *hCons ) ) {				        *hCons = CreateDialog( g_hInst, MAKEINTRESOURCE( IDD_ERRCONSOLE ), NULL, 				                 callback_err_console );				        //ShowWindow( *hCons, SW_SHOW );				    }				    idx = SendDlgItemMessage( *hCons, IDC_CONSOLE, LB_ADDSTRING, 0, ( LPARAM )error_msg );				    				    /* make sure that the last item added is visible (autoscroll) */				    if( idx >= 0 ) 				        SendDlgItemMessage( *hCons, IDC_CONSOLE, LB_SETTOPINDEX, ( WPARAM )idx, 0 );								}								static void statsfilename_renumber( char *dest, char *src, int i_pass )				{				    char *last_dot = strrchr( src, '.' );				    char *last_slash = X264_MAX( strrchr( src, '/' ), strrchr( src, '\\' ) );				    char pass_str[5];								    sprintf( pass_str, "-%i", i_pass );				    strcpy( dest, src );				    if( last_slash < last_dot ) {				        dest[ last_dot - src ] = 0;				        strcat( dest, pass_str );				        strcat( dest, last_dot );				    }				    else				    {				        strcat( dest, pass_str );				    }				}								/* */				LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput )				{				    CONFIG *config = &codec->config;				    x264_param_t param;				    int pass_number;								    /* Destroy previous handle */				    if( codec->h != NULL )				    {				        x264_encoder_close( codec->h );				        codec->h = NULL;				    }								    /* Get default param */				    x264_param_default( ¶m );								    param.rc.psz_stat_out = malloc (MAX_PATH);				    param.rc.psz_stat_in = malloc (MAX_PATH);				  				    param.i_log_level = X264_LOG_ERROR;				    param.pf_log = x264_log_vfw;				    param.p_log_private = malloc( sizeof( HWND ) );				    *( ( HWND * )param.p_log_private ) = NULL; /* error console window handle */				    codec->hCons = ( HWND * )param.p_log_private;								    param.analyse.b_psnr = 0;				    param.analyse.inter = 0;				    param.analyse.intra = X264_ANALYSE_I4x4;								    /* Set params: TODO to complete */				    param.i_width = lpbiInput->bmiHeader.biWidth;				    param.i_height= lpbiInput->bmiHeader.biHeight;								    param.i_fps_num = codec->fbase;				    param.i_fps_den = codec->fincr;								    param.i_frame_reference = config->i_refmax;				    param.i_keyint_min = config->i_keyint_min;				    param.i_keyint_max = config->i_keyint_max;				    param.b_deblocking_filter = config->b_filter;				    param.b_cabac = config->b_cabac;				    param.rc.f_ip_factor = 1 + (float)config->i_key_boost / 100;				    param.rc.f_pb_factor = 1 + (float)config->i_b_red / 100;				    param.rc.f_qcompress = (float)config->i_curve_comp / 100;								    param.i_bframe = config->i_bframe;				    if( config->i_bframe > 1 && config->b_b_wpred)				        param.analyse.b_weighted_bipred = 1;				    if( config->i_bframe > 1 && config->b_b_refs)				        param.b_bframe_pyramid = 1;				    param.analyse.i_subpel_refine = config->i_subpel_refine + 1; /* 0..4 -> 1..5 */								    /* bframe prediction - gui goes alphabetically, so 1=SPATIAL, 2=TEMPORAL */				    switch(config->i_direct_mv_pred) {				        case 0: param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL; break;				        case 1: param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_TEMPORAL; break;				    }				    param.i_deblocking_filter_alphac0 = config->i_inloop_a;				    param.i_deblocking_filter_beta = config->i_inloop_a;								    if( config->b_bsub16x16 )				        param.analyse.inter |= X264_ANALYSE_BSUB16x16;				    if( config->b_psub16x16 )				    {				        param.analyse.inter |= X264_ANALYSE_PSUB16x16;				        if( config->b_psub8x8 )				            param.analyse.inter |= X264_ANALYSE_PSUB8x8;				    }				    if( config->b_i4x4 )				        param.analyse.inter |= X264_ANALYSE_I4x4;								    switch( config->i_encoding_type )				    {				        case 0: /* 1 PASS ABR */				            param.rc.b_cbr = 1;				            param.rc.i_bitrate = config->bitrate;				            break;				        case 1: /* 1 PASS CQ */				            param.rc.i_qp_constant = config->i_qp;				            break;				        default:				        case 2: /* 2 PASS */				        {				            for( pass_number = 1; pass_number < 99; pass_number++ )				            {				                FILE *f;				                statsfilename_renumber( param.rc.psz_stat_out, config->stats, pass_number );				                if( ( f = fopen( param.rc.psz_stat_out, "r" ) ) != NULL )				                {				                    fclose( f );				                    if( config->i_pass == 1 )				                        unlink( param.rc.psz_stat_out );				                }				                else break;				            }								            if( config->i_pass > pass_number )				            {				                /* missing 1st pass statsfile */				                free( param.rc.psz_stat_out );				                free( param.rc.psz_stat_in );				                return ICERR_ERROR;				            }								            param.rc.i_bitrate = config->i_2passbitrate;				            param.rc.b_cbr = 1;								            if( config->i_pass == 1 )				            {				                statsfilename_renumber( param.rc.psz_stat_out, config->stats, 1 );				                param.rc.b_stat_write = 1;				                param.rc.f_rate_tolerance = 4;				                if( config->b_fast1pass )				                {				                    /* adjust or turn off some flags to gain speed, if needed */				                    param.analyse.i_subpel_refine = X264_MAX( X264_MIN( 3, param.analyse.i_subpel_refine - 1 ), 1 );				                    param.i_frame_reference = ( param.i_frame_reference + 1 ) >> 1;				                    param.analyse.inter &= ( ~X264_ANALYSE_PSUB8x8 );				                    param.analyse.inter &= ( ~X264_ANALYSE_BSUB16x16 );				                }				            }				            else				            {				                statsfilename_renumber( param.rc.psz_stat_in, config->stats, pass_number - 1 );				                param.rc.b_stat_read = 1;				                if( config->b_updatestats )				                    param.rc.b_stat_write = 1;				                param.rc.f_rate_tolerance = 1;				            }								            break;				        }				    }								    /* Open the encoder */				    codec->h = x264_encoder_open( ¶m );								    free( param.rc.psz_stat_out );				    free( param.rc.psz_stat_in );								    if( codec->h == NULL )				        return ICERR_ERROR;								    return ICERR_OK;				}								/* */				LRESULT compress_end(CODEC * codec)				{				    if( codec->h != NULL )				    {				        x264_encoder_close( codec->h );				        codec->h = NULL;				    }								    free( codec->hCons );				    return ICERR_OK;				}								/* */				LRESULT compress( CODEC *codec, ICCOMPRESS *icc )				{				    BITMAPINFOHEADER *inhdr = icc->lpbiInput;				    BITMAPINFOHEADER *outhdr = icc->lpbiOutput;								    x264_picture_t pic;								    int        i_nal;				    x264_nal_t *nal;				    int        i_out;								    int i;								    /* Init the picture */				    memset( &pic, 0, sizeof( x264_picture_t ) );				    pic.img.i_csp = get_csp( inhdr );								    /* For now biWidth can be divided by 16 so no problem */				    switch( pic.img.i_csp & X264_CSP_MASK )				    {				        case X264_CSP_I420:				        case X264_CSP_YV12:				            pic.img.i_plane = 3;				            pic.img.i_stride[0] = inhdr->biWidth;				            pic.img.i_stride[1] =				            pic.img.i_stride[2] = inhdr->biWidth / 2;								            pic.img.plane[0]    = (uint8_t*)icc->lpInput;				            pic.img.plane[1]    = pic.img.plane[0] + inhdr->biWidth * inhdr->biHeight;				            pic.img.plane[2]    = pic.img.plane[1] + inhdr->biWidth * inhdr->biHeight / 4;				            break;								        case X264_CSP_YUYV:				            pic.img.i_plane = 1;				            pic.img.i_stride[0] = 2 * inhdr->biWidth;				            pic.img.plane[0]    = (uint8_t*)icc->lpInput;				            break;								        case X264_CSP_BGR:				            pic.img.i_plane = 1;				            pic.img.i_stride[0] = 3 * inhdr->biWidth;				            pic.img.plane[0]    = (uint8_t*)icc->lpInput;				            break;								        case X264_CSP_BGRA:				            pic.img.i_plane = 1;				            pic.img.i_stride[0] = 4 * inhdr->biWidth;				            pic.img.plane[0]    = (uint8_t*)icc->lpInput;				            break;								        default:				            return ICERR_BADFORMAT;				    }								    /* encode it */				    x264_encoder_encode( codec->h, &nal, &i_nal, &pic, &pic );								    /* create bitstream, unless we're dropping it in 1st pass */				    i_out = 0;								    if( codec->config.i_encoding_type != 2 || codec->config.i_pass > 1 ) {				        for( i = 0; i < i_nal; i++ ) {				            int i_size = outhdr->biSizeImage - i_out;				            x264_nal_encode( (uint8_t*)icc->lpOutput + i_out, &i_size, 1, &nal[i] );								            i_out += i_size;				        }				    }								    outhdr->biSizeImage = i_out;								    /* Set key frame only for IDR, as they are real synch point, I frame				       aren't always synch point (ex: with multi refs, ref marking) */				    if( pic.i_type == X264_TYPE_IDR )				        *icc->lpdwFlags = AVIIF_KEYFRAME;				    else				        *icc->lpdwFlags = 0;								    return ICERR_OK;				}											

相关资源