使用X264库进行H264编码

    //关闭live555推流服务
    system("killall testOnDemandRTSPServer");
    //重启live555推流服务
    sleep(3);
    system("./testOnDemandRTSPServer &");
    //------------------------------------------------------------------------------------------------------
    cv::Mat BasePic = cv::imread("./test.jpg");
    cv::Mat inputPic;
    cv::resize(BasePic, BasePic, cv::Size(1920, 1080));
    //使用YUV420编码
    cv::cvtColor(BasePic, BasePic, cv::COLOR_BGR2YUV_I420);
    //创建fifo
    ::unlink("demo.264");
    ::mkfifo("demo.264", O_CREAT | O_EXCL | 777);
    //打开fifo
    int fp_dst = ::open("demo.264", O_WRONLY);
    if(fp_dst == NULL)
    {
        ::close(fp_dst);
        return;
    }
    //H264编码设置
    int video_width = 1920;
    int video_height = 1080;
    int res = 0;
    //压缩编码前的图像
    x264_picture_t pic;
    x264_picture_t pic_out;
    //
    x264_t *h;
    int i_frame = 0;
    int i_frame_size = 0;
    //压缩编码后的码流数据
    x264_nal_t *nal;
    int i_nal;
    x264_param_t param;
    res = x264_param_default_preset(&param, "veryfast", NULL);
    param.i_bitdepth = 8;//编码位数
    param.i_csp = X264_CSP_I420;//编码制式
    param.rc.i_qp_min = 36;//编码质量:越小,视频质量损失越小
    param.rc.i_qp_max = 40;
    param.rc.i_qp_step = 2;
    param.i_width = video_width;//分辨率
    param.i_height = video_height;
    param.i_fps_den = 1;//帧率
    param.i_fps_num = 30;
    param.i_keyint_max = 4;//设置IDR关键帧间隔
    param.i_keyint_min = 1;
    param.b_vfr_input = 0;//固定帧率
    param.b_repeat_headers = 1;//在每个关键帧前放置SPS/PPS
    param.b_annexb = 1;//在NAL单元前放置起始码
    res = x264_param_apply_profile(&param, "baseline");
    res = x264_picture_alloc(&pic, param.i_csp, param.i_width, param.i_height);
    //打开编码器
    h = x264_encoder_open(&param);
    if(h == 0)
    {
        return;
    }
    //输出头信息
    i_frame_size = x264_encoder_headers(h, &nal, &i_nal);
    if(i_frame_size < 0)
    {
        return;
    }
    else if(i_frame_size)
    {
        if(!::write(fp_dst, nal->p_payload, i_frame_size))
        {
            return;
        }
    }
    //对视频帧进行编码
    unsigned int luma_size = video_width * video_height;
    unsigned int chroma_size = luma_size / 4;
    for(;;i_frame++)
    {
        //读取输入帧YUV420
        inputPic = BasePic.clone();
        //绘制帧号
        int id = i_frame / 30;
        cv::String strFrameId;
        QString idStr = QString("%1").arg(id);
        strFrameId = idStr.toStdString();
        cv::putText(inputPic, strFrameId, cv::Point(960,500), cv::HersheyFonts::FONT_ITALIC, 10, cv::Scalar(255,0,0), 3);
        //
        memcpy(pic.img.plane[0], inputPic.data, luma_size);
        memcpy(pic.img.plane[1], inputPic.data + luma_size, chroma_size);
        memcpy(pic.img.plane[2], inputPic.data + luma_size + chroma_size, chroma_size);
        //
        pic.i_pts = i_frame;
        i_frame_size = x264_encoder_encode(h, &nal, &i_nal, &pic, &pic_out);
        if(i_frame_size < 0)
        {
            break;
        }
        else if(i_frame_size)
        {
            try{
                ::write(fp_dst, nal->p_payload, i_frame_size);
            }
            catch(std::exception exception)
            {
                std::cout << exception.what() << std::endl;
            }
        }
        if(i_frame == (30 * 60000))
        {
            break;
        }
    }
    //关闭编码器
    x264_encoder_close(h);
    x264_picture_clean(&pic);
    ::close(fp_dst);

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值