h264编码

//canok 20210804

#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <x264.h>

#define FAIL_IF_ERROR( cond, ... )\
do\
{\
    if( cond )\
    {\
        fprintf( stderr, __VA_ARGS__ );\
        goto fail;\
    }\
} while( 0 )


int64_t getNowUs(){
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec;
}

int main( int argc, char **argv )
{//https://www.cnblogs.com/wainiwann/p/5647521.html
    int width, height;
    x264_param_t param;
    x264_picture_t pic;
    x264_picture_t pic_out;
    x264_t *h;
    int i_frame = 0;
    int out_frame=0;
    int i_frame_size;
    x264_nal_t *nal;
    int i_nal;

    //FAIL_IF_ERROR( !(argc > 1), "Example usage: example 352x288 <input.yuv >output.h264\n" );
    if(argc !=3){
        printf("usage: my_encoder WxH inputfile.yuv\n");
        return -1;
    }

    FILE *fp_in=fopen(argv[2],"r");
    if(fp_in==NULL){
        printf("[%s%d] fopen err:%s\n",__FUNCTION__,__LINE__,argv[2]);
        return -1;
    }

    FILE *fp_out=fopen("out.h264","w+");
    if(fp_out==NULL){
        printf("[%s%d] fopen err:out.h264 \n",__FUNCTION__,__LINE__);
        return -1;
    }

    FAIL_IF_ERROR( 2 != sscanf( argv[1], "%dx%d", &width, &height ), "resolution not specified or incorrect\n" );



    /* Get default params for preset/tuning */
    #if 0
    if( x264_param_default_preset( &param, "medium", NULL ) < 0 )
        goto fail;
    #else
    //设置到最快
    //具体参数可以看base.c::param_apply_preset
    //zerolatency不延迟这个设置之后,就进一帧出一帧了,不延迟
    //char speed[][16]={"ultrafast","superfast","veryfast","faster","fast","medium","slow","slower","veryslow","placebo"};
    if( x264_param_default_preset( &param, "ultrafast", "zerolatency" ) < 0 )
    //if( x264_param_default_preset( &param, "ultrafast", NULL ) < 0 )
        goto fail;
    #endif
    /* Configure non-default params */
    param.i_bitdepth = 8;
    param.i_csp = X264_CSP_I420;//颜色空间
    param.i_width  = width;
    param.i_height = height;
    param.b_vfr_input = 0; //设置为1将控制时间戳?
    param.b_repeat_headers = 1; //在每一个I帧前面加上sps pps
    param.b_annexb = 1;//每一个帧携带启始码00 00 00 01,如果设置为0,则不添加00 00 00 01,而是存储这一帧的数据大小值。(占4个字节)

    param.i_bframe =0; // 不使用B帧/* how many b-frame between 2 references pictures */

    param.i_keyint_min = 25;
    param.i_keyint_max = 35; //gop

//https://blog.csdn.net/bingqingsuimeng/article/details/79197901
    param.rc.b_mb_tree = 0;//实时编码是强烈建议为0

    //f_rf_constant 设置 33 数据速率 972kbps  图像质量还行,设置20 数据速率 2501kbps ,设置30 数据速率1520kbps
    param.rc.f_rf_constant = 25; 
    param.rc.f_rf_constant_max = 45;

    /* Apply profile restrictions. */
    if( x264_param_apply_profile( &param, "high" ) < 0 )
        goto fail;

    if( x264_picture_alloc( &pic, param.i_csp, param.i_width, param.i_height ) < 0 )
        goto fail;
#undef fail
#define fail fail2

    h = x264_encoder_open( &param );
    if( !h )
        goto fail;
#undef fail
#define fail fail3

    int luma_size = width * height;
    int chroma_size = luma_size / 4;
    /* Encode frames */
    for( ;; i_frame++ )
    {
        /* Read input frame */
        if( fread( pic.img.plane[0], 1, luma_size, fp_in ) != (unsigned)luma_size )
            break;
        if( fread( pic.img.plane[1], 1, chroma_size, fp_in ) != (unsigned)chroma_size )
            break;
        if( fread( pic.img.plane[2], 1, chroma_size, fp_in ) != (unsigned)chroma_size )
            break;

        pic.i_pts = i_frame;
        int64_t t1=getNowUs();
        
        printf("[%s%d]in:%d %ld\n",__FUNCTION__,__LINE__,i_frame, t1);
        i_frame_size = x264_encoder_encode( h, &nal, &i_nal, &pic, &pic_out );
        if( i_frame_size < 0 )
            goto fail;
        else if( i_frame_size )
        {
            int64_t t2=getNowUs();
            printf("[%s%d]out:%d %ld\n",__FUNCTION__,__LINE__,out_frame, t2);
            //SLICE_TYPE_P SLICE_TYPE_B SLICE_TYPE_I 
            //nal->i_type nal_unit_type_e
            /*enum sei_payload_type_e
            {
                SEI_BUFFERING_PERIOD       = 0,
                SEI_PIC_TIMING             = 1,
                SEI_PAN_SCAN_RECT          = 2,
                SEI_FILLER                 = 3,
                SEI_USER_DATA_REGISTERED   = 4,
                SEI_USER_DATA_UNREGISTERED = 5,
                SEI_RECOVERY_POINT         = 6,
                SEI_DEC_REF_PIC_MARKING    = 7,
                SEI_FRAME_PACKING          = 45,
                SEI_ALTERNATIVE_TRANSFER   = 147,
            };*/
            printf("[%s%d]in:%d---%dout,taketimes:%ld,nal->i_type:%d\n",__FUNCTION__,__LINE__,i_frame,out_frame,t2-t1,nal->i_type);
            out_frame++;
            if( !fwrite( nal->p_payload, i_frame_size, 1, fp_out ) )
                goto fail;
        }
    }
    /* Flush delayed frames */
    //设置 "zerolatency" 之后就不会有delayed_frames了。
    while( x264_encoder_delayed_frames( h ) )
    {
        i_frame_size = x264_encoder_encode( h, &nal, &i_nal, NULL, &pic_out );
        if( i_frame_size < 0 )
            goto fail;
        else if( i_frame_size )
        {
            int64_t t2=getNowUs();
            printf("[%s%d]out-delayframe:%d %ld\n",__FUNCTION__,__LINE__,out_frame, t2);
            out_frame++;
            if( !fwrite( nal->p_payload, i_frame_size, 1, fp_out ) )
                goto fail;
        }
    }

    x264_encoder_close( h );
    x264_picture_clean( &pic );
    return 0;

#undef fail
fail3:
    x264_encoder_close( h );
fail2:
    x264_picture_clean( &pic );
fail:
    fclose(fp_in);
    fclose(fp_out);
    return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屁小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值