FFmpeg制作解码器

FFmpeg如何下载,简介,如何使用:

FFmpeg简介,下载_asiwxy的博客-CSDN博客

雷神代码用的FFmpeg版本比较老,在编译的时候一直弹被声明无效,这里将函数换成新的。

// FFmpegTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#define __SIDC_CONSTANT_MACROS
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
int main()
{
	AVFormatContext* pFormatCtx;
	int						i, videoindex;
	AVCodecContext* pCodeccCxt;
	AVCodec* pCodec;
	uint8_t* out_buffer;
	AVPacket* packet;
	AVFrame* pFrame, * pFrameYUV;
	int y_size;
	int ret, got_picture;
	struct SwsContext* img_convert_ctx;

	//输入文件路径
	char filepath[] = "Titanic.ts";

	int frame_cnt;


	avformat_network_init();
	pFormatCtx = avformat_alloc_context();//分配一个 AVFormatContext

	int rets = avformat_open_input(&pFormatCtx, filepath, NULL, NULL);

	if ( rets!= 0)
	{
		printf("Couldn't open input stream.rets = %d\r\n", rets);
		return 0;
	}
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
		printf("Couldn't find stream information.\n");
		return -1;
	}
	videoindex = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++)
	{
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoindex = i;
			break;
		}
	}
	if (videoindex == -1) {
		printf("Didn't find a video stream.\n");
		return -1;
	}

	pCodeccCxt = avcodec_alloc_context3(NULL);
	avcodec_parameters_to_context(pCodeccCxt, pFormatCtx->streams[videoindex]->codecpar);
	pCodec = avcodec_find_decoder(pCodeccCxt->codec_id);//查找解码器
	if (pCodec == NULL)
	{
		printf("Didn't find a video stream.\n");
		return -1;
	}
	if (avcodec_open2(pCodeccCxt, pCodec, NULL) < 0) {
		printf("Couldn't open codec.\n");
		return -1;
	}

	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();
	out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodeccCxt->width, pCodeccCxt->height,1));
	//ptr指向的数据填充到picture内,但并没有拷贝,只是将picture结构内的data指针指向了ptr的数据。
	av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer, AV_PIX_FMT_YUV420P, pCodeccCxt->width, pCodeccCxt->height,1);
	packet = (AVPacket*)av_malloc(sizeof(AVPacket));
	printf("--------------- File Information ----------------\n");
	av_dump_format(pFormatCtx, 0, filepath, 0);
	printf("-------------------------------------------------\n");
	img_convert_ctx = sws_getContext(pCodeccCxt->width, pCodeccCxt->height, pCodeccCxt->pix_fmt,
		pCodeccCxt->width, pCodeccCxt->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

	FILE* pfileYUV;
	fopen_s(&pfileYUV, "fileYUV.yuv", "wb+");
	FILE* pfileH264;
	fopen_s(&pfileH264,"fileH264.h264", "wb+");

	frame_cnt = 0;
	while (av_read_frame(pFormatCtx,packet) >= 0)//packet存放
	{
		if (packet->stream_index == videoindex)
		{
			/*
			 * 在此处添加输出H264码流的代码
			 * 取自于packet,使用fwrite()
			 */
			fwrite(packet->data, packet->size, 1, pfileH264);
			int ret = avcodec_send_packet(pCodeccCxt, packet);
			if (ret < 0)
			{
				printf("Decode Error.\n");
				return -1;
			}
			while(avcodec_receive_frame(pCodeccCxt, pFrame) == 0) {
				//读取到一帧音频或者视频
				//处理解码后音视频 frame

					sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodeccCxt->height,
						pFrameYUV->data, pFrameYUV->linesize);
					printf("Decoded frame index: %d\n", frame_cnt);

					/*
					 * 在此处添加输出YUV的代码
					 * 取自于pFrameYUV,使用fwrite()
					 */

						fwrite(pFrameYUV->data[0], pCodeccCxt->width * pCodeccCxt->height, 1, pfileYUV);
						fwrite(pFrameYUV->data[1], pCodeccCxt->width * pCodeccCxt->height/4, 1, pfileYUV);
						fwrite(pFrameYUV->data[2], pCodeccCxt->width * pCodeccCxt->height/4, 1, pfileYUV);

					frame_cnt++;
	
				av_packet_unref(packet);
			}
		}
	}
	sws_freeContext(img_convert_ctx);
	fclose(pfileH264);
	fclose(pfileYUV);
	av_frame_free(&pFrameYUV);
	av_frame_free(&pFrame);
	avcodec_close(pCodeccCxt);
	avformat_close_input(&pFormatCtx);
	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值