h.265编码库x265实例 | 迟思堂工作室
A-A+

h.265编码库x265实例

2015-09-14 12:59 业余研究 暂无评论 阅读 1,831 次

x265是一个开源的H.265编码库。API接口方面与x264很相像。本文介绍其在x86 linux及windows 7的编译方法,并给出实例。

一、编译

1、Linux平台

x265编译需要使用到yasm,到下载,最新版本为1.3.1。编译命令如下:

# ./configure;make;make install

x265库下载:,最新版本为1.7。

解压后,进入源码目录的build目录,选择linux。

# cd x265_1.7/build/linux
# ./make-Makefiles.bash

配置如下:

BIN_INSTALL_DIR                  /home/latelee/bin/x265-1.7
CHECKED_BUILD                    OFF
CMAKE_BUILD_TYPE                 Release
CMAKE_INSTALL_PREFIX             /home/latelee/bin/x265-1.7
DETAILED_CU_STATS                OFF
ENABLE_AGGRESSIVE_CHECKS         OFF
ENABLE_ASSEMBLY                  ON
ENABLE_CLI                       ON
ENABLE_PIC                       OFF
ENABLE_PPA                       OFF
ENABLE_SHARED                    OFF  # 不要动态库
ENABLE_TESTS                     OFF
ENABLE_VTUNE                     OFF

ENABLE_SHARED: Build shared library
Press [enter] to edit option                                                  CMake Version 3.3.1
Press [c] to configure
Press [h] for help           Press [q] to quit without generating
Press [t] to toggle advanced mode (Currently Off)

按c配置,再按g保存并退出。

2、Windows平台

0、安装cmake的windows版本,地址:。在安装过程要记得添加cmake到PATH。
1、进入build目录,根据编译器版本选择不同的工程目录,比如64bit的VS2010,就进入vc10-x86_64目录。双击:build-all.bat。
2、之后出现配置界面时,点击configure,再点击generate,然后关闭窗口。其它不同做。
3、等待cmd窗口编译完成,完成后会自动关闭。
4、在Debug或Release目录找到h265编码器x265.exe,另外还有dll和lib文件。头文件要到源码中找。

注:编译Windows平台,纯粹是为了得到x265,exe文件。

二、实例

下面给出使用的示例。

/**
x265库编码要使用以下库
-lpthread -ldl

ffprobe信息:
Input #0, hevc, from 'test.h265':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: hevc (Main), yuv420p(tv), 176x144, 25 fps, 25 tbr, 1200k
 tbn, 25 tbc
*/

#include <stdio.h>
#include <stdlib.h>

#include "x265.h"

int x265_encode(const char* infile, int width, int height, int type, const char* outfile)
{
    FILE *fp_src = NULL;
    FILE *fp_dst = NULL;
    unsigned int luma_size = 0;
    unsigned int chroma_size = 0;
    //int buff_size = 0;
    char *buff = NULL;
    uint32_t i_nal=0;
    int i_frame=0;
    int ret = 0;

    x265_param param;
    x265_nal *nal = NULL;
    x265_encoder *handle = NULL;
    x265_picture *pic_in = NULL;

    int csp = type; // X265_CSP_I420;

    fp_src = fopen(infile, "rb");
    fp_dst = fopen(outfile, "wb");
    if(fp_src==NULL || fp_dst==NULL)
    {
        perror("Error open yuv files:");
        return -1;
    }

    x265_param_default(?m);
    param.bRepeatHeaders = 1;//write sps,pps before keyframe
    param.internalCsp = csp;
    param.sourceWidth = width;
    param.sourceHeight = height;
    param.fpsNum = 25; // 帧率
    param.fpsDenom = 1; // 帧率

    handle = x265_encoder_open(?m);
    if(handle == NULL)
    {
        printf("x265_encoder_open err\n");
        goto out;
    }

    pic_in = x265_picture_alloc();
    if (pic_in == NULL)
    {
        goto out;
    }
    x265_picture_init(?m, pic_in);

    // Y分量大小
    luma_size = param.sourceWidth * param.sourceHeight;
    // 分量一帧YUV的空间
    switch (csp)
    {
    case X265_CSP_I444:
        buff = (char *)malloc(luma_size*3);
        pic_in->planes[0] = buff;
        pic_in->planes[1] = buff + luma_size;
        pic_in->planes[2] = buff + luma_size*2;
        pic_in->stride[0] = width;
        pic_in->stride[1] = width;
        pic_in->stride[2] = width;
        break;
    case X265_CSP_I420:
        buff = (char *)malloc(luma_size*3/2);
        pic_in->planes[0] = buff;
        pic_in->planes[1] = buff + luma_size;
        pic_in->planes[2] = buff + luma_size*5/4;
        pic_in->stride[0] = width;
        pic_in->stride[1] = width/2;
        pic_in->stride[2] = width/2;
        break;
    default:
        printf("Colorspace Not Support.\n");
        goto out;
    }

    // 计算总帧数
    fseek(fp_src, 0, SEEK_END);
    switch(csp)
    {
    case X265_CSP_I444:
        i_frame = ftell(fp_src) / (luma_size*3);
        chroma_size = luma_size;
        break;
    case X265_CSP_I420:
        i_frame = ftell(fp_src) / (luma_size*3/2);
        chroma_size = luma_size / 4;
        break;
    default:
        printf("Colorspace Not Support.\n");
        return -1;
    }
    fseek(fp_src,0,SEEK_SET);
    printf("framecnt: %d, y: %d u: %d\n", i_frame, luma_size, chroma_size);

    for(int i=0; i < i_frame; i++)
    {
        switch(csp)
        {
        case X265_CSP_I444:
        case X265_CSP_I420:
             if (fread(pic_in->planes[0], 1, luma_size, fp_src) != luma_size)
                break;
            if (fread(pic_in->planes[1], 1, chroma_size, fp_src) != chroma_size)
                break;
            if (fread(pic_in->planes[2], 1, chroma_size, fp_src) != chroma_size)
                break;
            break;
        default:
            printf("Colorspace Not Support.\n");
            goto out;
        }

        ret = x265_encoder_encode(handle, &nal, &i_nal, pic_in, NULL);    
        printf("encode frame: %5d framesize: %d nal: %d\n", i+1, ret, i_nal);
        if (ret < 0)
        {
            printf("Error encode frame: %d.\n", i+1);
            goto out;
        }

        for(uint32_t j = 0; j < i_nal; j++)
        {
            fwrite(nal[j].payload, 1, nal[j].sizeBytes, fp_dst);
        }
    }
    // Flush Decoder
    while((ret = x265_encoder_encode(handle, &nal, &i_nal, NULL, NULL)))
    {
        static int cnt = 1;
        printf("flush frame: %d\n", cnt++);
        for(uint32_t j=0; j < i_nal; j++)
        {
            fwrite(nal[j].payload, 1, nal[j].sizeBytes, fp_dst);
        }
    }

out:
    x265_encoder_close(handle);
    x265_picture_free(pic_in);
    if (buff)
        free(buff);

    fclose(fp_src);
    fclose(fp_dst);
    
    return 0;
}

使用方法:

x265_encode("../src/suzie_qcif_176x144_yuv420p.yuv", 176, 144, 1, "test.h265");

Makefile见上一文章所述。

李迟 2015.9.14 中午



如果本文对阁下有帮助,不妨赞助笔者以输出更多好文章,谢谢!
donate



标签:

给我留言