视频编码流程 YUV数据编码为H264数据

1.视频编码流程

在这里插入图片描述

2.实战demo

#ifndef MAINBACK_C
#define MAINBACK_C
#endif // MAINBACK_C
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <libavcodec/avcodec.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <time.h>
int encode(AVCodecContext* codec_ctx,AVFrame* frame,AVPacket* pkt,FILE* out)
{
    int ret=0;
    ret = avcodec_send_frame(codec_ctx,frame);
    printf("send data\n");
    if(ret<0){
        printf("avcodec_send_frame failed\n");
        return ret;
    }

    while(1)
    {
        ret=avcodec_receive_packet(codec_ctx,pkt);
        if(ret==AVERROR(EAGAIN)||ret==AVERROR(AVERROR_EOF))
            break;
        if(ret<0)return ret;
        printf("write data\n");
        fwrite(pkt->data,1,pkt->size,out);

    }

}
//编码流程  先初始化编码器,读取原始文件,send,recvice,写入
int main(int argc,char* argv[])
{
    if(argv<3)
    {
        printf("argv<3\n");
        return -1;
    }
    char* yuv_path=argv[1];
    char* out_path=argv[2];
    FILE* yuv_file=fopen(yuv_path,"rb");
    FILE* out_file=fopen(out_path,"wb");
    AVCodec* codec=avcodec_find_encoder(AV_CODEC_ID_H264);
    AVCodecContext* codec_ctx=avcodec_alloc_context3(codec);

    codec_ctx->bit_rate=1024*512;
    codec_ctx->width=768;
    codec_ctx->height=320;
    codec_ctx->pix_fmt=AV_PIX_FMT_YUV420P;
    codec_ctx->max_b_frames=0;
    codec_ctx->gop_size=25;
    codec_ctx->framerate=(AVRational){25,1};
    codec_ctx->time_base=(AVRational){1,25};
    av_opt_set(codec_ctx->priv_data,"preset","veryslow",0);
    av_opt_set(codec_ctx->priv_data,"profile","main",0);
    av_opt_set(codec_ctx->priv_data,"tune","zerolatency",0);
    avcodec_open2(codec_ctx,codec,NULL);
    AVFrame* frame=av_frame_alloc();
    AVPacket* pkt=av_packet_alloc();
    frame->format=codec_ctx->pix_fmt;
    frame->width=codec_ctx->width;
    frame->height=codec_ctx->height;

    av_frame_get_buffer(frame,0);//分配frame的buff
    int frame_bytes=av_image_get_buffer_size(frame->format,frame->width,frame->height,1);
    uint8_t* yuv_buff=av_malloc(frame_bytes);
    memset(yuv_buff,0,frame_bytes);
    int pts=0;
    int ret=0;
    uint64_t begin=time(0);
    while(1)
    {
        int rsize=fread(yuv_buff,1,frame_bytes,yuv_file);
        ret = av_frame_make_writable(frame);
        if(ret != 0)
            printf("av_frame_make_writable failed, ret = %d\n", ret);

        int need_size=av_image_fill_arrays(frame->data,frame->linesize,yuv_buff,frame->format,frame->width,frame->height,1);
        if(rsize!=need_size)break;
        frame->pts=pts;
        pts+=1;

        encode(codec_ctx,frame,pkt,out_file);
    }
    encode(codec_ctx,NULL,pkt,out_file);
    printf("time:%lld",time(0)-begin);
    return 0;
}

3.相关编码知识点讲解

1. 参数设置问题:

视频编码时,设置编码器上下文参数有:码率,宽,高,格式,帧率等
frame设置:宽,高,格式
然后计算一帧的数据:宽 * 高 * 格式占用字节数
通常使用av_image_get_buffer_size来计算

2. 关于av_opt_set

av_opt_set就是用来设置参数的

  • preset
    preset参数是一个权衡编码速度和压缩率的参数,编码速度越慢,压缩率越高
    参数:
    ultrafast
    superfast
    veryfast
    faster
    fast
    medium – default preset 默认是medium
    slow
    slower
    veryslow
  • tune
    tune参数用于视觉的侧重点,也就是说压缩的时候重点压缩什么,保留什么…
    参数:
    film:电影类型,对视频的质量⾮常严格时使⽤该选项
    animation:动画⽚,压缩的视频是动画⽚时使⽤该选项
    grain:颗粒物很重,该选项适⽤于颗粒感很重的视频
    stillimage:静态图像,该选项主要⽤于静⽌画⾯⽐较多的视频
    psnr:提⾼psnr,该选项编码出来的视频psnr⽐较⾼
    ssim:提⾼ssim,该选项编码出来的视频ssim⽐较⾼
    fastdecode:快速解码,该选项有利于快速解码
    zerolatency:零延迟,该选项主要⽤于视频直播
  • profile
  1. baseline profile:基本画质。⽀持I/P 帧,只⽀持⽆交错(Progressive)和CAVLC;
  2. extended profile:进阶画质。⽀持I/P/B/SP/SI 帧,只⽀持⽆交错(Progressive)和CAVLC;
  3. main profile:主流画质。提供I/P/B 帧,⽀持⽆交错(Progressive)和交错(Interlaced),也⽀持CAVLC 和CABAC 的⽀持;
  4. high profile:⾼级画质。在main Profile 的基础上增加了8x8内部预测、⾃定义量化、 ⽆损视频编码和更多的YUV 格式;

3. 关于码流设置

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

相知-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值