⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encoder.c

📁 H.264编码器
💻 C
📖 第 1 页 / 共 3 页
字号:
        h->frame_next[i]    = NULL;
        h->frame_unused[i]  = NULL;
    }
    
    h->frame_next[X264_BFRAME_MAX]  = NULL;
    h->frame_unused[X264_BFRAME_MAX]= NULL;

    for( i = 0; i < h->param.i_bframe+1; i++ )
    {
        h->frame_unused[i] = x264_frame_new( h );
    }

    h->mb = x264_macroblocks_new( h->sps->i_mb_width, h->sps->i_mb_height );

    // reference frame (2 for B frame) and current one
    for( i = 0; i < h->param.i_frame_reference+2; i++ )
	{
        h->freference[i] = x264_frame_new( h );
    }
    
	h->fdec     = h->freference[0];
    h->i_ref0 = 0;
    h->i_ref1 = 0;

    /* init cabac adaptive model */
    x264_cabac_model_init( &h->cabac );

    /* init predict_XxX */
    x264_predict_16x16_init( h->predict_16x16 );
    x264_predict_8x8_init( h->predict_8x8 );
    x264_predict_4x4_init( h->predict_4x4 );

    x264_pixel_init( &h->pixf );
    x264_dct_init( &h->dctf );

    x264_mc_init( h->mc );

    x264_me_init( me );
    h->me = me[h->param.i_me];

    /* rate control */
    h->rc = x264_ratecontrol_new( &h->param );

    return h;
}

/****************************************************************************
 * x264_nal_encode:
 ****************************************************************************/
int x264_nal_encode( unsigned char *p_data, int *pi_data, int b_annexeb, x264_nal_t *nal )
{
    uint8_t *dst = p_data;
    uint8_t *src = nal->p_payload;
    uint8_t *end = &nal->p_payload[nal->i_payload];

    int i_count = 0;

    /* FIXME this code doesn't check overflow */

    if( b_annexeb )
    {
        /* long nal start code (we always use long ones)*/
        *dst++ = 0x00;
        *dst++ = 0x00;
        *dst++ = 0x00;
        *dst++ = 0x01;
    }

    /* nal header */
    *dst++ = ( 0x00 << 7 ) | ( nal->i_ref_idc << 5 ) | nal->i_type;

    while( src < end )
    {
        if( i_count == 2 && *src <= 0x03 )
        {
            *dst++ = 0x03;
            i_count = 0;
        }
        if( *src == 0 )
        {
            i_count++;
        }
        else
        {
            i_count = 0;
        }
        *dst++ = *src++;
    }
    *pi_data = dst - (uint8_t*)p_data;

    return *pi_data;
}

/* internal usage */
static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
{
    x264_nal_t *nal = &h->nal[h->i_nal];

    nal->i_ref_idc = i_ref_idc;
    nal->i_type    = i_type;

    bs_align_0( &h->bs );   /* not needed */

    nal->i_payload= 0;
    nal->p_payload= &h->p_bitstream[bs_pos( &h->bs) / 8];
}

static void x264_nal_end( x264_t *h )
{
    x264_nal_t *nal = &h->nal[h->i_nal];

    bs_align_0( &h->bs );   /* not needed */

    nal->i_payload = &h->p_bitstream[bs_pos( &h->bs) / 8] - nal->p_payload;

    h->i_nal++;
}



/****************************************************************************
 * x264_encoder_headers:
 ****************************************************************************/
int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal)
{
    /* init bitstream context */
    h->i_nal = 0;
    bs_init( &h->bs, h->p_bitstream, h->i_bitstream );

    /* Put SPS and PPS */
    if( h->i_frame == 0 )
    {
        /* generate sequence parameters */
        x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
        x264_sps_write( &h->bs, h->sps );
        x264_nal_end( h );

        /* generate picture parameters */
        x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
        x264_pps_write( &h->bs, h->pps );
        x264_nal_end( h );
    }
    /* now set output*/
    *pi_nal = h->i_nal;
    *pp_nal = &h->nal[0];

    return 0;
}


static void x264_encoder_frame_put( x264_frame_t *buffer[X264_BFRAME_MAX], x264_frame_t *frame )
{
    int i;

    /* put the frame in buffer */
    for( i = 0; buffer[i] != NULL; i++ )
    {
        if( i >= X264_BFRAME_MAX )
        {
            fprintf( stderr, "not enough room\n" );
            return;
        }
    }
    buffer[i] = frame;
}
static x264_frame_t *x264_encoder_frame_put_from_picture( x264_t *h, x264_frame_t *buffer[X264_BFRAME_MAX], x264_picture_t *picture )
{
    int i;
    x264_frame_t *frame;

    /* get an unused bframe */
    frame = h->frame_unused[0];
    for( i = 0; i < X264_BFRAME_MAX; i++ )
    {
        h->frame_unused[i] = h->frame_unused[i+1];
    }
    h->frame_unused[X264_BFRAME_MAX] = NULL;

    /* copy the picture in it */
    x264_frame_copy_picture( frame, picture );

    /* put the frame in buffer */
    x264_encoder_frame_put( buffer, frame );

    buffer[i] = frame;
    return frame;
}

static x264_frame_t *x264_encoder_frame_get( x264_frame_t *buffer[X264_BFRAME_MAX])
{
    int i;
    x264_frame_t *frame = buffer[0];

    for( i = 0; i < X264_BFRAME_MAX-1; i++ )
    {
        buffer[i] = buffer[i+1];
    }
    buffer[X264_BFRAME_MAX-1] = NULL;

    return frame;
}

static int64_t i_mtime_analyse = 0;
static int64_t i_mtime_encode = 0;
static int64_t i_mtime_write = 0;
static int64_t i_mtime_filter = 0;
#define TIMER_START( d ) \
    { \
        int64_t d##start = x264_mdate();

#define TIMER_STOP( d ) \
        d += x264_mdate() - d##start;\
    }

/****************************************************************************
 * x264_encoder_encode:
 *  XXX: i_poc   : is the poc of the current given picture
 *       i_frame : is the number of the frame being coded
 *  ex:  type frame poc
 *       I      0   2*0
 *       P      1   2*3
 *       B      2   2*1
 *       B      3   2*2
 *       P      4   2*6
 *       B      5   2*4
 *       B      6   2*5
 ****************************************************************************/

//static x264_frame_t * recon_temp; 

int     x264_encoder_encode( x264_t *h,
                             x264_nal_t **pp_nal, int *pi_nal,
                             x264_picture_t *pic)
{
    x264_picture_t picture_tmp;

    x264_frame_t   *frame_psnr = h->fdec; /* just to kept the current decoded frame for psnr calculation */
    int     i_nal_type;
    int     i_nal_ref_idc;
    int     i_slice_type;

    int     mb_xy;

    int i;
    int i_skip;

    int b_ok;

    float psnr_y, psnr_u, psnr_v;

    /* no data out */
    *pp_nal = NULL;
    *pi_nal = 0;

    /* ------------------- Select slice type and frame --------------------- */
    if( h->i_frame % (h->param.i_iframe * h->param.i_idrframe) == 0 )
    {
        i_nal_type    = NAL_SLICE_IDR;
        i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
        i_slice_type = SLICE_TYPE_I;

        /* we encode the given frame */
        h->picture    = pic;

        /* null poc */
        h->i_poc       = 0;
        h->fdec->i_poc = 0;

        /* null frame */
        h->i_frame_num = 0;

        /* reset ref pictures */
        for( i = 1; i < h->param.i_frame_reference+2; i++ )
        {
            h->freference[i]->i_poc = -1;
        }
        h->freference[0]->i_poc = 0;
    }
    else
    {
        /* TODO detect scene changes and switch to I slice */

        if( h->param.i_bframe > 0 )
        {
            x264_frame_t *frame;

            // TODO avoid always doing x264_encoder_frame_put_from_picture */
            // TODO implement adaptive B frame patern (not fixed one)*/

            // put the current picture in frame_next */
            frame = x264_encoder_frame_put_from_picture( h, h->frame_next, pic );
            frame->i_poc = h->i_poc;

            // get the frame to be encoded */
            if( h->bframe_current[0] )
            {
                frame = x264_encoder_frame_get( h->bframe_current );
                i_slice_type = SLICE_TYPE_B;
            }
            else if( h->frame_next[h->param.i_bframe] == NULL )
            {
                // not enough b-frame yet */
                frame = NULL;
                i_slice_type = -1;
            }
            else
            {
                int i_mod = h->i_frame % h->param.i_iframe;

                if( i_mod == 0 )
                {
                    i_slice_type = SLICE_TYPE_I;
                    frame = x264_encoder_frame_get( h->frame_next );
                }
                else
                {
                    int i;

                    for( i = 0; i < h->param.i_bframe; i++ )
                    {
                        h->bframe_current[i] = x264_encoder_frame_get( h->frame_next );
                    }
                    frame = x264_encoder_frame_get( h->frame_next );

                    i_slice_type = SLICE_TYPE_P;
                }
            }

            if( frame )
            {
                h->picture = &picture_tmp;
                for( i = 0; i < frame->i_plane; i++ )
                {
                    h->picture->i_stride[i] = frame->i_stride[i];
                    h->picture->plane[i] = frame->plane[i];
                }
                h->fdec->i_poc = frame->i_poc;

                x264_encoder_frame_put( h->frame_unused, frame );   /* it's ok to do it now */
            }
            else
            {
                h->picture = NULL;
            }
        }
        else
        {
            i_slice_type = h->i_frame % h->param.i_iframe == 0 ? SLICE_TYPE_I : SLICE_TYPE_P;

            /* we encode the given frame */
            h->picture     = pic;
            h->fdec->i_poc = h->i_poc;  /* low delay */
        }

        i_nal_type    = NAL_SLICE;
        if( i_slice_type == SLICE_TYPE_I || i_slice_type == SLICE_TYPE_P )
        {
            i_nal_ref_idc = NAL_PRIORITY_HIGH;  /* Not completely true but for now it is (as all I/P are kept as ref)*/
        }
        else /* if( i_slice_type == SLICE_TYPE_B ) */
        {
            i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;
        }
    }

    /* increase poc */
    h->i_poc += 2;

    if( h->picture == NULL )
    {
        /* waiting for filling bframe buffer */
        return 0;
    }

    /* increase frame num but only once for B frame */
    if( i_slice_type != SLICE_TYPE_B || h->sh.i_type != SLICE_TYPE_B )
    {
        h->i_frame_num++;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -