X264编码(2)

来源:互联网 发布:公司淘宝培训协议书 编辑:程序博客网 时间:2024/06/06 16:26

    上一篇我们介绍了X264的编码,但是只能对本地文件编码,这里讨论怎么实时的读取摄像头文件并编码。

    利用opencv实时读取摄像头,可以参考博客:点击打开链接。这里不做过多介绍。

    至于编码流程,和上篇一样,没有改变。我们了解下X264编码器怎么直接读取摄像头的一帧图像就行。


    opencv打开摄像头时,一帧一帧的播放,每一帧都由frame指定:capture >> frame

    当然这里还有问题,X264对输入的要求是YUV格式,但是经过opencv采集后一帧frame是RGB格式,所以在编码之前我们要先将格式转换下,利用opencv自带的函数cvtColor。

    cv::cvtColor(frame, yuvImg, CV_BGR2YUV_I420)

    函数原型:

    void cvCvtColor(const CvArr* src,CvArr* dst,int code)         src:输入; dst:输出; code:转换的模式;

    转换后的数据保存在yuvImg中,并通过fwrite函数写出,这里写出的数据是YUV格式,直接将其送到X264编码器的接口处就能开始编码。


    最后给出完整代码:

#include #include #include #include #include "stdafx.h"#include "stdint.h"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"extern "C"{#include "x264.h"#include "x264_config.h"};using namespace cv;using namespace std;int MyYuvtoH264(int width, int height, string filename){int fps = 25;size_t yuv_size = width * height * 3 / 2;x264_t *encoder;x264_picture_t pic_in, pic_out;uint8_t *yuv_buffer;x264_param_t param;x264_param_default_preset(¶m, "veryfast", "zerolatency");param.i_threads = 1;param.i_width = width;param.i_height = height;param.i_fps_num = fps;param.i_fps_den = 1;param.i_keyint_max = 25;param.b_intra_refresh = 1;param.b_annexb = 1;x264_param_apply_profile(¶m, "baseline");encoder = x264_encoder_open(¶m);x264_picture_alloc(&pic_in, X264_CSP_I420, width, height);yuv_buffer = (uint8_t*)malloc(yuv_size);pic_in.img.plane[0] = yuv_buffer;pic_in.img.plane[1] = pic_in.img.plane[0] + width * height;pic_in.img.plane[2] = pic_in.img.plane[1] + width * height / 4;int64_t i_pts = 0;x264_nal_t *nals;int nnal;FILE *inf = fopen(filename.c_str(), "rb");FILE *outf = fopen("test.h264", "wb");if (NULL == inf){return -1;}while (fread(yuv_buffer, 1, yuv_size, inf) > 0){pic_in.i_pts = i_pts++;x264_encoder_encode(encoder, &nals, &nnal, &pic_in, &pic_out);x264_nal_t *nal;for (nal = nals; nal < nals + nnal; nal++){fwrite(nal->p_payload, 1, nal->i_payload, outf);}}x264_encoder_close(encoder);fclose(inf);fclose(outf);free(yuv_buffer);return 0;}int main(int argc, char* argv[]){VideoCapture capture(0);if (!capture.isOpened())  {cout << "Cannot open the video cam" << endl;return -1;}int w = capture.get(CV_CAP_PROP_FRAME_WIDTH);int h = capture.get(CV_CAP_PROP_FRAME_HEIGHT);int yuv_bufLen = w * h * 3 / 2;unsigned char* pYuvBuf = new unsigned char[yuv_bufLen];FILE* pFileOut = fopen("result.yuv", "w+");if (!pFileOut){printf("pFileOut open error \n");system("pause");exit(-1);}printf("pFileOut open ok \n");cout << "Frame size : " << w << " x " << h << endl;namedWindow("opencamera", CV_WINDOW_AUTOSIZE);while (1){Mat frame;capture >> frame;imshow("opencamera", frame); if (waitKey(30) == 27) break;cv::Mat yuvImg;cv::cvtColor(frame, yuvImg, CV_BGR2YUV_I420);memcpy(pYuvBuf, yuvImg.data, yuv_bufLen*sizeof(unsigned char));fwrite(pYuvBuf, yuv_bufLen*sizeof(unsigned char), 1, pFileOut);MyYuvtoH264(w, h, "result.yuv");}waitKey(0);fclose(pFileOut);delete[] pYuvBuf;Sleep(100);return 0;}

    运行效果图:
   
    后面的命令行工具里可以看出正在进行编码。

    完整工程下载:点击打开链接
 
  


原创粉丝点击