zc301P摄像头opencv录制,libx264编码为H264格式文件(test.264)

/*
* camera_yuv_x264.cpp
*/

#include <stdint.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define CLEAR(x) (memset((&x),0,sizeof(x)))
#define IMAGE_WIDTH   320
#define IMAGE_HEIGHT  240
#define ENCODER_PRESET "veryfast"
#define widthStep 960
//widthStep为图像宽度的3倍
/*配置参数
* 使用默认参数,在这里使用了zerolatency的选项,使用这个选项之后,就不会有
* delayed_frames,如果你使用不是这个的话,还需要在编码完成之后得到缓存的
* 编码帧
*/
#define ENCODER_TUNE   "zerolatency"
#define ENCODER_PROFILE  "baseline"
#define ENCODER_COLORSPACE X264_CSP_I420

extern "C"
{

#include <x264.h>

    typedef struct my_x264_encoder{
        x264_param_t  * x264_parameter;
        char parameter_preset[20];
        char parameter_tune[20];
        char parameter_profile[20];
        x264_t  * x264_encoder;
        x264_picture_t * yuv420p_picture;
        long colorspace;
        unsigned char *yuv;
        x264_nal_t * nal;
    } my_x264_encoder;

}


//global variable
char *write_filename = "test.264";
int ii = 500; //frames_total,这里设置你需要录制多少帧
IplImage * img;
CvCapture * cap;
unsigned char * RGB1;

//在RGB2YUV.cpp中
void Convert(unsigned char *RGB, unsigned char *YUV, unsigned int width, unsigned int height);

void getyuv(unsigned char *yuv)
{
    img = cvQueryFrame(cap);
    for (int i = 0; i < IMAGE_HEIGHT; i++)
    {
        for (int j = 0; j < IMAGE_WIDTH; j++)
        {
            RGB1[(i*IMAGE_WIDTH + j) * 3] = img->imageData[i * widthStep + j * 3 + 2];;
            RGB1[(i*IMAGE_WIDTH + j) * 3 + 1] = img->imageData[i * widthStep + j * 3 + 1];
            RGB1[(i*IMAGE_WIDTH + j) * 3 + 2] = img->imageData[i * widthStep + j * 3];
        }
    }
    Convert(RGB1, yuv, IMAGE_WIDTH, IMAGE_HEIGHT);
}


int main(int argc, char **argv)
{
    


    int ret;
    
    my_x264_encoder * encoder = (my_x264_encoder *)malloc(sizeof(my_x264_encoder));
    if (!encoder){
        printf("cannot malloc my_x264_encoder !\n");
        exit(EXIT_FAILURE);
    }
    CLEAR(*encoder);
    
    //摄像头初始化
    cap = cvCreateCameraCapture(0);
    cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_WIDTH, IMAGE_WIDTH);
    cvSetCaptureProperty(cap, CV_CAP_PROP_FRAME_HEIGHT, IMAGE_HEIGHT);

    //分配RGB空间,用于提取IplImage中的image_data
    RGB1 = (unsigned char *)malloc(IMAGE_HEIGHT * IMAGE_WIDTH * 3);

    /****************************************************************************
    * encoder结构体初始化
    ****************************************************************************/
    strcpy(encoder->parameter_preset, ENCODER_PRESET);
    strcpy(encoder->parameter_tune, ENCODER_TUNE);

    encoder->x264_parameter = (x264_param_t *)malloc(sizeof(x264_param_t));
    if (!encoder->x264_parameter){
        printf("malloc x264_parameter error!\n");
        exit(EXIT_FAILURE);
    }

    /*初始化编码器*/
    CLEAR(*(encoder->x264_parameter));
    x264_param_default(encoder->x264_parameter);

    if ((ret = x264_param_default_preset(encoder->x264_parameter, encoder->parameter_preset, encoder->parameter_tune))<0){
        printf("x264_param_default_preset error!\n");
        exit(EXIT_FAILURE);
    }

    /*cpuFlags 去空缓冲区继续使用不死锁保证*/
    encoder->x264_parameter->i_threads = X264_SYNC_LOOKAHEAD_AUTO;
    /*视频选项*/
    encoder->x264_parameter->i_width = IMAGE_WIDTH;//要编码的图像的宽度
    encoder->x264_parameter->i_height = IMAGE_HEIGHT;//要编码的图像的高度
    encoder->x264_parameter->i_frame_total = 0;//要编码的总帧数,不知道用0
    encoder->x264_parameter->i_keyint_max = 10;//一般为i_fps_num的一倍或两倍,视频文件总时间=总帧数/该值,time = ii / i_keyint_max;
    /*流参数*/
    encoder->x264_parameter->i_bframe = 5;
    encoder->x264_parameter->b_open_gop = 0;
    encoder->x264_parameter->i_bframe_pyramid = 0;
    encoder->x264_parameter->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;

    /*log参数,不需要打印编码信息时直接注释掉*/
    encoder->x264_parameter->i_log_level = X264_LOG_DEBUG;

    encoder->x264_parameter->i_fps_num = 10;//码率分子
    encoder->x264_parameter->i_fps_den = 1;//码率分母
    
    encoder->x264_parameter->b_intra_refresh = 1;
    encoder->x264_parameter->b_annexb = 1;
    

    strcpy(encoder->parameter_profile, ENCODER_PROFILE);
    if ((ret = x264_param_apply_profile(encoder->x264_parameter, encoder->parameter_profile))<0){
        printf("x264_param_apply_profile error!\n");
        exit(EXIT_FAILURE);
    }
    /*打开编码器*/
    encoder->x264_encoder = x264_encoder_open(encoder->x264_parameter);
    encoder->colorspace = ENCODER_COLORSPACE;

    /*初始化pic*/
    encoder->yuv420p_picture = (x264_picture_t *)malloc(sizeof(x264_picture_t));
    if (!encoder->yuv420p_picture){
        printf("malloc encoder->yuv420p_picture error!\n");
        exit(EXIT_FAILURE);
    }
    if ((ret = x264_picture_alloc(encoder->yuv420p_picture, encoder->colorspace, IMAGE_WIDTH, IMAGE_HEIGHT))<0){
        printf("ret=%d\n", ret);
        printf("x264_picture_alloc error!\n");
        exit(EXIT_FAILURE);
    }

    encoder->yuv420p_picture->img.i_csp = encoder->colorspace;
    encoder->yuv420p_picture->img.i_plane = 3;
    encoder->yuv420p_picture->i_type = X264_TYPE_AUTO;

    /*申请YUV buffer*/
    encoder->yuv = (uint8_t *)malloc(IMAGE_WIDTH*IMAGE_HEIGHT * 3 / 2);
    if (!encoder->yuv){
        printf("malloc yuv error!\n");
        exit(EXIT_FAILURE);
    }
    CLEAR(*(encoder->yuv));
    encoder->yuv420p_picture->img.plane[0] = encoder->yuv;
    encoder->yuv420p_picture->img.plane[1] = encoder->yuv + IMAGE_WIDTH*IMAGE_HEIGHT;
    encoder->yuv420p_picture->img.plane[2] = encoder->yuv + IMAGE_WIDTH*IMAGE_HEIGHT + IMAGE_WIDTH*IMAGE_HEIGHT / 4;
    
    encoder->nal = (x264_nal_t *)calloc(2,sizeof(x264_nal_t));//一般一帧分为两个nal,不行的话就改3-8
    if (!encoder->nal){
        printf("malloc x264_nal_t error!\n");
        exit(EXIT_FAILURE);
    }
    CLEAR(*(encoder->nal));
    //////////////////////////////////////////////////////////////////////////////////
    /************************* init finished ****************************************/

    int fd_write;
    if ((fd_write = open(write_filename, O_WRONLY  | O_CREAT, 0777))<0){     //| O_APPEND
        printf("cannot open output file!\n");
        exit(EXIT_FAILURE);
    }
    int n_nal = 0;
    x264_picture_t pic_out;
    x264_nal_t *my_nal;
    
    /*Encode*/
    while (ii--)
    {
        getyuv(encoder->yuv);
        encoder->yuv420p_picture->i_pts++;
        if ((ret = x264_encoder_encode(encoder->x264_encoder, &encoder->nal, &n_nal, encoder->yuv420p_picture, &pic_out))<0){
            printf("x264_encoder_encode error!\n");
            exit(EXIT_FAILURE);
        }
        for (my_nal = encoder->nal; my_nal<encoder->nal + n_nal; ++my_nal){
            write(fd_write, my_nal->p_payload, my_nal->i_payload);
        }
    }

    free(encoder->yuv);
    free(encoder->yuv420p_picture);
    free(encoder->x264_parameter);
    x264_encoder_close(encoder->x264_encoder);
    free(encoder);
    close(fd_read);
    close(fd_write);

    return 0;
}

需要用到我之前的文章中的 RGB2YUV.cpp (不含getyuv函数)文件。

编译:g++ RGB2YUV.cpp camera_yuv_x264.cpp -lopencv_highgui -lopencv_videoio -lx264 -o camera_yuv_x264

 

posted @ 2015-08-04 15:33  Chian_Gank  阅读(1742)  评论(0编辑  收藏  举报