FFmpeg的学习

FFmpeg的学习

使用版本:FFmpeg-4.2.2-win64-dev

FFmpeg库的介绍

  • avcodec:编码库
  • avformat:格式封装处理
  • avfilter:滤镜特效处理
  • avdevice:各种设备的输入输出
  • avutil:工具库
  • postproc:后加工
  • swresample:音频采样数据格式转换
  • swscale:视频像素数据格式转换

新版FFmpeg解码流程

源码函数流程

在这里插入图片描述

逻辑流程

在这里插入图片描述

新版FFmpeg最简解码

#include "stdafx.h"
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
#define __STDC_CONSTANT_MACROS
#define MICROSECOND_TO_SECOND 1000000

int _tmain(int argc, _TCHAR* argv[])
{
	//printf("%s", avcodec_configuration());//检查ffmpeg库是否配置好
	
	AVFormatContext *pFormatCtx = avformat_alloc_context();
	int video_index, i;
	AVCodecContext *pCodecCtx;
	AVCodec *pCodec;
	AVPacket *pPacket;
	AVFrame *pFrame, *pFrameYUV;
	uint8_t *out_buffer;
	struct SwsContext *img_convert_ctx;
	int frame_cnt = 0;
	char filepath[] = "./Titanic.ts";

	/*打开视频文件*/
	if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0){
		printf("Couldn't open input stream.\n");
		return -1;
	}

	/*获取视频文件信息*/
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
		printf("Couldn't find stream information.\n");
		return -1;
	}

	/*查找视频流*/
	video_index = -1;
	for (int i = 0; i < pFormatCtx->nb_streams; i++){
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
			video_index = i;
			break;
		}
	}

	if (video_index == -1){
		printf("Didn't find a video stream.\n");
		return -1;
	}

	/*获取编码器信息*/
	pCodecCtx = avcodec_alloc_context3(NULL);
	if (pCodecCtx == NULL)
	{
		printf("Could not allocate AVCodecContext\n");
		return -1;
	}
	avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[video_index]->codecpar);

	/*查找解码器*/
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL){
		printf("Codec not found.\n");
		return -1;
	}

	/*打开解码器*/
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
		printf("Could not open codec.\n");
		return -1;
	}

	/*打印视频信息*/
	printf("视频时长:%d s\n", pFormatCtx->duration / MICROSECOND_TO_SECOND);

	/*为缓存区分配内存,初始化*/
	pPacket = av_packet_alloc();
	pFrame = av_frame_alloc();
	pFrameYUV = av_frame_alloc();
	out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));
	av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
	
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

	/*解码*/
	while (av_read_frame(pFormatCtx, pPacket) >= 0){
		if (pPacket->stream_index == video_index){
			if (avcodec_send_packet(pCodecCtx, pPacket) == 0){
				while (avcodec_receive_frame(pCodecCtx, pFrame) == 0){
					int a = sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
					printf("Decoded frame index: %d\n", frame_cnt++);
					//输出画面
				}
			}
		}
	}

	/*关闭*/
	sws_freeContext(img_convert_ctx);
	av_frame_free(&pFrameYUV);
	av_frame_free(&pFrame);
	av_packet_free(&pPacket);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值