FFmpeg 之X264视频编码与FAAC音频编码(四)

阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
本篇文章将通过以下两部分内容来介绍FFmpeg

  • 视频x264编码浅析
  • 音频编解码FAAC

一、视频x264编码浅析

声明 x264_param_t 结构体变量:

x264_param_t params;

x264_param_default_preset(&params, "ultrafast", "zerolatency");//优化编码延迟?

变量参数编码前赋值:

params.i_csp                = (csp == 17) ? X264_CSP_NV12 : csp;//编码比特流的CSP,仅支持i420,色彩空间设置 
#ifdef    SQUARE_AND_ROTATE
    params.i_width            = w;
    params.i_height            = h;
#else
    params.i_width            = width;
    params.i_height            = height;
#endif
    params.vui.i_sar_width        = 1;
    params.vui.i_sar_height    = 1;    //设置长宽比 

    params.i_fps_num            = fpsnum;//帧率分子    
    params.i_fps_den            = fpsden;//帧率分母 

    params.i_timebase_num    = 1;
    params.i_timebase_den    = 1000;//ms

    params.i_keyint_max        = fpsnum/fpsden;
    params.i_keyint_min        = fpsnum/fpsden;//X264_KEYINT_MIN_AUTO

    params.b_repeat_headers    = 0;//
    params.b_annexb            = 0;

    params.b_deblocking_filter    = 1;
    params.rc.f_rf_constant     = 33;
    params.rc.i_bitrate            = bitrate;

初始化编码器:

enc = x264_encoder_open(&params);

获取整个流的pps和SPS:

int s = x264_encoder_headers(enc, &nals, &nal_count);

x264编码:

初始化图片信息:

x264_picture_t picin, picout;
x264_picture_init(&picin);

对图片信息参数设定:

picin.i_pts            = ts;
picin.i_type            = X264_TYPE_AUTO;
picin.i_qpplus1        = 0;
picin.img.i_csp        = (csp == 17) ? X264_CSP_NV12 : csp;//special hack for android
。。。。。。。
。。。。。。。
。。。。。

对帧进行x264编码:

ret = x264_encoder_encode(enc, &nals, &nnal, &picin, &picout);

总结

(1)初始化并设定x264_param_t

(2)初始化并设定 x264_picture_t

(3)x264编码

二、音频编解码·实战篇WAV转至AAC(AAC编码)

这里利用FAAC来实现AAC编码。另外,WAV的数据段是PCM,代码会出现很多PCM缩写。

1 下载安装 FAAC

这里的安装过程是在 Mac 和 Linux 上实现的,Windows可以类似参考。

wget http://downloads.sourceforge.net/faac/faac-1.28.tar.gz
tar zxvf faac-1.28.tar.gz
cd faac-1.28
./configure
make
sudo make install

如果才用默认的 configure 中的 prefix path,那么安装后的 lib 和 .h 文件分别在/usr/local/lib/usr/local/include,后面编译的时候会用到。

2 FAAC API

2.1 Open FAAC engine

Prototype:
faacEncHandle faacEncOpen               
// 返回一个FAAC的handle(                       
unsigned long   nSampleRate,        // 采样率,单位是bps    
unsigned long   nChannels,          // 声道,1为单声道,2为双声道
unsigned long   &nInputSamples,     // 传引用,得到每次调用编码时所应接收的原始数据长度    
unsigned long   &nMaxOutputBytes    // 传引用,得到每次调用编码时生成的AAC数据的最大长度);

2.2 Get/Set encoding configuration

Prototype:

获取编码器的配置:

faacEncConfigurationPtr faacEncGetCurrentConfiguration // 得到指向当前编码器配置的指针
(    
faacEncHandle hEncoder  // FAAC的handle
);

设定编码器的配置:

int FAACAPI faacEncSetConfiguration
(    
    faacDecHandle hDecoder,         // 此前得到的FAAC的handle    
    faacEncConfigurationPtr config  // FAAC编码器的配置
);

2.3 Encode

Prototype:
int faacEncEncode
(    
    faacEncHandle hEncoder,     // FAAC的handle    
    short *inputBuffer,         // WAV原始数据    
    unsigned int samplesInput,  // 调用faacEncOpen时得到的nInputSamples值    
    unsigned char *outputBuffer,// 至少具有调用faacEncOpen时得到的nMaxOutputBytes字节长度的缓冲区    
    unsigned int bufferSize     // outputBuffer缓冲区的实际大小
);

2.4 Close FAAC engine

Prototype
void faacEncClose
(    
    faacEncHandle hEncoder  // 此前得到的FAAC handle
);

3 流程

3.1 做什么准备?

采样率,声道数(双声道还是单声道?),还有你的WAV的单个样本是8位的还是16位的?

3.2 开启FAAC编码器,做编码前的准备

  1. 调用faacEncOpen开启FAAC编码器后,得到了单次输入样本数nInputSamples和输出数据最大字节数nMaxOutputBytes
  2. 根据nInputSamplesnMaxOutputBytes,分别为WAV数据和将要得到的AAC数据创建缓冲区;
  3. 调用faacEncGetCurrentConfiguration获取当前配置,修改完配置后,调用faacEncSetConfiguration设置新配置。

3.3 开始编码

调用faacEncEncode,该准备的刚才都准备好了,很简单。

3.4 善后

关闭编码器,另外别忘了释放缓冲区,如果使用了文件流,也别忘记了关闭。

4 测试程序

4.1 完整代码

WAV格式音频文件/home/michael/Development/testspace/in.wav转至AAC格式文件/home/michael/Development/testspace/out.aac

#include <faac.h>
#include <stdio.h>
 
typedef unsigned long   ULONG;
typedef unsigned int    UINT;
typedef unsigned char   BYTE;
typedef char            _TCHAR;
 
int main(int argc, _TCHAR* argv[])
{
    ULONG nSampleRate = 11025;  // 采样率
    UINT nChannels = 1;         // 声道数
    UINT nPCMBitSize = 16;      // 单样本位数
    ULONG nInputSamples = 0;
    ULONG nMaxOutputBytes = 0;
 
    int nRet;
    faacEncHandle hEncoder;
    faacEncConfigurationPtr pConfiguration; 
 
    int nBytesRead;
    int nPCMBufferSize;
    BYTE* pbPCMBuffer;
    BYTE* pbAACBuffer;
 
    FILE* fpIn; // WAV file for input
    FILE* fpOut; // AAC file for output
 
    fpIn = fopen("/home/michael/Development/testspace/in.wav", "rb");
    fpOut = fopen("/home/michael/Development/testspace/out.aac", "wb");
 
    // (1) Open FAAC engine
    hEncoder = faacEncOpen(nSampleRate, nChannels, &nInputSamples, &nMaxOutputBytes);
    if(hEncoder == NULL)
    {
        printf("[ERROR] Failed to call faacEncOpen()\n");
        return -1;
    }
 
    nPCMBufferSize = nInputSamples * nPCMBitSize / 8;
    pbPCMBuffer = new BYTE [nPCMBufferSize];
    pbAACBuffer = new BYTE [nMaxOutputBytes];
 
    // (2.1) Get current encoding configuration
    pConfiguration = faacEncGetCurrentConfiguration(hEncoder);
    pConfiguration->inputFormat = FAAC_INPUT_16BIT;
 
    // (2.2) Set encoding configuration
    nRet = faacEncSetConfiguration(hEncoder, pConfiguration);
 
    for(int i = 0; 1; i++)
    {
        // 读入的实际字节数,最大不会超过nPCMBufferSize,一般只有读到文件尾时才不是这个值
        nBytesRead = fread(pbPCMBuffer, 1, nPCMBufferSize, fpIn);
 
        // 输入样本数,用实际读入字节数计算,一般只有读到文件尾时才不是nPCMBufferSize/(nPCMBitSize/8);
        nInputSamples = nBytesRead / (nPCMBitSize / 8);
 
        // (3) Encode
        nRet = faacEncEncode(
        hEncoder, (int*) pbPCMBuffer, nInputSamples, pbAACBuffer, nMaxOutputBytes);
 
        fwrite(pbAACBuffer, 1, nRet, fpOut);
 
        printf("%d: faacEncEncode returns %d\n", i, nRet);
 
        if(nBytesRead <= 0)
        {
            break;
        }
    }
 
    
 
    // (4) Close FAAC engine
    nRet = faacEncClose(hEncoder);
 
    delete[] pbPCMBuffer;
    delete[] pbAACBuffer;
    fclose(fpIn);
    fclose(fpOut);
 
    //getchar();
 
    return 0;
}

4.2 编译运行

将上述代码保存为“wav2aac.cpp”文件,然后编译:

g++ wav2aac.cpp -o wav2aac -L/usr/local/lib -lfaac -I/usr/local/include

运行:

./wav2aac

然后就生成了out.aac文件了,听听看吧!~
参考 https://blog.youkuaiyun.com/simongyley/article/details/8507928
https://www.cnblogs.com/wainiwann/p/4427845.html
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值