【媒体流】libx264 将rgb24格式转换为h264

来源:互联网 发布:淘宝宝贝经常修改价格 编辑:程序博客网 时间:2024/06/07 05:34

简介

最近我在将自己的久笔记本放在家里做小型的远程监控,在网络传输视频时需要用到h264码流。然而我对h264只能说知道只知道它是一个视频编码格式,仅此而已。然后某度一下之后发现有开源的库可以直接使用。libx264就这样被我发现了。在其他博客中混迹了一段时间后发现,网上基本上是没有说使用libx264 将rgb24 数据格式转 h264的。基本上都是讲yuv420转的,说什么libx264只支持yuv420格式作为输入源,在这个我不想吐槽太多了。这篇博文主要是讲述如会将摄像头捕获回来的个图像数据转换为h264码流并保存到本地。然后可以用vlc查看。
当时我是看雷神的这篇博客踏入这神圣的殿堂的
雷霄骅 基于libx264(编码YUV为H.264)

本文框架

  • opencv 采集图像
  • libx264编码
  • vlc效果演示

opencv 采集图像

opencv 相信很多博友都应该知道。现在都可以说是烂大街了。现在我就直接使用它来作为我们采集图像的工具(可能有点大材小用了)。

// bolgLibx264.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <opencv/cv.h>#include <opencv/highgui.h>using namespace std;using namespace cv;#define WIDTH 640#define HEIGHT 480void testVideoCapture(void){    VideoCapture cap(0);    Mat frame;    if (cap.isOpened() == false)        cout << "can't not capture an usb camera from your computer!!!" << endl;    while (true)    {        cap >> frame;        if (frame.empty())            continue;        resize(frame, frame, Size(WIDTH, HEIGHT));        imshow("frame", frame);        waitKey(1);    }}int _tmain(int argc, _TCHAR* argv[]){    testVideoCapture();    return 0;}

这里给出的代码片段只是简单的使用opencv 采集pc机中默认摄像头并显示图像,代码中的resize是缩放函数,我这里是将图像分辨率规定为640*480了。下面的是上边代码片段的运行效果:这里写图片描述


libx264编码

在上面的采集的基础上添加编码程序,至于怎么添加libx264 可以参考【雷霄骅博客】在简介中我已经给出了。我这里就不废话了。直接上代码。

// bolgLibx264.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <opencv/cv.h>#include <opencv/highgui.h>#if defined ( __cplusplus)extern "C"{#include <stdint.h>#include "x264.h"};#else#include "x264.h"#endifusing namespace std;using namespace cv;#define WIDTH 640#define HEIGHT 480#define VENC_FPS 30typedef struct __X264_ENCODER__{    x264_t* m_pX264Handle;    x264_param_t* m_pX264Param;    x264_picture_t* m_pX264Pic_out;    x264_picture_t* m_pX264Pic_in;    x264_nal_t* m_pX264Nals;    int m_x264iNal;    FILE *m_x264Fp;}X264Encoder;void initX264Encoder(X264Encoder &x264Encoder,char *filePath){    x264Encoder.m_x264Fp = fopen(filePath, "wb");    x264Encoder.m_pX264Param = (x264_param_t *)malloc(sizeof(x264_param_t));    assert(x264Encoder.m_pX264Param);    x264_param_default(x264Encoder.m_pX264Param);    x264_param_default_preset(x264Encoder.m_pX264Param, "veryfast", "zerolatency");    x264_param_apply_profile(x264Encoder.m_pX264Param, "baseline");    x264Encoder.m_pX264Param->i_threads = X264_THREADS_AUTO;//X264_SYNC_LOOKAHEAD_AUTO; // 取空缓冲区继续使用不死锁的保证    // 视频选项    x264Encoder.m_pX264Param->i_width = WIDTH; // 要编码的图像宽度.    x264Encoder.m_pX264Param->i_height = HEIGHT; // 要编码的图像高度    // 帧率    x264Encoder.m_pX264Param->b_vfr_input = 0;//0时只使用fps控制帧率    int m_frameRate = VENC_FPS;    x264Encoder.m_pX264Param->i_fps_num = m_frameRate; // 帧率分子    x264Encoder.m_pX264Param->i_fps_den = 1; // 帧率分母    x264Encoder.m_pX264Param->i_timebase_den = x264Encoder.m_pX264Param->i_fps_num;    x264Encoder.m_pX264Param->i_timebase_num = x264Encoder.m_pX264Param->i_fps_den;    x264Encoder.m_pX264Param->b_intra_refresh = 0;    x264Encoder.m_pX264Param->b_annexb = 1;    //m_pX264Param->b_repeat_headers = 0;    x264Encoder.m_pX264Param->i_keyint_max = m_frameRate;    x264Encoder.m_pX264Param->i_csp = X264_CSP_BGR;//X264_CSP_I420;//     x264Encoder.m_pX264Param->i_log_level = X264_LOG_INFO;//X264_LOG_DEBUG;    x264Encoder.m_x264iNal = 0;    x264Encoder.m_pX264Nals = NULL;    x264Encoder.m_pX264Pic_in = (x264_picture_t *)malloc(sizeof(x264_picture_t));    if (x264Encoder.m_pX264Pic_in == NULL)        exit(1);    else        memset(x264Encoder.m_pX264Pic_in, 0, sizeof(x264_picture_t));    //x264_picture_alloc(m_pX264Pic_in, X264_CSP_I420, m_pX264Param->i_width, m_pX264Param->i_height);    x264_picture_alloc(x264Encoder.m_pX264Pic_in, X264_CSP_BGR, x264Encoder.m_pX264Param->i_width, x264Encoder.m_pX264Param->i_height);    x264Encoder.m_pX264Pic_in->i_type = X264_TYPE_AUTO;    x264Encoder.m_pX264Pic_out = (x264_picture_t *)malloc(sizeof(x264_picture_t));    if (x264Encoder.m_pX264Pic_out == NULL)        exit(1);    else        memset(x264Encoder.m_pX264Pic_out, 0, sizeof(x264_picture_t));    x264_picture_init(x264Encoder.m_pX264Pic_out);    x264Encoder.m_pX264Handle = x264_encoder_open(x264Encoder.m_pX264Param);    assert(x264Encoder.m_pX264Handle);}void convertFrameToX264Img(x264_image_t *x264InImg,Mat &frame){    //RGB方式    int srcSize = frame.rows*frame.cols;    x264InImg->plane[0] = frame.data;    x264InImg->plane[1] = frame.data + srcSize;    x264InImg->plane[2] = frame.data + srcSize;}void encoderImg(X264Encoder &x264Encoder,Mat &frame){    //转换图像格式    convertFrameToX264Img(&x264Encoder.m_pX264Pic_in->img,frame);    x264Encoder.m_pX264Pic_in->i_pts++;    int ret = x264_encoder_encode(x264Encoder.m_pX264Handle, &x264Encoder.m_pX264Nals, &x264Encoder.m_x264iNal, x264Encoder.m_pX264Pic_in, x264Encoder.m_pX264Pic_out);    if (ret< 0){        printf("Error.\n");        return;    }    for (int i = 0; i < x264Encoder.m_x264iNal; ++i)    {        fwrite(x264Encoder.m_pX264Nals[i].p_payload, 1, x264Encoder.m_pX264Nals[i].i_payload, x264Encoder.m_x264Fp);    }}void testVideoEncoder(void){    X264Encoder x264Encoder;    initX264Encoder(x264Encoder,"myCamera.h264");    VideoCapture cap(0);    Mat frame;    if (cap.isOpened() == false)        cout << "can't not capture an usb camera from your computer!!!" << endl;    while (true)    {        cap >> frame;        if (frame.empty())            continue;        resize(frame, frame, Size(WIDTH, HEIGHT));        encoderImg(x264Encoder, frame);        imshow("frame", frame);        waitKey(30);    }}int _tmain(int argc, _TCHAR* argv[]){    testVideoEncoder();    return 0;}

vlc演示

将代码产生的myCamera.h264 用vlc播放器打开即可播放
这里写图片描述

注:整个工程稍后上传至csdn下载中心。没有积分的可以留言联系我给你直接发过去。
源码下载链接