C++-FFmpeg-(5)-1-ffmpeg原理-ffmpeg编码接口-AVFrame-AVPacket-最简单demo

1.视频编码原理

2.FFMpeg编码接口和AVPacket结构体详解
2.1ffmpeg编码接口 -编码器+上下文
2.2AVPacket结构体
2.3AVFrame结构体
3.视频播放最简单demo
3.1FFMpeg编码器获取和上下文打开
3.2视频帧创建和测试


1.视频编码原理

1.1 流程:像素格式转换->编码->封装

1.2为什么要编码:像素格式数据过大

采集高速数据,内存:128G内存

硬盘来不及存储:SSD :1s,3G ;PCIE接口 1s,500MB

1.3原始帧AVFrame->压缩帧AVPacket

AVFrame数据大:1s 1G的数据,性能性问题,不能复制。

AVPacket数据小:1080p:1s 1MB 结构清晰

1.4帧内压缩、帧间压缩

图片压缩:bmp->jpg 压缩 找相似点,大小变化不大

视频压缩:视频:保存差异

帧内压缩:只跟关键帧相关

1.5有损压缩、无损压缩

有损压缩:类似数据丢掉 解压后无法与原文件相同。

无损压缩:zip,rar,7z

2.FFMpeg编码接口和AVPacket结构体详解

2.1ffmpeg编码接口 -编码器+上下文

2.2AVPacket结构体

2.3AVFrame结构体

3.视频播放最简单demo

cpp 复制代码
int main113()
{
  //  auto codec; 编码器
  //  auto c;     上下文
  //  auto frame; 对象+缓冲 编码前
  //  auto pkt;   对象+缓冲 编码后

    // 编码器+上下文
    //1.查找+分配空间
    auto codec = avcodec_find_encoder(AV_CODEC_ID_H264);  //对象返回的是指针
    if (!codec) { return -1; }
    auto c = avcodec_alloc_context3(codec);
    //2.上下文 参数设置 视频宽、高、帧时间、元数据像素格式、编码线程数
    c->width = 400;
    c->height = 300;
    c->time_base = { 1,25 };
    c->pix_fmt = AV_PIX_FMT_YUV420P;
    c->thread_count = 16;
    //3.编码器 参数设置 b帧为0,
    c->max_b_frames = 0;
    int opt_re = av_opt_set(c->priv_data,"preset","ultrafast",0);//最快速度
    opt_re = av_opt_set(c->priv_data,"tune","zerolatency",0);    //零延时
    //4.打开上下文 返回值==0 OK
    int re = avcodec_open2(c, codec, NULL);                      // 返回值 "打开"!=0表示正确 
    if (re != 0) { return -1; }
    //5.AVFrame -赋值-编码(压缩数据AVPAckage)-写入文件
    //5.1AVFrame   创建对象+缓冲(),
    //5.11AVFrame设置参数 宽、高、像素格式
    auto frame=av_frame_alloc();
    frame->width = 400;
    frame->height = 300;
    frame->format = c->pix_fmt;
    int re = av_frame_get_buffer(frame,0);                     // 返回值  创建"缓冲区"!=0表示错误
    if (re != 0) { return -1; }
    //5.12 AVPacket 创建对象
    auto pkt = av_packet_alloc();
    //5.13
    string filename;
    filename = "400_300_25_preset.h265";
    ofstream ofs;
    ofs.open(filename, ios::binary);                          //返回值  ofs ofs.open  !表示错误
    if (!ofs)
    {
        cerr << "open " << filename<<" failed!" << endl;
        return -1;
    }
    //ofs.write((char*)pkt->data, pkt->size);
    //ofs.close();
    /*编码
    re=avcodec_send_frame(c,frame);
    while (re >= 0)
    {
        re=avcodec_receive_packet(c,pkt);
        if (re < 0) { break; }
        ofs.write((char*)pkt->data, pkt->size);
        av_packet_unref(pkt);
    }*/
    for (int i = 0; i < 250; i++)
    {
        for (int y = 0; y < frame->height;y++)//Y
        {
            for (int x = 0; x < frame->width; x++)
            {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }

        }
        for (int y = 0; y < frame->height / 2; y++)//UV
        {
            for (int x = 0; x < frame->width / 2; x++)
            {
                frame->data[1][y*frame->linesize[1]+x]= 128+x + y + i * 3;
                frame->data[2][y*frame->linesize[2]+x]=64+ x + y + i * 3;
            }
        }
        frame->pts = i;
        re=avcodec_send_frame(c, frame);                     //返回值    !=0 表示错误
        if (re != 0){ break;}
        while (re >= 0)
        {
            re=avcodec_receive_packet(c, pkt);               //返回值
            if (re < 0) { break; }
            av_packet_unref(pkt);
        }
    }

    ofs.close();
    //5.释放对象 AVFrame AVPAckage 编码器上下文
    av_packet_free(&pkt);
    av_frame_free(&frame);
    avcodec_free_context(&c);
    return 0;

}
相关推荐
浮游本尊3 分钟前
Java学习第22天 - 云原生与容器化
java
渣哥2 小时前
原来 Java 里线程安全集合有这么多种
java
间彧2 小时前
Spring Boot集成Spring Security完整指南
java
间彧2 小时前
Spring Secutiy基本原理及工作流程
java
Java水解3 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆6 小时前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学6 小时前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole6 小时前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端
华仔啊6 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端