源文件:
#include <iostream>
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include <libavcodec/avcodec.h>
}
//预处理指令导入库
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
int main(int argc, char* argv[])
{
//1 找到编码器
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
//2 编码上下文的创建
AVCodecContext* c = avcodec_alloc_context3(codec);
//3设定上下文参数
c->width = 400;//视频宽度
c->height = 300;
c->time_base = { 1,25 };// 1/25,pts*time_base = 播放时间(秒)
c->pix_fmt = AV_PIX_FMT_YUV420P;//指定元数据的像素格式 与编码算法相关 h264只能yuv420;
c->thread_count = 16;//编码的线程数 可以调用系统接口获取cpu核心数
//4 打开编码上下文
int re = avcodec_open2(c, codec, NULL);
cout << "avcodec_open2 succece!" << endl;
//5 创建avframe,存储的是未压缩的元数据
auto frame = av_frame_alloc();
frame->width = 400;
frame->height = 300;
frame->format = c->pix_fmt;
re = av_frame_get_buffer(frame, 0);
auto pkt = av_packet_alloc();
//6 十秒视频 250帧
for (int i = 0; i < 250; i++)
{
//6.1生成AVFrame 数据 每帧数据不同
//Y
for (int y = 0; y < c->height; y++)
{
for (int x = 0; x < c->width; x++)
{
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
}
}
//UV
for (int y = 0; y < c->height / 2; y++)
{
for (int x = 0; x < c->width / 2; x++)
{
frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
}
}
frame->pts = i;//显示的时间
//6.2发送未压缩的帧到线程中进行压缩
//对于解码,调用avcodec_send_packet()以将AVPacket中的原始压缩数据提供给解码器。
//对于编码,调用avcodec_send_frame()为编码器提供包含未压缩音频或视频的AVFrame。
re = avcodec_send_frame(c, frame);//此时编码器有了元数据
//6.3接收压缩帧,一般前几次调用返回空(缓冲,立刻返回,编码未完成)
//编码是在另外独立线程中进行编码的
//每次调用会重新分配pkt中的空间
while (re >= 0)//返回多个帧
{
//要解码,请调用avcodec_receive_frame()。成功后,它将返回包含未压缩音频或视频数据的AVFrame 。
//对于编码,请调用avcodec_receive_packet()。成功时,它将返回带有压缩帧的AVPacket 。重复此调用,直到返回AVERROR(EAGAIN)或错误。
re = avcodec_receive_packet(c, pkt);//此时对编码器中的元数据进行压缩到avpacket中
cout << pkt->size << " " << flush;//输出压缩后的数据大小 单位为kb
av_packet_unref(pkt);
}
}
av_packet_free(&pkt);
av_frame_free(&frame);
avcodec_free_context(&c);//释放编码器上下文
auto b = getchar();
return 0;
}
运行结果:
可以看出这250帧中,基本上每帧就几千kb,压缩后的数据存储在avpacket中,下一步我们把数据写进文件并播放出来