ffmpeg编码示例

// ffmpegTest.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include "windows.h"
#include "time.h"

#include <avformat.h>
#include <avutil.h>
#include <avcodec.h>
#include <swscale.h>
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")

void SaveBmp(AVCodecContext *CodecContex, AVFrame *Picture, int width, int height);

#define MAX_BUF_SIZE 256*1024	
int main(int argc, char* argv[])
{
	int ret=-1, i=0, videoindex=-1, nComplete=0, len=0, frame_index=0;
	unsigned char *pEnCodeBuf = new unsigned char[MAX_BUF_SIZE];
	char *sourceFile = "5.avi";
	char *destFile = "123.mp4";
	av_register_all();
		
	AVFormatContext *pInputFormatContext=NULL;
	AVCodec *pInputCodec = NULL;
	AVCodecContext *pInputCodecContext = NULL;
	AVPacket InPack;
	int videoWidth, videoHeight;

	AVOutputFormat *pOutputFmt = NULL;
	AVFormatContext *pOutFormatContext = NULL;
	AVCodecContext *pOutCodecContext = NULL;
	AVCodec *pOutCodec = NULL;
	AVStream *pOutStream = NULL;
	AVPacket OutPack;
	AVFrame OutFrame;
	if(av_open_input_file(&pInputFormatContext, sourceFile, NULL, 0, NULL) !=0 )
	{
		//打开输入文件
		printf("can't open the file %s\n",sourceFile);
		exit(1);
	}

	if(av_find_stream_info(pInputFormatContext)<0)
	{
		//查找流信息
		printf("can't find suitable codec parameters\n");
		goto lk_error;
	}
	
	for(i=0; i<pInputFormatContext->nb_streams; i++)
	{
		if(pInputFormatContext->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
		{
			videoindex=i;
			break;
		}
	}

	if(-1 == videoindex)
	{
		//没有找到视频流
		goto lk_error;
	}
	
	pInputCodecContext = pInputFormatContext->streams[videoindex]->codec;
	pInputCodec = avcodec_find_decoder(pInputCodecContext->codec_id);
	if(NULL == pInputCodec)
	{
		//没有找到解码器
		goto lk_error;
	}
	if(avcodec_open(pInputCodecContext, pInputCodec) != 0)
	{
		//打开解码器失败
		goto lk_error;
	}

	videoWidth = pInputCodecContext->width;
	videoHeight = pInputCodecContext->height;

	pOutputFmt = guess_format(NULL, destFile, NULL);
	if(NULL == pOutputFmt)
	{
		//分析输出文件格式失败
		goto lk_error;
	}

	pOutFormatContext = av_alloc_format_context();
	if(NULL == pOutFormatContext)
	{
		goto lk_error;
	}

	pOutFormatContext->oformat = pOutputFmt;
	pOutStream = av_new_stream(pOutFormatContext, 0);
	if(NULL == pOutStream)
	{
		//创建流失败
		goto lk_error;
	}
	
	//设定转换编码参数
	pOutCodecContext = pOutStream->codec;
	pOutCodecContext->codec_id = CODEC_ID_MPEG4;
	pOutCodecContext->codec_type = CODEC_TYPE_VIDEO;
	pOutCodecContext->bit_rate = 98000;
	pOutCodecContext->width = videoWidth;
	pOutCodecContext->height = videoHeight;
	pOutCodecContext->time_base = pInputCodecContext->time_base;
	pOutCodecContext->gop_size = pInputCodecContext->gop_size;
	pOutCodecContext->pix_fmt = pInputCodecContext->pix_fmt;
	pOutCodecContext->max_b_frames = pInputCodecContext->max_b_frames;
	pOutCodecContext->time_base.den = 15;
	pOutCodecContext->time_base.num = 1;
	pOutStream->r_frame_rate = pInputFormatContext->streams[videoindex]->r_frame_rate;

	if (av_set_parameters(pOutFormatContext, NULL) < 0) 
	{
		//转换编码参数设置不正确
		goto lk_error;                               
	}
	
	strcpy(pOutFormatContext->title, pInputFormatContext->title);
	strcpy(pOutFormatContext->author, pInputFormatContext->author);
	strcpy(pOutFormatContext->copyright, pInputFormatContext->copyright);
	strcpy(pOutFormatContext->comment, pInputFormatContext->comment);
	strcpy(pOutFormatContext->album, pInputFormatContext->album);
	pOutFormatContext->year = pInputFormatContext->year;
	pOutFormatContext->track = pInputFormatContext->track;
	strcpy(pOutFormatContext->genre, pInputFormatContext->genre);

	pOutCodec = avcodec_find_encoder(CODEC_ID_MPEG4);
	if(NULL == pOutCodec)
	{
		//找不到指定编码器
		goto lk_error;
	}
	
	if(avcodec_open(pOutCodecContext, pOutCodec) < 0)
	{
		//打开指定编码器错误
		goto lk_error;
	}
	
	if (!(pOutFormatContext->flags & AVFMT_NOFILE))
	{
		if(url_fopen(&pOutFormatContext->pb, destFile, URL_WRONLY)<0)
		{
			//打开输出文件
			goto lk_error;
		}
	}

	if(av_write_header(pOutFormatContext) < 0)
	{
		//写入输出文件头失败
		goto lk_error;
	}

	while(av_read_frame(pInputFormatContext, &InPack) >= 0)
	{
		len = avcodec_decode_video(pInputCodecContext, &OutFrame, &nComplete, InPack.data, InPack.size);
		if(nComplete > 0)
		{
			//解码一帧成功
			SaveBmp(pInputCodecContext, &OutFrame, videoWidth, videoHeight);
			memset(pEnCodeBuf, 0, MAX_BUF_SIZE);
			OutFrame.pts = av_rescale(frame_index, AV_TIME_BASE*(int64_t)pOutCodecContext->time_base.num, pOutCodecContext->time_base.den);
			OutFrame.pict_type = 0;
			len = avcodec_encode_video(pOutCodecContext, pEnCodeBuf, MAX_BUF_SIZE, &OutFrame);   
			if (len > 0)            
			{  
				av_init_packet(&OutPack);                               
				if(pOutCodecContext->coded_frame && pOutCodecContext->coded_frame->key_frame)                                       
				{
					OutPack.flags |= PKT_FLAG_KEY;                                        
				}

				OutPack.flags = InPack.flags;                      
				OutPack.stream_index = InPack.stream_index;                                               
				OutPack.data = pEnCodeBuf;                                                         
				OutPack.size = len;                                             
				ret=av_write_frame(pOutFormatContext, &OutPack);                                       
			}
			frame_index++;
		}
		av_free_packet(&OutPack);
	}
	
	av_write_trailer(pOutFormatContext);
	for(i=0; i<pOutFormatContext->nb_streams; i++) 
	{            
		av_freep(&pOutFormatContext->streams[i]->codec);                       
		av_freep(&pOutFormatContext->streams[i]);                           
	}

lk_error:
	av_free(pOutCodec);
	av_free(pOutputFmt);
	avcodec_close(pInputCodecContext);
	av_free(pInputFormatContext);
	av_free(pOutFormatContext);

	return 0;
}

void SaveBmp(AVCodecContext *CodecContex, AVFrame *Picture, int width, int height)
{
	AVPicture pPictureRGB;//RGB图片

	static struct SwsContext *img_convert_ctx;
	img_convert_ctx = sws_getContext(width, height,	CodecContex->pix_fmt, width, height,\
		PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
	avpicture_alloc(&pPictureRGB, PIX_FMT_RGB24, width, height);
	sws_scale(img_convert_ctx, Picture->data, Picture->linesize,\
		0, height, pPictureRGB.data, pPictureRGB.linesize);
	
	int lineBytes = pPictureRGB.linesize[0], i=0;
	
	char fileName[1024]={0};
	time_t ltime;
	time(<ime);
	sprintf(fileName, "%d.bmp", ltime);
	
	FILE *pDestFile = fopen(fileName, "wb");
	BITMAPFILEHEADER btfileHeader;
	btfileHeader.bfType = MAKEWORD(66, 77); 
	btfileHeader.bfSize = lineBytes*height; 
	btfileHeader.bfReserved1 = 0; 
	btfileHeader.bfReserved2 = 0; 
	btfileHeader.bfOffBits = 54;

	BITMAPINFOHEADER bitmapinfoheader;
	bitmapinfoheader.biSize = 40; 
	bitmapinfoheader.biWidth = width; 
	bitmapinfoheader.biHeight = height; 
	bitmapinfoheader.biPlanes = 1; 
	bitmapinfoheader.biBitCount = 24;
	bitmapinfoheader.biCompression = BI_RGB; 
	bitmapinfoheader.biSizeImage = lineBytes*height; 
	bitmapinfoheader.biXPelsPerMeter = 0; 
	bitmapinfoheader.biYPelsPerMeter = 0; 
	bitmapinfoheader.biClrUsed = 0; 
	bitmapinfoheader.biClrImportant = 0;

	fwrite(&btfileHeader, 14, 1, pDestFile);
	fwrite(&bitmapinfoheader, 40, 1, pDestFile);
	for(i=height-1; i>=0; i--)
    {
		fwrite(pPictureRGB.data[0]+i*lineBytes, lineBytes, 1, pDestFile);
	}

	fclose(pDestFile);
	avpicture_free(&pPictureRGB);
}

以下是一个基本的 ffmpeg 编码示例,可以将 FIFO 中的视频信息放入编码器: ```c #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> int main(int argc, char *argv[]) { AVFormatContext *format_context; AVCodecContext *codec_context; AVCodec *codec; AVPacket packet; AVFrame *frame; int stream_index; int ret; // 打开输入 FIFO ret = avformat_open_input(&format_context, "input.fifo", NULL, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not open input FIFO\n"); return ret; } // 查找输入流信息 ret = avformat_find_stream_info(format_context, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not find stream information\n"); return ret; } // 查找视频流 stream_index = av_find_best_stream(format_context, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0); if (stream_index < 0) { av_log(NULL, AV_LOG_ERROR, "Could not find video stream in input file\n"); return stream_index; } // 打开视频解码器 codec_context = avcodec_alloc_context3(codec); if (!codec_context) { av_log(NULL, AV_LOG_ERROR, "Could not allocate codec context\n"); return AVERROR(ENOMEM); } ret = avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not copy codec parameters to codec context\n"); return ret; } ret = avcodec_open2(codec_context, codec, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Could not open codec\n"); return ret; } // 分配视频帧内存 frame = av_frame_alloc(); if (!frame) { av_log(NULL, AV_LOG_ERROR, "Could not allocate frame\n"); return AVERROR(ENOMEM); } // 初始化 AVPacket av_init_packet(&packet); packet.data = NULL; packet.size = 0; // 读取 FIFO 中的视频信息 while (av_read_frame(format_context, &packet) >= 0) { // 将 AVPacket 转换为 AVFrame ret = avcodec_send_packet(codec_context, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error sending packet to codec\n"); break; } while (ret >= 0) { ret = avcodec_receive_frame(codec_context, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; else if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error receiving frame from codec\n"); break; } // 在这里将 AVFrame 写入编码器 } av_packet_unref(&packet); } // 清理 av_frame_free(&frame); avcodec_free_context(&codec_context); avformat_close_input(&format_context); return 0; } ``` 在上面的代码中,`av_read_frame()` 函数从 FIFO 中读取一个 `AVPacket`,然后将其发送到编码器。编码器使用 `avcodec_receive_frame()` 函数将 `AVPacket` 转换为 `AVFrame`,然后在代码中的注释部分,可以将 `AVFrame` 写入编码器中。注意,这里仅仅是一个编码示例,实际上如何将 `AVFrame` 写入编码器中取决于你使用的编码器和编码设置。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值