使用FFMpeg制作简易视频解码器

 av_dump_format()  打印关于输入或输出格式的详细信息,例如持续时间,比特率,流,容器,程序,元数据,边数据,编解码器和时基。其中最后一个参数is_output选择输出或是输入,最后一个参数填0,打印输入流,最后一个参数填1,打印输出流。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
}
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"swscale.lib")
int main()
{
	//定义文件名称
	FILE* f1 = fopen("www_y.yuv", "wb+");
	FILE* f2 = fopen("www_u.yuv", "wb+");
	FILE* f3 = fopen("www_v.yuv", "wb+");
	//测试DLL库是否成功
	printf("%s/n", avcodec_configuration());
	//注册DLL
	av_register_all();
	//网络
	avformat_network_init();
	AVFormatContext* pFormat = NULL;

	const char* path = "22.mp4";
	//打开视频文件
	int ret = avformat_open_input(&pFormat, path, NULL, NULL);
	
	if (ret) {
		printf("打开文件失败\n");
		return -1;
	}
	printf("打开文件成功\n");

	//寻找流信息
	ret = avformat_find_stream_info(pFormat, NULL);

	if (ret) {
		printf("打开流失败\n");
		return -1;
	}
	printf("打开流成功\n");

	
	av_dump_format(pFormat, NULL, path, 0);

	
	int VideoStream = -1, AudioStream = -1;

    //获取视频流
	VideoStream = av_find_best_stream(pFormat, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL);
	//解码器
	AVCodec* vCodec = avcodec_find_decoder(pFormat->streams[VideoStream]->codec->codec_id); 

	if (!vCodec) {
		printf("vCodec失败\n");
		return -1;
	}
	printf("vCodec成功\n");
	
	//打开解码器
	ret = avcodec_open2(pFormat->streams[VideoStream]->codec, vCodec, NULL);
	if (ret) {
		printf("解码器打开失败\n");
		return -1;
	}
	printf("解码器打开成功\n");

	//解码视频
	//创建帧空间
	AVFrame* frame = av_frame_alloc();
	AVFrame* frameYUV = av_frame_alloc();
	
    //拿取视频宽高
	int width = pFormat->streams[VideoStream]->codec->width;
	int height = pFormat->streams[VideoStream]->codec->height;
	printf("%d\n", width);
	printf("%d\n", height);
	int fmt = pFormat->streams[VideoStream]->codec->pix_fmt;
	//分配空间 进行图像转换
	int nSize = avpicture_get_size(AV_PIX_FMT_YUV420P, width, height);
	uint8_t* buff = NULL;
	buff = (uint8_t*)av_malloc(nSize);
	
	//一帧图像
	avpicture_fill((AVPicture*)frameYUV, buff, AV_PIX_FMT_YUV420P, width, height);

	AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));
	
	//转换上下文
	SwsContext* swsCtx = NULL;
	swsCtx = sws_getContext(width, height, (AVPixelFormat)fmt, width, height,
		AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

	//读帧
	int go = 0;
	int FrameCount = 0;
	while (av_read_frame(pFormat,packet) >= 0){
		 
		if (packet->stream_index == AVMEDIA_TYPE_VIDEO) {
			ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec, frame, &go, packet);
			if (ret < 0) {
				printf("读帧失败\n");
				return -1;
			}
			if (go) {
				//裁剪
			    sws_scale(swsCtx, (const uint8_t**)frame->data, frame->linesize,
				      0, height, frameYUV->data, frameYUV->linesize);
                //写入
				fwrite(frameYUV->data[0], 1, width * height, f1);
				fwrite(frameYUV->data[1], 1, width * height/4, f2);
				fwrite(frameYUV->data[2], 1, width * height/4, f3);
				FrameCount++;
				printf("帧数据:%d\n", FrameCount);
			}
		}

        //清除packet数据
		av_free_packet(packet);
	}
    
    //关闭及释放空间
	fclose(f1);
	fclose(f2);
	fclose(f3);
	sws_freeContext(swsCtx);
	av_frame_free(&frame);
	av_frame_free(&frameYUV);
	avformat_close_input(&pFormat);

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值