ffmpeg3.4 yuv编码为h264

参考:https://blog.csdn.net/tph5559/article/details/79093293

#include "stdafx.h"  

#include   

#include   

#include   

 

extern "C"

{

#include     

#include     

#include     

#include     

#include     

#include   

}

 

 

extern "C"

{

#include "libavutil/opt.h"  

#include "libavcodec/avcodec.h"  

#include "libavformat/avformat.h"  

#include "libavutil/imgutils.h"  

};

 

//encode one frame  

static int encode(AVCodecContext *pCodecCtx, AVFrame *pFrame, AVPacket *pPkt, FILE *out_file) {

 

int got_packet = 0;

int ret = avcodec_send_frame(pCodecCtx, pFrame);

if (ret < 0) {

//failed to send frame for encoding  

return -1;

}

while (!ret) {

ret = avcodec_receive_packet(pCodecCtx, pPkt);

if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {

return 0;

}

else if (ret < 0) {

//error during encoding  

return -1;

}

 

printf("Write frame %d, size=%d\n", pPkt->pts, pPkt->size);

fwrite(pPkt->data, 1, pPkt->size, out_file);

av_packet_unref(pPkt);

}

return 0;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

AVFormatContext *pFormatCtx;

AVOutputFormat *pOutputFmt;

AVStream *pStream;

AVCodecContext *pCodecCtx;

AVCodec *pCodec;

AVPacket *pPkt;

AVFrame *pFrame;

 

/*读入文件,并创建输出文件*/

FILE *in_file = NULL;

FILE *out_file = NULL;

in_file = fopen("yuv_test.yuv", "rb");

if (in_file == NULL) {

printf("cannot open input file\n");

return -1;

}

 

out_file = fopen("out.h264", "wb");

if (out_file == NULL) {

printf("cannot create out file\n");

return -1;

}

 

int nWidth = 1920;

int nHeight = 1080;

int nFrameNum = 100;

unsigned char* pFrameBuf = NULL;//存储buffer  

int nFrameBufSize = 0;//buffer大小  

int nReadSize = 0;

int nEncodedFrameCount = 0;

unsigned char endcode[] = { 0, 0, 1, 0xb7 };

 

av_register_all();//初始化  

 

pFormatCtx = avformat_alloc_context();//申请AVFormatContext  

pOutputFmt = av_guess_format(NULL, "out.h264", NULL);//猜测类型,返回输出类型。  

pFormatCtx->oformat = pOutputFmt;

 

//除了以下方法,另外还可以使用avcodec_find_encoder_by_name()来获取AVCodec  

pCodec = avcodec_find_encoder(pOutputFmt->video_codec);//获取编码器  

if (!pCodec) {

//cannot find encoder  

return -1;

}

 

pCodecCtx = avcodec_alloc_context3(pCodec);//申请AVCodecContext,并初始化。  

if (!pCodecCtx) {

//failed get AVCodecContext  

return -1;

}

 

pPkt = av_packet_alloc();//申请Packet资源  

 

if (!pPkt) {

return -1;

}

//编码参数设定  

pCodecCtx->codec_id = pOutputFmt->video_codec;   //编码类型对应的ID。  

pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;      //编码类型,音频、视频等等。  

pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;         //像素格式。  

pCodecCtx->width = nWidth;                       //宽  

pCodecCtx->height = nHeight;                     //高  

pCodecCtx->time_base.num = 1;                    //时间戳,分子  

pCodecCtx->time_base.den = 25;                   //时间戳,分母  

pCodecCtx->bit_rate = 400000;                    //比特率  

pCodecCtx->gop_size = 250;                       //连续的画面组  

pCodecCtx->qmin = 10;                            //最小量化参数  

pCodecCtx->qmax = 51;                            //最大量化参数  

pCodecCtx->max_b_frames = 3;                     //最大B帧  

 

 //Set Option  

AVDictionary *param = NULL;

//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);  

}

//H.265  

if (pCodecCtx->codec_id == AV_CODEC_ID_H265) {

av_dict_set(¶m, "preset", "ultrafast", 0);

av_dict_set(¶m, "tune", "zero-latency", 0);

}

// 用已有的AVCodec 初始化AVCodecContext  

if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0) {

//failed to open codec  

return -1;

}

 

pFrame = av_frame_alloc();//申请AVFrame  

if (!pFrame) {

fprintf(stderr, "Could not allocate the video frame data\n");

return -1;

}

pFrame->format = pCodecCtx->pix_fmt;

pFrame->width = pCodecCtx->width;

pFrame->height = pCodecCtx->height;

 

int ret = av_frame_get_buffer(pFrame, 32);//申请buffer大小。  

if (ret < 0) {

fprintf(stderr, "Could not allocate the video frame data\n");

return -1;

}

/*计算buffer大小*/

nFrameBufSize = av_image_get_buffer_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 1);

 

pFrameBuf = (unsigned char *)av_malloc(nFrameBufSize);

av_image_fill_arrays(pFrame->data, pFrame->linesize, pFrameBuf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 1);

 

nReadSize = pCodecCtx->width * pCodecCtx->height;

 

for (int i = 0; i < nFrameNum; i++) {

//读取YUV数据,读取大小为nReadSize  

if (fread(pFrameBuf, 1, nReadSize * 3 / 2, in_file) <= 0) {

//读取数据失败  

return -1;

}

else if (feof(in_file)) {

break;

}

 

ret = av_frame_make_writable(pFrame);//判断帧数据是否可写。  

if (ret < 0) {

return -1;

}

 

pFrame->data[0] = pFrameBuf;                    //Y  

pFrame->data[1] = pFrameBuf + nReadSize;           //U  

pFrame->data[2] = pFrameBuf + nReadSize * 5 / 4;   //V  

pFrame->pts = i;                                //PTS  

 

//encode  

encode(pCodecCtx, pFrame, pPkt, out_file);

}

 

//flush the encoder  

encode(pCodecCtx, NULL, pPkt, out_file);

 

//写数据  

fwrite(endcode, 1, sizeof(endcode), out_file);

 

avcodec_free_context(&pCodecCtx);

avformat_free_context(pFormatCtx);

av_frame_free(&pFrame);

av_packet_free(&pPkt);

av_free(pFrameBuf);

 

return 0;

}


你可能感兴趣的:(视频编解码)