前提:
从前面的学习我们知道 AVFrame中是最原始的 视频数据,这一节开始我们需要将这个最原始的视频数据 压缩成 AVPacket数据,
我们前面,将YUV数据或者 RGBA 数据装进入了 AVFrame里面,并且在SDL中显示。
也就是说:对于安防项目来说,我们将原始从摄像头数据(YUV,RGB)转换成 AVFrame后,可以直接显示出来。但是如果我们将要数据存储,则要将 AVFrame转成 AVPacket.
视频编码 以及原理
从摄像头得到原始数据 ---- > 像素格式转换---->编码 ------>封装
编码的原因很好理解,YUV数据太大了,我们要编码成 h264,h265 等较小的格式
背后的原理是这样,一个YUV视频是由一张一张YUV图片组成的。
帧内压缩:
我们将一张YUV图片,假设是 1280x728大小的,我们将其划分成16x16的大小,总有一些像素点是一样的,或者接近的,例如下图:
帧间压缩:
假设上述图片是YUV 的第一张图片,第二帧图片是师爷 在讲话,那么第二帧图片可能只是嘴巴变化了一下,那么我们参考第一张图片,去存储第二张图片,就只用存储第二章图片 和 第一张图片不同的地方就好。。在还原的时候,参考第一张图片和差异,通过算法还原,这就叫做帧间压缩
我们这一节将 AVFrame转成 AVPacket,实际上就是编码的过程。
在将AVFrame转成AVPacket的过程中,我们会使用ffmpeg的提供的现成的API。
编码过程中的专业词语
为了更好的理解这些API的参数,我们需要大致明白这个转化流程中用到的专业方法,知道了这些专业方法,对于我们在使用API参数的时候,有个比较好的理解,实际上我们基本不会改动ffmpeg的源码,明白这些专业方法的对于开发者的含义是:你在使用API参数的时候,会能更好的明白为什么参数这么定义。
将AVFrame转成 AVPakcet,经过了 DCT离散余弦变换----->量化------>熵编码
在量化 阶段:有一个QP量化参数,也叫做QStep。这个QP取值为0---51,越大,质量越差。
AVPacket 重要函数以及重要结构体成员
FFmpeg存放压缩后的音视频数据的结构体:AVPacket简介,结构体,函数-CSDN博客
pts 和 dts 的区别
https://zhuanlan.zhihu.com/p/707384213
从avframe 变成 avpacket 也就是编码,编码相关API
0.从核心api出发倒推需要哪些API
0.1核心api 是将 avframe 发送给 AVCodecContext。
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
0.2 然后从AVCodecContext获得avpacket
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
对于视频来说:一帧avframe对应一帧avpacket
对于音频来说:一帧avframe对应多帧avpacket
注意的点:
这个过程实际可以看成是 生产者消费者模式。我们发送 AVFrame到AVCodecContext,然后从AVCodecContext就可以获得AVPacket了。
avcodec_send_frame方法 内部实现是开启线程 的,参见源码从这一行往下看 :return do_encode(avctx, frame, &(int){0});
得到的结论:
那么这个从源码实现看会 开启线程, 这说明啥呢?说明 这个过程一定是耗时的。
对于开发者来说:
立即从 avcodec_receive_packet 得到的 avpacket,这个avpacket有可能没有值,
那么对于这种情况开发者正确使用呢?
avcodec_receive_packet 对于这部分的说明是:
返回值<0, 说明有问题。但是<0的情况有4种。
如果 是 EAGAIN,说明output目前不可用,user必须再次发送 input。
* @return 0 on success, otherwise negative error code:
* AVERROR(EAGAIN): output is not available in the current state - user
* must try to send input
* AVERROR_EOF: the encoder has been fully flushed, and there will be
* no more output packets
* AVERROR(EINVAL): codec not opened, or it is a decoder
* other errors: legitimate encoding errors
*/
0.3 从前面的两个API可知,我们需要三个参数,avcodecContext,avframe,avpacket
0.4 获得avframe
前提条件是:
我们要从一个YUV420p文件中读取一帧 avframe,
要知道这个 YUV420P文件的 分辨率(也就是宽高),
要知道 YUV420P文件的 AVPixelFormat,
要知道这个文件的 linesize[0], linesize[1], linesize[2], 或者 对齐方式(知道了对齐方式,是可以计算出来 linesize[0],linesize[1],linesize[2]的)。如果不指定 linesize[0], linesize[1], linesize[2],ffmepg在av_frame_get_buffer 方法内部会自己计算出 linesize[0], linesize[1], linesize[2],计算的依据是 av_frame_get_buffer(avframe, 0)的第二个参数,传0会使用32位对齐的方式。
AVFrame* avframe = av_frame_alloc();
avframe->width = 800;
avframe->height = 600;
avframe->format = AV_PIX_FMT_YUV420P;
avframe->linesize[0] = 800;
avframe->linesize[1] = 400;
avframe->linesize[2] = 400;
ret = av_frame_get_buffer(avframe, 0);
如果是从头读取一个avframe,还应该设置 avframe的pts,pts就是显示时间,因为YUV420P文件就是原始的文件,因此按照顺序读取一帧avframe,就应该给pts++,那么在最前面的时候,应该给 avframe->pts 赋值为0 ;
0.5 获得 avpacket
创建 avpacket
AVPacket* avpacket = av_packet_alloc();
if (avpacket == nullptr) {
cout << "av_packet_alloc error" << endl;
return;
}
0.6 获得 avcodec
AVCodec* encoderAVCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (avpacket == nullptr) {
cout << "avcodec_find_encoder AV_CODEC_ID_H264 error" << endl;
return;
}
0.7 获得 avcodecContext,并给AVCodecContext 设置基本参数,timebase,pix_fmt,width,height
//4.创建 AVCodecContext
AVCodecContext* encoderAVCodecContext = avcodec_alloc_context3(encoderAVCodec);
if (encoderAVCodecContext == nullptr) {
cout << "avcodec_alloc_context3 error" << endl;
return;
}
//4.1 这里要设置 avcodecContext的基本参数,如果不设置,在 avcodec_open2的时候会有问题,参见如下的测试代码
encoderAVCodecContext->time_base = {1,25};
encoderAVCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
encoderAVCodecContext->width = avframe->width;
encoderAVCodecContext->height = avframe->height;
0.8 打开 AVCodecContexxt
ret = avcodec_open2(encoderAVCodecContext, nullptr, nullptr);
if (ret < 0) {
//如果不设置 encoderAVCodecContext的参数,这里会报错 -Invalid argument,
//[libx264 @ 00BAAE00] The encoder timebase is not set.
//[libx264 @ 007AAE00] Specified pixel format -1 is invalid or not supported
//[libx264 @ 00EFCBC0] dimensions not set..测试如果不设置encoderAVCodecContext->width 和 encoderAVCodecContext->height,就会有这个问题
cout << "avcodec_open2 error" << endl;
PrintErr(ret);
}
0.9 将 avframe 发送给 AVCodecContext。也就是0.1的操作
1.0 从 AVCodecContext 获得 avpacket。也就是0.2的操作
1.1 一般情况下,我们要读取的YUV文件都是很多帧,因此 0.9 和 1.0 要在一个读取YUV文件的循环里面做
1.2 当YUV文件读取完成后,还应该 刷新 AVCodecContext的缓存
具体方法是:通过 avcodec_send_frame(encoderAVCodecContext, nullptr);
然后通过 avcodec_receive_packet(encoderAVCodecContext, avpacket);接受,但是注意的是:一般的缓存有多个avpacket。因此要用循环接收
ret = avcodec_send_frame(encoderAVCodecContext, nullptr);
if (ret < 0) {
cout << "avcodec_send_frame nullptr error" << endl;
PrintErr(ret);
}
int count = 0;
//*@return 0 on success, otherwise negative error code :
// *AVERROR(EAGAIN) : output is not available in the current state - user
// * must try to send input
// * AVERROR_EOF : the encoder has been fully flushed, and there will be
// * no more output packets
// * AVERROR(EINVAL) : codec not opened, or it is a decoder
// * other errors : legitimate encoding errors
// * /
// int avcodec_receive_packet(AVCodecContext * avctx, AVPacket * avpkt);
while (true) {
ret = avcodec_receive_packet(encoderAVCodecContext, avpacket);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
cout << "last avcodec_receive_packet ret = " << ret << endl;
PrintErr(ret);
break;
}
if (ret < 0) {
char buf[1024] = { 0 };
av_strerror(ret, buf, sizeof(buf) - 1);
cerr << "avcodec_receive_packet failed!" << buf << endl;
break;
}
if (ret == 0) {
//这时候 说明 编码器中的 avpacket是真的有数据的
count++;
avpacketofs.write((char*)avpacket->data, avpacket->size);
cerr << "avcodec_receive_packet good! ret = " << ret << endl;
av_packet_unref(avpacket);
}
}
cout << "count = " << count << endl;
1.3 avpacket的清理工作。
每一帧的avpacket的大小都有可能不一样大,这个很好理解,IDR帧就很多,P和B帧就相对小的多。
我们通过 avcodec_receive_packet 读取到avpacket后,
下一次循环的时候,还会使用这个avpacket,这时候需要清理一下avpacket,
以防止可能的问题发生---使用方法为av_packet_unref(avpacket);
代码如下:
ret = avcodec_receive_packet(encoderAVCodecContext, avpacket);
if (ret == 0) {
//这时候 说明 编码器中的 avpacket是真的有数据的
count++;
avpacketofs.write((char*)avpacket->data, avpacket->size);
cerr << "avcodec_receive_packet good! ret = " << ret << endl;
av_packet_unref(avpacket); //清理avpacket,以防止问题发生。
}
那么这个问题是啥问题?内存泄漏吗?
我们将 avframe中的数据发送 10000000 次,并通过avcodec_receive_packet 得到 avpacket,每次都清空 avpakcet的情况下,没有内存泄漏问题发生。
int times = 10000000;
while (times != 0) {
ret = avcodec_send_frame(encoderAVCodecContext, avframe);
if (ret < 0) {
cout << "avcodec_send_frame error" << endl;
PrintErr(ret);
}
//我们看到,如果只有一帧的情况下,avcodec_receive_packet的返回值就是
ret = avcodec_receive_packet(encoderAVCodecContext, avpacket);
if (ret < 0) {
cout << "avcodec_receive_packet error ret = " << ret << endl;
PrintErr(ret);
// log如下
//avcodec_receive_packet error ret = -11
//Resource temporarily unavailable
av_packet_unref(avpacket);
times--;
}
else if (ret == 0) {
cerr << "avcodec_receive_packet good good godd ret = " << ret << endl;
}
}
其他条件不变,但是每次不清空,也不会有内存泄漏问题
int times = 10000000;
while (times != 0) {
ret = avcodec_send_frame(encoderAVCodecContext, avframe);
if (ret < 0) {
cout << "avcodec_send_frame error" << endl;
PrintErr(ret);
}
//我们看到,如果只有一帧的情况下,avcodec_receive_packet的返回值就是
ret = avcodec_receive_packet(encoderAVCodecContext, avpacket);
if (ret < 0) {
cout << "avcodec_receive_packet error ret = " << ret << endl;
PrintErr(ret);
// log如下
//avcodec_receive_packet error ret = -11
//Resource temporarily unavailable
//av_packet_unref(avpacket);
times--;
}
else if (ret == 0) {
cerr << "avcodec_receive_packet good good godd ret = " << ret << endl;
}
}
1.4 avframe的清理工作。
我们来看从yuvfile 文件中读取一帧 avframe中,然后将这一帧avframe 编码成一帧 avpacket,然后存储文件成 xxx.h264文件的操作,在这个过程中,观察应该方法
1.查找编码器
/**
* Find a registered encoder with a matching codec ID.
*
* @param id AVCodecID of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
const AVCodec *avcodec_find_encoder(enum AVCodecID id);
如果参数 是 AVCodecID ,那么对应的值如下,重要的为
AV_CODEC_ID_H264,
#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
enum AVCodecID {
AV_CODEC_ID_NONE,
/* video codecs */
AV_CODEC_ID_MPEG1VIDEO,
AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding
AV_CODEC_ID_H261,
AV_CODEC_ID_H263,
AV_CODEC_ID_RV10,
AV_CODEC_ID_RV20,
AV_CODEC_ID_MJPEG,
AV_CODEC_ID_MJPEGB,
AV_CODEC_ID_LJPEG,
AV_CODEC_ID_SP5X,
AV_CODEC_ID_JPEGLS,
AV_CODEC_ID_MPEG4,
AV_CODEC_ID_RAWVIDEO,
AV_CODEC_ID_MSMPEG4V1,
AV_CODEC_ID_MSMPEG4V2,
AV_CODEC_ID_MSMPEG4V3,
AV_CODEC_ID_WMV1,
AV_CODEC_ID_WMV2,
AV_CODEC_ID_H263P,
AV_CODEC_ID_H263I,
AV_CODEC_ID_FLV1,
AV_CODEC_ID_SVQ1,
AV_CODEC_ID_SVQ3,
AV_CODEC_ID_DVVIDEO,
AV_CODEC_ID_HUFFYUV,
AV_CODEC_ID_CYUV,
AV_CODEC_ID_H264,
AV_CODEC_ID_INDEO3,
AV_CODEC_ID_VP3,
AV_CODEC_ID_THEORA,
AV_CODEC_ID_ASV1,
AV_CODEC_ID_ASV2,
AV_CODEC_ID_FFV1,
AV_CODEC_ID_4XM,
AV_CODEC_ID_VCR1,
AV_CODEC_ID_CLJR,
AV_CODEC_ID_MDEC,
AV_CODEC_ID_ROQ,
AV_CODEC_ID_INTERPLAY_VIDEO,
AV_CODEC_ID_XAN_WC3,
AV_CODEC_ID_XAN_WC4,
AV_CODEC_ID_RPZA,
AV_CODEC_ID_CINEPAK,
AV_CODEC_ID_WS_VQA,
AV_CODEC_ID_MSRLE,
AV_CODEC_ID_MSVIDEO1,
AV_CODEC_ID_IDCIN,
AV_CODEC_ID_8BPS,
AV_CODEC_ID_SMC,
AV_CODEC_ID_FLIC,
AV_CODEC_ID_TRUEMOTION1,
AV_CODEC_ID_VMDVIDEO,
AV_CODEC_ID_MSZH,
AV_CODEC_ID_ZLIB,
AV_CODEC_ID_QTRLE,
AV_CODEC_ID_TSCC,
AV_CODEC_ID_ULTI,
AV_CODEC_ID_QDRAW,
AV_CODEC_ID_VIXL,
AV_CODEC_ID_QPEG,
AV_CODEC_ID_PNG,
AV_CODEC_ID_PPM,
AV_CODEC_ID_PBM,
AV_CODEC_ID_PGM,
AV_CODEC_ID_PGMYUV,
AV_CODEC_ID_PAM,
AV_CODEC_ID_FFVHUFF,
AV_CODEC_ID_RV30,
AV_CODEC_ID_RV40,
AV_CODEC_ID_VC1,
AV_CODEC_ID_WMV3,
AV_CODEC_ID_LOCO,
AV_CODEC_ID_WNV1,
AV_CODEC_ID_AASC,
AV_CODEC_ID_INDEO2,
AV_CODEC_ID_FRAPS,
AV_CODEC_ID_TRUEMOTION2,
AV_CODEC_ID_BMP,
AV_CODEC_ID_CSCD,
AV_CODEC_ID_MMVIDEO,
AV_CODEC_ID_ZMBV,
AV_CODEC_ID_AVS,
AV_CODEC_ID_SMACKVIDEO,
AV_CODEC_ID_NUV,
AV_CODEC_ID_KMVC,
AV_CODEC_ID_FLASHSV,
AV_CODEC_ID_CAVS,
AV_CODEC_ID_JPEG2000,
AV_CODEC_ID_VMNC,
AV_CODEC_ID_VP5,
AV_CODEC_ID_VP6,
AV_CODEC_ID_VP6F,
AV_CODEC_ID_TARGA,
AV_CODEC_ID_DSICINVIDEO,
AV_CODEC_ID_TIERTEXSEQVIDEO,
AV_CODEC_ID_TIFF,
AV_CODEC_ID_GIF,
AV_CODEC_ID_DXA,
AV_CODEC_ID_DNXHD,
AV_CODEC_ID_THP,
AV_CODEC_ID_SGI,
AV_CODEC_ID_C93,
AV_CODEC_ID_BETHSOFTVID,
AV_CODEC_ID_PTX,
AV_CODEC_ID_TXD,
AV_CODEC_ID_VP6A,
AV_CODEC_ID_AMV,
AV_CODEC_ID_VB,
AV_CODEC_ID_PCX,
AV_CODEC_ID_SUNRAST,
AV_CODEC_ID_INDEO4,
AV_CODEC_ID_INDEO5,
AV_CODEC_ID_MIMIC,
AV_CODEC_ID_RL2,
AV_CODEC_ID_ESCAPE124,
AV_CODEC_ID_DIRAC,
AV_CODEC_ID_BFI,
AV_CODEC_ID_CMV,
AV_CODEC_ID_MOTIONPIXELS,
AV_CODEC_ID_TGV,
AV_CODEC_ID_TGQ,
AV_CODEC_ID_TQI,
AV_CODEC_ID_AURA,
AV_CODEC_ID_AURA2,
AV_CODEC_ID_V210X,
AV_CODEC_ID_TMV,
AV_CODEC_ID_V210,
AV_CODEC_ID_DPX,
AV_CODEC_ID_MAD,
AV_CODEC_ID_FRWU,
AV_CODEC_ID_FLASHSV2,
AV_CODEC_ID_CDGRAPHICS,
AV_CODEC_ID_R210,
AV_CODEC_ID_ANM,
AV_CODEC_ID_BINKVIDEO,
AV_CODEC_ID_IFF_ILBM,
#define AV_CODEC_ID_IFF_BYTERUN1 AV_CODEC_ID_IFF_ILBM
AV_CODEC_ID_KGV1,
AV_CODEC_ID_YOP,
AV_CODEC_ID_VP8,
AV_CODEC_ID_PICTOR,
AV_CODEC_ID_ANSI,
AV_CODEC_ID_A64_MULTI,
AV_CODEC_ID_A64_MULTI5,
AV_CODEC_ID_R10K,
AV_CODEC_ID_MXPEG,
AV_CODEC_ID_LAGARITH,
AV_CODEC_ID_PRORES,
AV_CODEC_ID_JV,
AV_CODEC_ID_DFA,
AV_CODEC_ID_WMV3IMAGE,
AV_CODEC_ID_VC1IMAGE,
AV_CODEC_ID_UTVIDEO,
AV_CODEC_ID_BMV_VIDEO,
AV_CODEC_ID_VBLE,
AV_CODEC_ID_DXTORY,
AV_CODEC_ID_V410,
AV_CODEC_ID_XWD,
AV_CODEC_ID_CDXL,
AV_CODEC_ID_XBM,
AV_CODEC_ID_ZEROCODEC,
AV_CODEC_ID_MSS1,
AV_CODEC_ID_MSA1,
AV_CODEC_ID_TSCC2,
AV_CODEC_ID_MTS2,
AV_CODEC_ID_CLLC,
AV_CODEC_ID_MSS2,
AV_CODEC_ID_VP9,
AV_CODEC_ID_AIC,
AV_CODEC_ID_ESCAPE130,
AV_CODEC_ID_G2M,
AV_CODEC_ID_WEBP,
AV_CODEC_ID_HNM4_VIDEO,
AV_CODEC_ID_HEVC,
#define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
AV_CODEC_ID_FIC,
AV_CODEC_ID_ALIAS_PIX,
AV_CODEC_ID_BRENDER_PIX,
AV_CODEC_ID_PAF_VIDEO,
AV_CODEC_ID_EXR,
AV_CODEC_ID_VP7,
AV_CODEC_ID_SANM,
AV_CODEC_ID_SGIRLE,
AV_CODEC_ID_MVC1,
AV_CODEC_ID_MVC2,
AV_CODEC_ID_HQX,
AV_CODEC_ID_TDSC,
AV_CODEC_ID_HQ_HQA,
AV_CODEC_ID_HAP,
AV_CODEC_ID_DDS,
AV_CODEC_ID_DXV,
AV_CODEC_ID_SCREENPRESSO,
AV_CODEC_ID_RSCC,
AV_CODEC_ID_AVS2,
AV_CODEC_ID_Y41P = 0x8000,
AV_CODEC_ID_AVRP,
AV_CODEC_ID_012V,
AV_CODEC_ID_AVUI,
AV_CODEC_ID_AYUV,
AV_CODEC_ID_TARGA_Y216,
AV_CODEC_ID_V308,
AV_CODEC_ID_V408,
AV_CODEC_ID_YUV4,
AV_CODEC_ID_AVRN,
AV_CODEC_ID_CPIA,
AV_CODEC_ID_XFACE,
AV_CODEC_ID_SNOW,
AV_CODEC_ID_SMVJPEG,
AV_CODEC_ID_APNG,
AV_CODEC_ID_DAALA,
AV_CODEC_ID_CFHD,
AV_CODEC_ID_TRUEMOTION2RT,
AV_CODEC_ID_M101,
AV_CODEC_ID_MAGICYUV,
AV_CODEC_ID_SHEERVIDEO,
AV_CODEC_ID_YLC,
AV_CODEC_ID_PSD,
AV_CODEC_ID_PIXLET,
AV_CODEC_ID_SPEEDHQ,
AV_CODEC_ID_FMVC,
AV_CODEC_ID_SCPR,
AV_CODEC_ID_CLEARVIDEO,
AV_CODEC_ID_XPM,
AV_CODEC_ID_AV1,
AV_CODEC_ID_BITPACKED,
AV_CODEC_ID_MSCC,
AV_CODEC_ID_SRGC,
AV_CODEC_ID_SVG,
AV_CODEC_ID_GDV,
AV_CODEC_ID_FITS,
AV_CODEC_ID_IMM4,
AV_CODEC_ID_PROSUMER,
AV_CODEC_ID_MWSC,
AV_CODEC_ID_WCMV,
AV_CODEC_ID_RASC,
AV_CODEC_ID_HYMT,
AV_CODEC_ID_ARBC,
AV_CODEC_ID_AGM,
AV_CODEC_ID_LSCR,
AV_CODEC_ID_VP4,
AV_CODEC_ID_IMM5,
AV_CODEC_ID_MVDV,
AV_CODEC_ID_MVHA,
AV_CODEC_ID_CDTOONS,
AV_CODEC_ID_MV30,
AV_CODEC_ID_NOTCHLC,
AV_CODEC_ID_PFM,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
AV_CODEC_ID_PCM_S16LE = 0x10000,
AV_CODEC_ID_PCM_S16BE,
AV_CODEC_ID_PCM_U16LE,
AV_CODEC_ID_PCM_U16BE,
AV_CODEC_ID_PCM_S8,
AV_CODEC_ID_PCM_U8,
AV_CODEC_ID_PCM_MULAW,
AV_CODEC_ID_PCM_ALAW,
AV_CODEC_ID_PCM_S32LE,
AV_CODEC_ID_PCM_S32BE,
AV_CODEC_ID_PCM_U32LE,
AV_CODEC_ID_PCM_U32BE,
AV_CODEC_ID_PCM_S24LE,
AV_CODEC_ID_PCM_S24BE,
AV_CODEC_ID_PCM_U24LE,
AV_CODEC_ID_PCM_U24BE,
AV_CODEC_ID_PCM_S24DAUD,
AV_CODEC_ID_PCM_ZORK,
AV_CODEC_ID_PCM_S16LE_PLANAR,
AV_CODEC_ID_PCM_DVD,
AV_CODEC_ID_PCM_F32BE,
AV_CODEC_ID_PCM_F32LE,
AV_CODEC_ID_PCM_F64BE,
AV_CODEC_ID_PCM_F64LE,
AV_CODEC_ID_PCM_BLURAY,
AV_CODEC_ID_PCM_LXF,
AV_CODEC_ID_S302M,
AV_CODEC_ID_PCM_S8_PLANAR,
AV_CODEC_ID_PCM_S24LE_PLANAR,
AV_CODEC_ID_PCM_S32LE_PLANAR,
AV_CODEC_ID_PCM_S16BE_PLANAR,
AV_CODEC_ID_PCM_S64LE = 0x10800,
AV_CODEC_ID_PCM_S64BE,
AV_CODEC_ID_PCM_F16LE,
AV_CODEC_ID_PCM_F24LE,
AV_CODEC_ID_PCM_VIDC,
/* various ADPCM codecs */
AV_CODEC_ID_ADPCM_IMA_QT = 0x11000,
AV_CODEC_ID_ADPCM_IMA_WAV,
AV_CODEC_ID_ADPCM_IMA_DK3,
AV_CODEC_ID_