[FFmpeg] 视频编码将yuv文件编码为264文件

本文详细介绍了如何使用FFmpeg库中的函数,如`avformat_open_input`、`avcodec_find_encoder_by_name`等,通过libx264编码器将YUV格式的视频文件转换为H.264编码的MP4文件,包括设置编码参数和实际编码过程。
摘要由CSDN通过智能技术生成
av_register_all();
const char *inFilename = "/home/16THDD/xieyingbo/xieyingbo/big_buck_bunny.yuv";
const char *outFilename = "/home/16THDD/xieyingbo/xieyingbo/big_buck_bunny.264";
AVFormatContext *pFormatCtx = NULL;

int ret = avformat_open_input(&pFormatCtx, inFilename, NULL, NULL);
if(ret != 0)
{
    printf("%s\n", "open input format error.");
}

int width = 640, height = 360;    //源文件分辨率
AVRational avrational;            //设置时间基
avrational.den = 1;
avrational.num = 30;              //30(30帧 fps)

//1.查找编码器
AVcodec *encodec = avcodec_find_encoder_by_name("libx264");
if(NULL == encodec)
{
    printf("%s\n", "find encodec error.");
}

//2.创建编码器上下文
AVCodecContext *encodeCtx = avcodec_alloc_context3(encodec);
if(NULL == encodecCtx)
{
    printf("%s\n", "avcodec alloc context3 error.");
}

//3.设置编码参数(不设置的话为默认参数)
encodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;    //视频还是音频
encodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;       //颜色空间
encodecCtx->width = width;
encodecCtx->height = height;
encodecCtx->time_base = avrational;             //时间基
encodecCtx->bit_rate = 4096000;                 //比特率(每秒传输多少数据,比特率越大,图像质量越好)
encodecCtx->max_b_frames = 2;                   //最大连续B帧(减少B帧会减小数据量,但是会影响解码效率)
encodecCtx->gop_size = 50;                      //I帧间隔

//4.打开编码器
ret = avcodec_open2(encodecCtx, encodec, NULL);
if(ret <= 0)
{
    printf("%s\n", "avcodec open encodecCtx error.");
}

//5.读取yuv数据
FILE *src_fp = fopen(inFilename, "rb");
if(NULL == src_fp)
{
    printf("%s\n", "open inFilename error.");
}

FILE *dst_fp = fopen(outFilename, "wb+");
if(NULL == dst_fp)
{
    printf("%s\n", "open outFilename error.");
}

AVFrame *avframe = av_frame_alloc();  //申请frame内存
int framesize = av_image_get_buffer_size(encodecCtx->pix_fmt, width, height, 1); //获取转换空间大小
uint8_t *frameBuffer = av_malloc(framesize);  //申请内存空间
av_image_fill_arrays(avframe->data, avframe->linesize, frameBuffer, encodecCtx->pix_fmt, 640, 360);  //把转换后的连续空间打包到avframe中

avframe->format = encodecCtx->pix_fmt;
avframe->width = width;
avframe->height = height;

int picturesize = width * height;
AVPacket avpacket;
int count = 0;
while(fread(frameBuffer, 1, picturesize *3/2, src_fp) == picturesize *3/2)
{
    //YUV420 Y 1 U 1/4 V 1/4
    avframe->data[0] = frameBuffer;
    avframe->data[1] = frameBuffer + picturesize;
    avframe->data[2] = frameBuffer + picturesize +picturesize / 4;
    count++;
    avframe->pts = count;        //表示这一帧的展示顺序,不是时间戳
}

encodeVideo(encodecCtx, avframe, *packet, dst_fp);
void encodeVideo(AVCodecContext *enCodecCtx, AVFrame *frame, AVPacket *packet, FILE *dst_fp)
{
    //6.开始编码
    int ret = avcodec_send_frame(enCodecCtx, frame);
    if(ret < 0)
    {
        printf("%s\n", "avcodec send frame failed.");
    }

    while(ret >= 0)
    {
        ret = avocdec_receive_packet(encodecCtx, packet);
        if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)    //没有数据了
        {
           break;
        }
        else if(ret < 0)
        {
           printf("%s\n", "encodec frame failed.");
           return;
        }
        fwrite(packet->data, 1, packet->size, dst_fp);
        av_packet_unref(&packet);
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值