?? encoder.c
字號:
/*****************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - Encoder main module -
*
* This program is an implementation of a part of one or more MPEG-4
* Video tools as specified in ISO/IEC 14496-2 standard. Those intending
* to use this software module in hardware or software products are
* advised that its use may infringe existing patents or copyrights, and
* any such use would be at such party's own risk. The original
* developer of this software module and his/her company, and subsequent
* editors and their companies, will have no liability for use of this
* software or modifications or derivatives thereof.
*
* 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-1307 USA
*
****************************************************************************/
/*****************************************************************************
*
* History
*
* 20.06.2002 bframe patch
* 08.05.2002 fix some problem in DEBUG mode;
* MinChen <chenm001@163.com>
* 14.04.2002 added FrameCodeB()
*
* $Id: encoder.c,v 1.51 2002/06/30 10:46:29 suxen_drol Exp $
*
****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "encoder.h"
/*#include "prediction/mbprediction.h"*/
#include "global.h"
#include "utils/timer.h"
#include "image/image.h"
#include "user_macro.h"
#include "motion/motion.h"
#include "bitstream/cbp.h"
#include "utils/mbfunctions.h"
#include "bitstream/bitstream.h"
#include "bitstream/mbcoding.h"
#include "utils/ratecontrol.h"
#include "bitstream/mbcoding.h"
/*#include "quant/adapt_quant.h"*/
/*
#include "quant/quant_matrix.h"
*/
#include "utils/mem_align.h"
#include "motion/sad.h"
/*****************************************************************************
* Local macros
****************************************************************************/
#define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT
#define SWAP(A,B) { void * tmp = A; A = B; B = tmp; }
/*****************************************************************************
* Local function prototypes
****************************************************************************/
FILE *pEncLogFile=NULL;/*用于輸出記錄文件的指針 */
/*extern FILE * encodelog;*/
/*static int FrameCodeI(Encoder * pEnc,
Bitstream * bs,
uint32_t * pBits,int* head,BOOL scence_change,int *mad);*//*modify add head---*/
static int FrameCodeI(Encoder * pEnc,
Bitstream * bs,
uint32_t * pBits,int* head,int *mad);/*modify del scence_change---*/
/*增加scence_change 表示在編P幀過程中由于場景切換產(chǎn)生的I幀TURE 為有場景切換*/
/*static int FrameCodeP(Encoder * pEnc,
Bitstream * bs,
uint32_t * pBits,
bool force_inter,
bool vol_header,int* head_vector,int* mad);*/
static int FrameCodeP(Encoder * pEnc,
Bitstream * bs,
uint32_t * pBits,
int* head_vector,int* mad);
/*****************************************************************************
* Local data
****************************************************************************/
static int DQtab[4] = {
-1, -2, 1, 2
};
static int iDQtab[5] = {
1, 0, NO_CHANGE, 2, 3
};
static void __inline
image_null(IMAGE * image)
{
image->y = image->u = image->v = NULL;
}
/*
Calculate mad value of I frame.
For P frame, use sad vaule that comes from motion estimation to calculate mad value.
Add by fyh 2002.12.23
*/
int compute_MAD(Encoder * pEnc)
{ int mad=0;
uint32_t x,y;
for (y = 0; y < pEnc->mbParam.mb_height; y++)
for (x = 0; x < pEnc->mbParam.mb_width; x++)
{
mad+=dev16((uint8_t *)(pEnc->current->image.y + y*16 + y*16*pEnc->mbParam.edged_width),pEnc->mbParam.edged_width);
}
mad/=pEnc->mbParam.mb_height*pEnc->mbParam.mb_width;
return mad;
}
/*****************************************************************************
* Encoder creation
*
* This function creates an Encoder instance, it allocates all necessary
* image buffers (reference, current and bframes) and initialize the internal
* xvid encoder paremeters according to the XVID_ENC_PARAM input parameter.
*
* The code seems to be very long but is very basic, mainly memory allocation
* and cleaning code.
*
* Returned values :
* - XVID_ERR_OK - no errors
* - XVID_ERR_MEMORY - the libc could not allocate memory, the function
* cleans the structure before exiting.
* pParam->handle is also set to NULL.
*
****************************************************************************/
int
encoder_create(XVID_ENC_PARAM * pParam)
{
Encoder *pEnc;
int i;
/* decide P frame type by use amvfast . Add by fyh */
first_P_gop=1;
first_P_seq=1;
pParam->handle = NULL;
ENC_CHECK(pParam);
ENC_CHECK(pParam->width > 0 && pParam->width <= 1920);
ENC_CHECK(pParam->height > 0 && pParam->height <= 1280);
ENC_CHECK(!(pParam->width % 2));
ENC_CHECK(!(pParam->height % 2));
/* Fps */
if (pParam->fincr <= 0 || pParam->fbase <= 0) {
pParam->fincr = 1;
pParam->fbase = 25;
}
/*
* Simplify the "fincr/fbase" fraction
* (neccessary, since windows supplies us with huge numbers)
*/
i = pParam->fincr;
while (i > 1) {
if (pParam->fincr % i == 0 && pParam->fbase % i == 0) {
pParam->fincr /= i;
pParam->fbase /= i;
i = pParam->fincr;
continue;
}
i--;
}
if (pParam->fbase > 65535) {
float div = (float) pParam->fbase / 65535;
pParam->fbase = (int) (pParam->fbase / div);
pParam->fincr = (int) (pParam->fincr / div);
}
/* Bitrate allocator defaults */
if (pParam->rc_bitrate <= 0)
pParam->rc_bitrate = 900000;
if (pParam->rc_reaction_delay_factor <= 0)
pParam->rc_reaction_delay_factor = 16;
if (pParam->rc_averaging_period <= 0)
pParam->rc_averaging_period = 100;
if (pParam->rc_buffer <= 0)
pParam->rc_buffer = 100;
/* Max and min quantizers */
if ((pParam->min_quantizer <= 0) || (pParam->min_quantizer > 31))
pParam->min_quantizer = 1;
if ((pParam->max_quantizer <= 0) || (pParam->max_quantizer > 31))
pParam->max_quantizer = 31;
if (pParam->max_quantizer < pParam->min_quantizer)
pParam->max_quantizer = pParam->min_quantizer;
/* 1 keyframe each 10 seconds */
if (pParam->max_key_interval == 0)
pParam->max_key_interval = pParam->sequence_time* pParam->fincr / pParam->fbase;
pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE);
if (pEnc == NULL)
return XVID_ERR_MEMORY;
/* Zero the Encoder Structure */
memset(pEnc, 0, sizeof(Encoder));
/* Fill members of Encoder structure */
pEnc->mbParam.width = pParam->width;
pEnc->mbParam.height = pParam->height;
pEnc->mbParam.mb_width = (pEnc->mbParam.width + 15) / 16;
pEnc->mbParam.mb_height = (pEnc->mbParam.height + 15) / 16;
pEnc->mbParam.edged_width = 16 * pEnc->mbParam.mb_width + 2 * EDGE_SIZE;
pEnc->mbParam.edged_height = 16 * pEnc->mbParam.mb_height + 2 * EDGE_SIZE;
pEnc->mbParam.fbase = pParam->fbase;
pEnc->mbParam.fincr = pParam->fincr;
pEnc->mbParam.m_quant_type = H263_QUANT;
pEnc->sStat.fMvPrevSigma = -1;
/* Fill rate control parameters */
pEnc->bitrate = pParam->rc_bitrate;
pEnc->rc_type=pParam->rc_type;
pEnc->iFrameNum = 0;
pEnc->iMaxKeyInterval = pParam->max_key_interval;
/* try to allocate frame memory */
pEnc->current = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
pEnc->reference = xvid_malloc(sizeof(FRAMEINFO), CACHE_LINE);
if (pEnc->current == NULL || pEnc->reference == NULL)
goto xvid_err_memory1;
/* try to allocate mb memory */
pEnc->current->mbs =
xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
pEnc->mbParam.mb_height, CACHE_LINE);
pEnc->reference->mbs =
xvid_malloc(sizeof(MACROBLOCK) * pEnc->mbParam.mb_width *
pEnc->mbParam.mb_height, CACHE_LINE);
if (pEnc->current->mbs == NULL || pEnc->reference->mbs == NULL)
goto xvid_err_memory2;
/* try to allocate image memory */
/* 緩沖區(qū)指針的初始化 */
#ifdef _DEBUG_PSNR
image_null(&pEnc->sOriginal);
#endif
image_null(&pEnc->current->image);
image_null(&pEnc->reference->image);
image_null(&pEnc->vInterH);
image_null(&pEnc->vInterV);
/* image_null(&pEnc->vInterVf);*//* no use */
image_null(&pEnc->vInterHV);
/* image_null(&pEnc->vInterHVf);*//* no use */
#ifdef _DEBUG_PSNR
if (image_create
(&pEnc->sOriginal, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
#endif
if (image_create
(&pEnc->current->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
if (image_create
(&pEnc->reference->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
if (image_create
(&pEnc->vInterH, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
if (image_create
(&pEnc->vInterV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
/* if (image_create
(&pEnc->vInterVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;*/
if (image_create
(&pEnc->vInterHV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;
/* if (image_create
(&pEnc->vInterHVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height) < 0)
goto xvid_err_memory3;*/
pParam->handle = (void *) pEnc;
pEncLogFile=(FILE *)pParam->pFile;
if (pParam->rc_bitrate) {
if(pParam->rc_type)
RCInitialization(&pEnc->rc,pParam->rc_bitrate,pParam->fbase/pParam->fincr,
pParam->sequence_time);/*初始化位率控制 */
else
RateControlInit(&pEnc->rate_control, pParam->rc_bitrate,
pParam->rc_reaction_delay_factor,
pParam->rc_averaging_period, pParam->rc_buffer,
pParam->fbase * 1000 / pParam->fincr,
pParam->max_quantizer, pParam->min_quantizer);
}
init_timer();
return XVID_ERR_OK;
xvid_err_memory3:
#ifdef _DEBUG_PSNR
image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
#endif
image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
/* image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);*/
image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
/* image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);*/
xvid_err_memory2:
xvid_free(pEnc->current->mbs);
xvid_free(pEnc->reference->mbs);
xvid_err_memory1:
xvid_free(pEnc->current);
xvid_free(pEnc->reference);
xvid_free(pEnc);
pParam->handle = NULL;
return XVID_ERR_MEMORY;
}
/*****************************************************************************
* Encoder destruction
*
* This function destroy the entire encoder structure created by a previous
* successful encoder_create call.
*
* Returned values (for now only one returned value) :
* - XVID_ERR_OK - no errors
*
****************************************************************************/
int
encoder_destroy(Encoder * pEnc)
{
ENC_CHECK(pEnc);
/* All images, reference, current etc ... */
image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
/* image_destroy(&pEnc->vInterVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);*/
image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
/* image_destroy(&pEnc->vInterHVf, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);*/
#ifdef _DEBUG_PSNR
image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width,
pEnc->mbParam.edged_height);
#endif
/* Encoder structure */
xvid_free(pEnc->current->mbs);
xvid_free(pEnc->current);
xvid_free(pEnc->reference->mbs);
xvid_free(pEnc->reference);
xvid_free(pEnc);
return XVID_ERR_OK;
}
/*****************************************************************************
* "original" IP frame encoder entry point
*
* Returned values :
* - XVID_ERR_OK - no errors
****************************************************************************/
/*
int
encoder_encode(Encoder * pEnc,
XVID_ENC_FRAME * pFrame,
XVID_ENC_STATS * pResult)
*/
int
encoder_encode(Encoder * pEnc,/* point to global Encoder structure */
XVID_ENC_FRAME * pFrame/* point to global XVID_ENC_FRAME structure */
)
{
Bitstream bs;/* Bitstream structure */
uint32_t bits;/* bit streams length */
/* uint16_t write_vol_header = 0;*/
int head_vector=0;/* header information and vector encoding bits number */
int frametype;/* encoding frame type(I or P) */
int mad=0;/* use mad value to measure encoding complexity */
BOOL IsOverFlow;/* bit streams overflow flag */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -