博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ffmpeg--封装格式转换 YUV文件 -> 其他格式(freadpFrame.data[012]->编码成目标格式pkt->写入 + flush_encoder)
阅读量:3921 次
发布时间:2019-05-23

本文共 3954 字,大约阅读时间需要 13 分钟。

摘要:

YUV -> H.264步骤:
1、读取一帧->pFrame->data[012]->编码成目标h264格式的pkt->写入)
2、flush_encoder直到全部编码成功
3、注意pts
区别只在与参数的设置

在这里插入图片描述

代码

#include "libavutil/opt.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"  int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)//输入的像素数据读取完成后调用此函数。用于输出编码器中剩余的AVPacket。{
int ret; int got_frame; AVPacket enc_pkt; if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities & CODEC_CAP_DELAY)) return 0; while (1) {
enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet(&enc_pkt); ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,NULL, &got_frame); av_frame_free(NULL); if (ret < 0) break; //出错 if (!got_frame) {
ret=0;break;} //编码正常但没有拿到pkt printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size); /* mux encoded frame */ ret = av_write_frame(fmt_ctx, &enc_pkt); //将编码后的视频码流写入文件。 if (ret < 0) break; } return ret;} int main(int argc, char* argv[]){
AVFormatContext* pFormatCtx; AVOutputFormat* fmt; AVStream* video_st; AVCodecContext* pCodecCtx; AVCodec* pCodec; AVPacket pkt; uint8_t* picture_buf; AVFrame* pFrame; int picture_size; int y_size; int framecnt=0; FILE *in_file = fopen("../ds_480x272.yuv", "rb"); int in_w=480,in_h=272; int framenum=100; const char* out_file = "ds.h264"; av_register_all(); avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);//初始化输出码流的AVFormatContext fmt = pFormatCtx->oformat;【通过文件名out_file=?.h264→→av_guess_format推测出pFormatCtx->oformat为H264】 //avformat_alloc_output_context2()={...+avformat_alloc_context + av_guess_format+...} //Open output URL avio_open打开输出文件 avio_open(AVIOContext结构体&pFormatCtx->pb,out_file, flag) video_st = avformat_new_stream(pFormatCtx, 0); //Param that must set pCodecCtx = video_st->codec; //pCodecCtx->codec_id =AV_CODEC_ID_HEVC; pCodecCtx->codec_id = fmt->video_codec;【编解码器ID】 pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;【编解码器类型-视频】 pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P; pCodecCtx->width = in_w; pCodecCtx->height = in_h; pCodecCtx->bit_rate = 400000; pCodecCtx->gop_size=250; //H264 pCodecCtx->qmin = 10; pCodecCtx->qmax = 51; //Optional Param pCodecCtx->max_b_frames=3; // Set Option AVDictionary *param = 0; //H.264 if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶m, "preset", "slow", 0); av_dict_set(¶m, "tune", "zerolatency", 0); //av_dict_set(¶m, "profile", "main", 0); } //Show some Information av_dump_format(pFormatCtx, 0, out_file, 1); pCodec = avcodec_find_encoder(pCodecCtx->codec_id); avcodec_open2(pCodecCtx, pCodec,¶m) pFrame = av_frame_alloc();//pFrame内部的数据指针为NULL,需要单独申请和绑定 picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); picture_buf = (uint8_t *)av_malloc(picture_size); avpicture_fill((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//绑定pFrame和数据picture_buf avformat_write_header(pFormatCtx,NULL); //写文件头(某些没有文件头的封装格式,不需要此函数 av_new_packet(&pkt,picture_size); y_size = pCodecCtx->width * pCodecCtx->height; for (int i=0; i
data[0] = picture_buf; // Y pFrame->data[1] = picture_buf+ y_size; // U pFrame->data[2] = picture_buf+ y_size*5/4; // V pFrame->pts=i; int got_picture=0; avcodec_encode_video2(pCodecCtx,&pkt,pFrame, &got_picture);//得到的pkt中的pts和dts沿袭pFrame中的pts if (got_picture==1){
framecnt++; pkt.stream_index = video_st->index; av_write_frame(pFormatCtx, &pkt); av_free_packet(&pkt);//旧av_free_packet释放内容但不释放空间 而新函数av_packet_free会释放pkt空间 } } flush_encoder(pFormatCtx,0); //用于输出编码器中剩余的AVPacket。 av_write_trailer(pFormatCtx); end: if (video_st){
avcodec_close(video_st->codec); av_free(pFrame); av_free(picture_buf);【释放数据内存picture_buf】 } avio_close(pFormatCtx->pb);//封装格式上下文AVFormatContext中的AVIOContext结构体 avformat_free_context(pFormatCtx); fclose(in_file); return 0;}

转载地址:http://qyhrn.baihongyu.com/

你可能感兴趣的文章
NET问答: 为什么仅有 getter 的属性,还可以在构造函数中赋值 ?
查看>>
WPF TextBox限制只能输入数字的两种方法
查看>>
【荐】牛逼的WPF动画库:XamlFlair
查看>>
如何绕过 TPM 2.0 安装 Windows 11 操作系统?
查看>>
为WPF播放GIF伤神不?
查看>>
.NET Core with 微服务 - Elastic APM
查看>>
生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包...
查看>>
考虑用Task.WhenAll
查看>>
关于面试,避开这几点,成功几率更大~~~
查看>>
通过反射实现IOC功能
查看>>
堵俊平:开放治理是开源社区的终极之路 | DEV. Together 2021 中国开发者生态峰会...
查看>>
Linux实操--实用指令Day3
查看>>
Mysql 事务处理
查看>>
Linux实操--实用指令Day4
查看>>
Linux实操--实用指令Day3
查看>>
spring+springboot认识
查看>>
Leetcode 136. 只出现一次的数字
查看>>
Leetcode 11. 盛最多水的容器
查看>>
Leetcode 121. 买卖股票的最佳时机
查看>>
Leetcode 123. 买卖股票的最佳时机 III
查看>>