音视频处理 ffmpeg中级开发 H264编码

开发介绍

  • libavcodec/avcodec.h
  • 常用的数据结构
    • AVCodec 编码器结构体
    • AVCodecContext 编码器上下文
    • AVFrame 解码后的帧
  • 结构体内存的分配和释放
    • av_frame_alloc 申请
    • av_frame_free() 释放
    • avcodec_alloc_context3() 创建编码器上下文
    • avcodec_free_context() 释放编码器上下文
  • 解码步骤
    • avcodec_find_decoder 查找解码器
    • avcodec_open2 打开解码器
    • avcodec_decode_video2 解码

FFMpegH264编码

  • avcodec_find_encoder_by_name 查找编码器
  • avcodec_open3  设置编码参数(分辨率、高、宽),并打开编码器,(解码的时候直接拷贝对应参数即可,无需再次设置)
  • avcodec_encode_video2 编码
    • 真正执行编码的由第三方库进行
    • 如libx264 libopenh264
  • 注意
    • 通过ID       查找编/解码器
    • 通过Name 查找编/解码器
  • 参考链接:FFmpeg h264编码 - 简书

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>extern "C" {#include<libavutil/opt.h>#include<libavutil/imgutils.h>#include<libavcodec/avcodec.h>
}//对每一帧数据进行编码
static void encode(AVCodecContext *enc_ctx,AVFrame *frame,AVPacket *pkt,FILE *outfile){int ret = 0;//send the frame to the encoderif (frame){printf("Send frame %3"PRId64"\n",frame->pts);}ret = avcodec_send_frame(enc_ctx,frame);if (ret < 0){fprintf(stderr,"Error sending a frame for encoding\n");exit(1);}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx,pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){return;} else if (ret < 0){fprintf(stderr,"Error during encoding\n");exit(1);}printf("Write packet %3"PRId64" (size=%5d)\n",pkt->pts,pkt->size);fwrite(pkt->data,1,pkt->size,outfile);av_packet_unref(pkt);}
}
int main(int argc,char** argv){const char *file_name,*codec_name;//输出文件路径和编码器名字,由运行程序时传入参数(要编码的内容是从摄像头获取的)const AVCodec *codec;             //编码器AVCodecContext *codec_context = nullptr;//编码上下文环境int i,ret,x,y,got_output;         //got_output用于标记一帧是否压缩成功FILE *file;AVFrame *frame;                   //原始帧(未压缩的数据)AVPacket pkt;uint8_t endcode[]={0,0,1,0xb7};if (argc <= 2){fprintf(stderr,"Usage: %s <output file> <codec name>\n",argv[0]);exit(0);}file_name = argv[1];codec_name = argv[2];     //h264编码器名字是libx264//avcodec_register_all()  //delete//通过名字查找编码器codec = avcodec_find_encoder_by_name(codec_name);if (!codec){fprintf(stderr,"Codec not found\n");exit(1);}//生成编码上下文环境codec_context = avcodec_alloc_context3(codec);if (!codec_context){fprintf(stderr,"Could not allocate video codec context\n");exit(1);}// 设置码率codec_context->bit_rate = 400000;// 设置视频宽高codec_context->width = 352;codec_context->height = 288;// 设置时间基、帧率(时间基根据帧率而变化)codec_context->time_base = (AVRational){1,25}; //一秒钟25帧,刻度就是1/25codec_context->framerate = (AVRational){25,1}; //时间基根据帧率进行变化// 设置多少帧产生一个关键帧,也就是一组帧是多少帧// 如果同一个镜头没有变化,只需要设定一个关键帧,一组帧以这个关键帧作为参照,从而降低数据存储codec_context->gop_size = 10;// 设置b帧(前后参考帧)// P帧 向前参考帧codec_context->max_b_frames = 1;// 要编码的原始数据的YUV格式codec_context->pix_fmt = AV_PIX_FMT_YUV420P;// 如果编码器id是h264if (codec->id == AV_CODEC_ID_H264){// preset表示采用一个预先设定好的参数集,级别是slow// slow表示压缩速度是慢的,慢的可以保证视频质量,用快的会降低视频质量av_opt_set(codec_context->priv_data,"preset","slow",0);}// 打开编码器if (avcodec_open2(codec_context,codec,NULL) < 0){fprintf(stderr,"Could not open codec\n");exit(1);}file = fopen(file_name,"wb");if (!file){fprintf(stderr,"Could not open %s\n",file_name);exit(1);}// 初始化帧并设置帧的YUV格式和分辨率frame = av_frame_alloc();if (!frame){fprintf(stderr,"Could not allocate video frame\n");exit(1);}frame->format = codec_context->pix_fmt;frame->width = codec_context->width;frame->height = codec_context->height;ret = av_frame_get_buffer(frame,32);if (ret < 0){fprintf(stderr,"Could not allocate the video frame data\n");exit(1);}// 这里是人工添加数据模拟生成1秒钟(25帧)的视频(真实应用中是从摄像头获取的原始数据,摄像头拿到数据后会传给编码器,然后编码器进行编码形成一帧帧数据。)for (i = 0; i < 25; i++) {av_init_packet(&pkt);//packet data will be allocated by the encoderpkt.data = NULL;pkt.size = 0;// 强制输出写入文件fflush(stdout);/* make sure the frame data is writable */ret = av_frame_make_writable(frame);if (ret < 0){exit(1);}// 下面2个循环是人工往frame里面添的数据/* Y */for (int y = 0; y < codec_context->height; y++) {for (int x = 0; x < codec_context->width; x++) {frame->data[0][y * frame->linesize[0] + x] = x + y + i*3;}}/* Cb and Cr */for (int y = 0; y < codec_context->height/2; y++) {for (int x = 0; x < codec_context->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;// 进行编码压缩encode(codec_context,frame,&pkt,file);}/* flush the encoder */encode(codec_context,NULL,&pkt,file);/* add sequence end code to have a real MPEG file */fwrite(endcode,1,sizeof (endcode),file);fclose(file);avcodec_free_context(&codec_context);av_frame_free(&frame);return 0;
}
  • build不出现错误之后,点击run,弹出提示信息,需要输入指定的参数
  • 进入终端页面,进入cmake-build-debug文件夹下
  • 使用如下命令进行数据编码 ./learn_ffmpeg 1.h264 libx264
  • 生成1.h264文件
  • 使用ffplay 1.h264 进行播放
  • 本人使用开源软件 PotPlayer进行视频播放 

  •  ffplay 1.h264进行视频播放,输出数据的相关描述信息
  • Stream #0:0: 流的ID
  • 视频流是 h264 high
  • 数据先前的格式是 yuv420p 分辨率是353x288 帧率是25 时间基是25 流的时间基是1200 编码的时间基是 50

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

音视频处理 ffmpeg中级开发 视频转图片

操作流程 目的&#xff1a;使用FFmpeg将视频的每一帧数据转换为图片1&#xff0c;打开输入的多媒体文件&#xff0c;检索多媒体文件中的流信息2&#xff0c;查找视频流的索引号&#xff0c;通过索引号获取数据流&#xff1b;通过解析视频流中的编码参数得到解码器ID&#xff0…

企业知识库与知识管理:如何统一战略与实践

在知识密集型的现代企业中&#xff0c;知识已经成为了一种宝贵的资产。如何有效地管理和利用这一资产&#xff0c;成为企业持续发展与创新的关键。企业知识库与知识管理作为知识经济的两大支柱&#xff0c;它们的重要性不言而喻。但很多时候&#xff0c;我们发现企业的知识管理…

音视频处理 ffmpeg中级开发 AAC编码

介绍 编码流程类似于视频编码&#xff0c;1&#xff0c;查找编码器&#xff1b;2&#xff0c;设定参数&#xff0c;打开编码器&#xff1b;3&#xff0c;数据编码编码函数 avcodec_encode_audio2 已经被弃用FFmpeg 过时 Api 汇总整理 - 灰色飘零 - 博客园 未成功使用 旧版本i…

虚拟机为Ubuntu分配空间

当虚拟机里面的创建的ubuntu镜像需要更大的空间&#xff0c;将ubuntu关掉之后&#xff0c;对应调整硬盘的空间大小&#xff0c;由先前的20G上调至50G&#xff0c;但是先前的20G内存空间映射的位置是/dev/sda&#xff0c;后面增加的这段内存空间30G映射到/dev/sda1因此&#xff…

为什么人会摆高姿态_Yo , 你为什么喜欢冲浪?

“你为什么喜欢冲浪&#xff1f;” 那天木木突然问我。我愣住了。此时一道碧波恰从防泼堤&#xff08;jetty&#xff09;的那头升起&#xff0c;木木转头望去&#xff0c;视线追着那道浪缓缓向西&#xff0c;直至它破碎成白色的浪花。我瞥见他眼神中的光亮&#xff0c;就和小孩…

音视频处理 ffmpeg初级开发 命令行工具-实用命令

参考链接 ffmpeg Documentation作者&#xff1a;smallest_one 链接&#xff1a;FFmpeg命令行工具-实用命令 - 简书 目录 1&#xff0c;help命令使用 1.1 ffmpeg命令的语法结构1.2 获取详细的help信息1.3 打印帮助或者支持能力的信息1.4 全局选项1.5 文件选项1.6 视频/音频/字…

不同的电脑打印预览不同怎么解决_条码打印软件中标签预览正常打印无反应怎么解决...

在使用条码打印软件制作标签时&#xff0c;有客户反馈,标签打印预览正常的&#xff0c;但是打印无反应&#xff0c;咨询是怎么回事?今天针对这个情况&#xff0c;可以参考以下方法进行解决。一、预览正常情况下&#xff0c;打印没反应(1)在条码打印软件中设计好标签之后&#…

MP4文件格式的相关内容

参考链接 FFmpeg中mp4的demuxer(mov.c)代码阅读 - 简书mp4文件格式解析 - 简书mp4封装格式各box类型讲解及IBP帧计算_青丶空゛的博客-CSDN博客5分钟入门MP4文件格式 - 程序猿小卡 - 博客园​关于M4A文件的随机访问 - 云社区 - 腾讯云 MP4文件格式相关内容 MP4文件由许多box组…

华三交换机如何进入配置_学校机房项目交换机的如何配置,理解这篇,交换机配置不再难...

弱电项目中&#xff0c;交换机的配置是无法避免的&#xff0c;大部分的项目都有可能会涉及到&#xff0c;尤其是机房等网络项目&#xff0c;本期我们就通过一个实际项目案例来详细了解交换机在项目中的应用配置&#xff0c;如果我们平时对交换机配置不熟&#xff0c;这个案例可…

百度地图迁徙大数据_百度地图大数据:五一高速拥堵不似预期,广深成热门迁出入地...

五一假期在即&#xff0c;你是否做好了“出行功课”&#xff1f;高速拥堵水平降低、公众出门不出城、公园成踏青赏景热门目的地……在全国疫情防控仍未松懈的时刻&#xff0c;2020年的五一或许注定与往年不同。近日&#xff0c;百度地图发布2020五一假期安全出行大数据&#xf…

音视频的基础知识 视频播放器原理/封装格式/视频音频编码数据/视频像素数据/音频采样数据

参考链接 FFMpeg视频播放器的制作-雷霄骅&#xff08;去除电流音版本&#xff09;_哔哩哔哩_bilibili 视频播放器原理 播放视频文件的流程YUV是一张屏幕中像素点的数值封装格式 MP4 RMVB TS FLV AVI将视频和音频码流按照一定的格式存储在一个文件中封装格式分析工具&#xf…

科立捷7代写频软件_天大厦大“两硕士论文雷同”通报,代写买卖论文

澎湃新闻记者 薛莎莎天津大学、厦门大学7月10日晚就“两硕士论文雷同”一事&#xff0c;分别发出调查处理通报。通报称&#xff0c;涉事两名学生存在由他人代写、买卖论文的学术作假的行为&#xff0c;均撤销其所获硕士学位&#xff0c;收回、注销硕士学位证书。澎湃新闻注意到…

FFMpeg命令行基础

参考链接 FFMpeg视频播放器的制作-雷霄骅&#xff08;去除电流音版本&#xff09;_哔哩哔哩_bilibili音视频处理 ffmpeg初级开发 命令行工具-实用命令_MY CUP OF TEA的博客-CSDN博客 介绍 FFMpeg是视频播放和转码的内核 使用 win中ffmpeg.exe用于视频转码简单命令&#xff1…

悲观锁和乐观锁_面试必备之乐观锁与悲观锁

何谓悲观锁与乐观锁乐观锁对应于生活中乐观的人总是想着事情往好的方向发展&#xff0c;悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点&#xff0c;不能不以场景而定说一种人好于另外一种人。大家可以点击加群【JAVA架构知识学习讨论群】47398464…

Microsoft Visual Studio2019环境下搭建FFmpeg开发环境

参考链接 《基于 FFmpeg SDL 的视频播放器的制作》课程的视频_雷霄骅的博客-CSDN博客_雷霄骅ffmpeg视频教程小学期课程资料 - 基于FFmpegSDL的视频播放器的制作.zip_免费高速下载|百度网盘-分享无限制辅助参考链接使用VS2019创建项目&#xff0c;添加文件和库地址_MY CUP OF …

vue process.env获取不到_从文档开始,重学vue(下)源码级别

此篇文章主要是从应用及源码层面讲解vue部分常用api,阅读起来可能略有难度,新手可以看《从文档开始,重学vue(上)》示例代码均在vue-cli3中完成Vue.extend()可以使用 extend 创建一个子类,该方法通常用于构建全局组件,如弹框组件等,下面我们就用它来制作个全局alert组件吧首先我…

Microsoft Visual Studio2019环境下搭建SDL开发环境

参考链接 《基于 FFmpeg SDL 的视频播放器的制作》课程的视频_雷霄骅的博客-CSDN博客_雷霄骅ffmpeg视频教程小学期课程资料 - 基于FFmpegSDL的视频播放器的制作.zip_免费高速下载|百度网盘-分享无限制辅助参考链接VS自动链接到Windows上随vcpkg安装的SDL2库 | 码农俱乐部 - G…

不关注公众号可以获取openid吗_微信公众号粉丝迁移

目录 [toc] 微信公众号迁移 正常的公众号迁移直接通过微信操作就可以&#xff0c;如下图。但是因为udb数据里面存的是迁移前公众号的openid以及unionid,需要自行获取新旧openid以及unionid。 旧的用户信息要在迁移之前获取&#xff0c;第三步点击同意之后就公众号的接口就调不通…

建筑专业规范大全 2020版_房屋建筑工程现行规范标准目录汇编(2020版)—建筑电气...

房屋建筑工程现行规范标准目录汇编(2020版)建筑电气规范编号规范名称GB 50034-2013建筑照明设计标准GB 50052-2009供配电系统设计规范GB 50053-201320kV及以下变电所设计规范GB 50057-2010建筑物防雷设计规范GB 50147-2010电气装置安装工程 高压电器施工及验收规范GB 50148-201…

基于Microsoft Visual Studio2019环境编写ffmpeg视频解码代码

旧代码 旧代码使用了很多过时的API&#xff0c;这些API使用后&#xff0c;vs会报编译器警告 (级别 3) C4996的错误即 函数被声明为已否决 报 C4996的错误 // test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #define SDL_MAIN_HANDLED …