使用FFMPEG库将YUV编码为H264

news/2025/3/14 21:39:40/

准备

ffmpeg 4.4

p准备一段yuv420p的格式的视频原始数据

这里我们使用命令直接提取

 ffmpeg -i .\beautlWorld.mp4 -pixel_format yuv420p  -s 1280x720 yuv420p_1280x720.yuv

编码流程

大致可以分为以下几步:

1.初始化编码器并设置参数

2.初始化AVPacket和AVFrame,设置参数

3.读取视频文件,进行编码

4.释放内存,结束

编码

以下是完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
}using namespace std;const char* inFileName = "D:/测试工程/sound/yuv420p_1280x720.yuv";
const char* outFileName = "D:/测试工程/sound/3333encode_yuv420p_1280x720.h264";int encode(AVCodecContext* codecContent, AVPacket * packet, AVFrame* frame, FILE* outFile)
{//解码int ret = avcodec_send_frame(codecContent, frame);if (ret < 0){fprintf(stderr, "Error sending a frame for encoding\n");return -1;}while (ret == 0){ret = avcodec_receive_packet(codecContent, packet);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;}else if (ret < 0) {fprintf(stderr, "Error encoding video frame\n");return -1;}if (ret == 0){fwrite(packet->data, 1, packet->size, outFile);}}
}int main(int argc, char* argv[])
{int ret = 0;AVCodec* codec = nullptr;AVCodecContext* codecContent = nullptr;AVPacket* packet = nullptr;AVFrame* frame = nullptr;FILE* inFile = nullptr;FILE* outFile = nullptr;//编码器初始化codec = avcodec_find_encoder(AV_CODEC_ID_H264);if (codec == nullptr){printf("could not find h264 encoder!");return -1;}codecContent = avcodec_alloc_context3(codec);if (codecContent == nullptr){printf("could not alloc h264 content!");return -1;}//必设参数codecContent->width = 1280;codecContent->height = 720;codecContent->time_base = AVRational{ 1, 25 };codecContent->pix_fmt = AV_PIX_FMT_YUV420P;codecContent->gop_size = 25; //关键帧间隔,默认250codecContent->framerate = AVRational{ 25, 1 };ret = avcodec_open2(codecContent, codec, NULL);if (ret < 0) {fprintf(stderr, "Could not open codec: %d\n", ret);exit(1);}packet = av_packet_alloc();if (packet == nullptr){printf("alloc packet error");return -1;}frame = av_frame_alloc();if (packet == nullptr){printf("alloc frame error");return -1;}frame->width = codecContent->width;frame->height = codecContent->height;frame->format = codecContent->pix_fmt;ret =  av_frame_get_buffer(frame, 0);if (ret){printf("alloc frame buffer error!");return -1;}inFile = fopen(inFileName, "rb");if (inFile == nullptr){printf("error to open file: %s\n", inFileName);return -1;}outFile = fopen(outFileName, "wb");if (inFile == nullptr){printf("error to open file: %s\n", outFileName);return -1;}int framecount = 0;frame->pts = 0;while (!feof(inFile)){ret = av_frame_is_writable(frame);if (ret < 0) {ret = av_frame_make_writable(frame);}fread(frame->data[0], 1, frame->width * frame->height, inFile); //yfread(frame->data[1], 1, frame->width * frame->height / 4, inFile); //ufread(frame->data[2], 1, frame->width * frame->height / 4, inFile);  //vprintf("encode frame num: %d\n", ++framecount);frame->pts += 1000 / (codecContent->time_base.den / codecContent->time_base.num);encode(codecContent, packet, frame, outFile);}encode(codecContent, packet, nullptr, outFile);av_packet_free(&packet);av_frame_free(&frame);avcodec_free_context(&codecContent);fclose(inFile);fclose(outFile);return 0;
}

小结

AVCodecContext

对于视频编码器而言必须设置以下参数:

AVRational time_base;

int width, height;

以下由用户设置,可选

gop_size: 默认250,也就是每250帧一个关键帧,可选设置

max_b_frames: 默认3, b帧最大连续个数

bit_rate: 平均比特率

avcodec_alloc_context3

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

为AVCodecContext结构申请空间,并使用默认值初始化!最后使用avcodec_free_context进行释放。

avcodec_open2

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

调用该函数前:time_base(也就是每帧显示的时间),width(帧宽), height(帧高)

av_frame_get_buffer

int av_frame_get_buffer(AVFrame *frame, int align);

为音视频分配数据存储空间。调用该函数前需要设置AVFRAME几个初始值。

音频:1.sample format  2.nb_samples 3.channel_layout

视频:1.pixel format 2.width 3.height  

align:直接对其,默认给0,根据当前CPU自行设置


http://www.ppmy.cn/news/48241.html

相关文章

适应大、中、小型医院的手术麻醉临床信息管理系统源码

手术麻醉管理系统是一款专门用于医院手术麻醉管理的软件系统&#xff0c;它可以帮助医院和医生更好地管理手术麻醉过程&#xff0c;提高手术麻醉的质量和安全性。本文将介绍手术麻醉管理系统的实现、功能概述、主要功能、系统设置、麻醉管理、术中记录、苏醒室记录、PCA实施及管…

gRPC(Java) keepAlive机制研究

文章目录 结论Client端KeepAlive使用入口简要时序列表 Server端KeepAlive使用入口简要时序列表KeepAliveEnforcer 基于java gRPC 1.24.2 分析 结论 gRPC keepAlive是grpc框架在应用层面连接保活的一种措施。即当grpc连接上没有业务数据时&#xff0c;是否发送pingpong,以保持连…

快手社招Java后端开发岗面试,被问麻了

社招面试是基于你的工作项目来展开问的&#xff0c;比如你项目用了 xxx 技术&#xff0c;那么面试就会追问你项目是怎么用 xxx 技术的&#xff0c;遇到什么难点和挑战&#xff0c;然后再考察一下这个 xxx 技术的原理。 今天就分享一位快手社招面经&#xff0c;岗位是后端开发&…

陪诊小程序开发|陪诊软件开发功能特色

为了提升就医的服务质量&#xff0c;人们对于医疗服务的需求也在不断提高。这几年随着生活水平和医疗水平的提升&#xff0c;陪诊服务越来越受到人们的重视和青睐&#xff0c;越来越多的人开始意识到&#xff0c;陪伴和关爱在疾病治疗过程中的重要性&#xff0c;为了更好的规划…

第四章 面向对象(OOP)

目录 一、编程思想 1.1. 面向对象 1.2. 面向过程 1.3.举例说明&#xff08;把大象装进冰箱&#xff09; 1.4.二者的联系与区别 1.5.面向对象的三个阶段 1.6.什么是类&#xff0c;什么是实例&#xff0c;二者的联系 二、面向对象三大特征 2.1 封装 2.2 继承 2.3 多态…

2023年全国最新二级建造师精选真题及答案56

百分百题库提供二级建造师考试试题、二建考试预测题、二级建造师考试真题、二建证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 11.关于施工企业项目经理部的说法&#xff0c;正确的是&#xff08;&#xff09;。 A.项目经…

学习风`宇博客用户权限菜单模块

文章目录 用户-角色-菜单-资源 各表关系图菜单 和 路由菜单表及分析分析 /api/admin/user/menus接口MenuServiceImpl#listUserMenus接口返回示例及分析 前端代码分析menu.jsSideBar.vue 接口权限控制资源表 及 分析分析 WebSecurityConfig权限控制整体流程先说登录UserDetailsS…

MATLAB应用笔记

其他 1、NaN值 MATLAB判断数据是否为NaN可以直接使用函数&#xff1a;isnan() 三、数据分析 1、相关性 均值、方差、协方差、标准差、相关系数 mean() %均值 nanmean()%去除NAN值求均值 var() %方差 cov() %协方差 std() %标准差 corrcoef(B,b) %R 相关系数plot()…