ffmpeg视频编码原理和实战-(2)视频帧的创建和编码packet压缩

作者 : admin 本文共1717个字,预计阅读时间需要5分钟 发布时间: 2024-06-16 共1人阅读

源文件:

#include 
using namespace std;
extern "C" { //指定函数是c语言函数,函数名不包含重载标注
//引用ffmpeg头文件
#include 
}
//预处理指令导入库
#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!" <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 height; y++)
        {
            for (int x = 0; x width; x++)
            {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }
        //UV
        for (int y = 0; y height / 2; y++)
        {
            for (int x = 0; x 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 <size << " " << flush;//输出压缩后的数据大小 单位为kb
            av_packet_unref(pkt);
        }
    }
    av_packet_free(&pkt);
    av_frame_free(&frame);
    avcodec_free_context(&c);//释放编码器上下文
    auto b = getchar();
    return 0;
}

运行结果:ffmpeg视频编码原理和实战-(2)视频帧的创建和编码packet压缩插图

可以看出这250帧中,基本上每帧就几千kb,压缩后的数据存储在avpacket中,下一步我们把数据写进文件并播放出来

本站无任何商业行为
个人在线分享 » ffmpeg视频编码原理和实战-(2)视频帧的创建和编码packet压缩
E-->