ffmpeg视频转码示例

extern "C"
{
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")

#include<iostream>
#include<queue>
using namespace std;

void Time_base(AVPacket * pkt, AVFormatContext* &ic, AVFormatContext* &oc)
{
	pkt->pts = av_rescale_q_rnd(pkt->pts,
		ic->streams[pkt->stream_index]->time_base,
		oc->streams[pkt->stream_index]->time_base,
		(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)
	);
	pkt->dts = av_rescale_q_rnd(pkt->dts,
		ic->streams[pkt->stream_index]->time_base,
		oc->streams[pkt->stream_index]->time_base,
		(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)
	);
	pkt->pos = -1;
	pkt->duration = av_rescale_q_rnd(pkt->duration,
		ic->streams[pkt->stream_index]->time_base,
		oc->streams[pkt->stream_index]->time_base,
		(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)
	);
}

int Open_In_fine(const char*  infile, int& videoidx, int& audioidx, AVFormatContext* &ic)
{
	avformat_open_input(&ic, infile, 0, 0);
	if (!ic)
	{
		//cout << "avformat_open_input failed!" << endl;
		return -1;
	}
	for (int i = 0; i < ic->nb_streams; i++)
	{
		if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
			videoidx = i;
		if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
			audioidx = i;
	}
	if (videoidx == -1)
	{
		//cout << "Codec find failed!" << endl;
		return -1;
	}
	if (audioidx == -1)
	{
		//cout << "Codec find failed!" << endl;
		return -1;
	}

	av_dump_format(ic, 0, infile, 0);
	return 0;
}

int Open_out_file(const char*  outfile, int& videoidx, int& audioidx, AVStream *videoStream, AVStream *audioStream, AVCodecContext* &encodec_video, AVCodecContext* &encodec_audio, AVFormatContext* &oc)
{
	avformat_alloc_output_context2(&oc, NULL, NULL, outfile);
	if (!oc)
	{
		cout << avformat_alloc_output_context2 << endl;
		cin.get();
	}
	if (videoidx != -1) {
		videoStream = avformat_new_stream(oc, NULL);
		avcodec_parameters_from_context(videoStream->codecpar, encodec_video);
		videoStream->codecpar->codec_tag = 0;
	}
	if (audioidx != -1) {
		audioStream = avformat_new_stream(oc, NULL);
		avcodec_parameters_from_context(audioStream->codecpar, encodec_audio);
		audioStream->codecpar->codec_tag = 0;
	}
	av_dump_format(oc, 0, outfile, 1);
	int ret = avio_open(&oc->pb, outfile, AVIO_FLAG_WRITE);
	if (ret < 0)
	{
		cout << avio_open << endl;
		cin.get();
	}
	ret = avformat_write_header(oc, NULL);
	if (ret < 0)
	{
		cout << "avformat_write_header" << endl;
		cin.get();
	}
	return 0;
}
bool open_encodec(AVCodecContext* &encodec, AVCodec* &enc, AVCodecParameters *& codecpar) {
	enc = avcodec_find_encoder(AV_CODEC_ID_H264);
	if (!enc) {
		cout << "Find Decoder failed!" << endl;
		cin.get();
	}
	encodec = avcodec_alloc_context3(enc);
	encodec->bit_rate = 1000;					//压缩比特率  越大文件越大
	encodec->codec_type = AVMEDIA_TYPE_VIDEO;
	encodec->width = codecpar->width;			//视频宽
	encodec->height = codecpar->height;			//视频高
	encodec->time_base = {1,25};				//时间基 设置可能会出现警告
	encodec->framerate = { 25,1 };				//设置帧率 (和时间基准相反  可能被抛弃)
	encodec->gop_size = 30;						//设置画面组大小(关键帧 多少帧一帧,I贞)
	encodec->max_b_frames = 30;					//设置b帧(b帧越多压缩率越高)
	encodec->pix_fmt = AV_PIX_FMT_YUV420P;
	encodec->codec_id = AV_CODEC_ID_H264;
	encodec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;//AV_CODEC_FLAG2_LOCAL_HEADER;//在每个关键帧放置全局标题,而不是在extradata中。
	encodec->thread_count = 4;					//ffmpeg新转码函数支持多线程 配置线程个数
	if (encodec->codec_id == AV_CODEC_ID_H264)
	{
		//encodec->qmin = 10;
		//encodec->qmax = 51;
		//encodec->qcompress = 0.6;
	}
	if (encodec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
		encodec->max_b_frames = 2;
	if (encodec->codec_id == AV_CODEC_ID_MPEG1VIDEO)
		encodec->mb_decision = 2;

	int ret = avcodec_open2(encodec, enc, NULL);
	if (ret < 0) {
		cout << "avcodec_open2" << endl;
		cin.get();
	}
	return 0;
}
bool open_decodec(AVCodecContext* &decodec, AVCodec* &c, AVCodecID& codecID) {
	c = avcodec_find_decoder(codecID);
	if (!c) {
		cout << avcodec_find_decoder << endl;
		cin.get();
	}
	int ret = avcodec_open2(decodec, c, NULL);
	if (ret < 0) {
		cout << "avcodec_open2" << endl;
		cin.get();
	}
	return 0;
}

int open_decodec(AVCodecContext * &decodec, AVFormatContext * ic, int videoidx, AVCodec * &dec)
{
	
	decodec = avcodec_alloc_context3(NULL);
	if (avcodec_parameters_to_context(decodec, ic->streams[videoidx]->codecpar) < 0)
	{
		cout << "Copy stream failed!" << endl;
		return -1;
	}
	dec = avcodec_find_decoder(decodec->codec_id);
	if (!dec) {
		cout << "Find Decoder failed!" << endl;
		return -1;
	}
	// 打开解码器
	if (avcodec_open2(decodec, dec, NULL) != 0) {
		cout << "Open codec failed!" << endl;
		return -1;
	}
	
	return true;
}

int main(){
	char path[] = "11.mp4";			//输入视频文件
	char outfile[] = "Test.flv";	//输出视频文件
	int videoidx = -1;				//视频索引标志
	int audioidx = -1;				//音频索引标志
	AVFormatContext *ic = nullptr;	//输入上下文
	AVFormatContext *oc = nullptr;	//输出上下文
	AVStream *videoStream = nullptr;//给输出上下文添加的视频流
	AVStream *audioStream = nullptr;//给输出上下文添加的音频流
	AVCodecContext *decodec_video = nullptr;	//解码器上下文_视频
	AVCodecContext *encodec_video = nullptr;	//编解码器上下文_视频
	AVCodec *enc = nullptr;			//编码器
	AVCodec *dec = nullptr;			//解码器


	
	
	Open_In_fine(path, videoidx, audioidx, ic);

	open_encodec(encodec_video, enc, ic->streams[videoidx]->codecpar);

	open_decodec(decodec_video, ic, videoidx, dec);

	Open_out_file(outfile, videoidx, audioidx, videoStream, audioStream, encodec_video,ic->streams[audioidx]->codec, oc);

	//FILE *fp_yuv = fopen("test_out123.yuv", "wb+");
	//int y_size = decodec->width*decodec->height;
			//fwrite(inyuv->data[0], 1, y_size, fp_yuv);        // Y 
			//fwrite(inyuv->data[1], 1, y_size / 4, fp_yuv);    // U
			//fwrite(inyuv->data[2], 1, y_size / 4, fp_yuv);    // V
			//cout << "pkt->size ="<<pkt->size<<endl;
	while (true) {
		AVPacket* pkt = av_packet_alloc();
		av_init_packet(pkt);
		AVFrame *inyuv = av_frame_alloc();
		
		if (!(av_read_frame(ic, pkt) >= 0)) {
			break;
		}
		if (pkt->stream_index == videoidx) {
			
			int iRes;
			if ((iRes = avcodec_send_packet(decodec_video, pkt)) != 0)
			{
				cout << "Send video stream packet failed!" << iRes << endl;
				continue;
			}
			if ((iRes = avcodec_receive_frame(decodec_video, inyuv)) != 0)
			{
				cout << "Receive video frame failed!" << iRes << endl;
				continue;
			}
			
			iRes = avcodec_send_frame(encodec_video, inyuv);
			if (iRes < 0)
			{
				cout << "编码错误" << endl;
				continue;
				cin.get();
			}
			AVPacket* outpkt = av_packet_alloc();
			while (iRes >= 0)
			{
				
				iRes = avcodec_receive_packet(encodec_video, outpkt);
				if (iRes == AVERROR(EAGAIN) || iRes == AVERROR_EOF)
					continue;
				else if (iRes < 0)
				{
					fprintf(stderr, "Error during encoding\n");
					exit(1);
				}
				Time_base(outpkt, ic, oc);
				av_write_frame(oc,outpkt);
				cout << iRes << "**********************" << endl;
				printf("Write packet %3lld(size=%5d)\n", outpkt->pts, outpkt->size);
				
				
			}
			av_packet_free(&outpkt);
			//av_packet_free(&pkt);
			av_frame_free(&inyuv);
		}
		
		if (pkt->stream_index == audioidx) {
			Time_base(pkt, ic, oc);
			av_write_frame(oc,pkt);
			//av_packet_free(&pkt);
		}
			
		av_packet_free(&pkt);
		
	}
	av_write_trailer(oc);

	//cin.get();
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值