FFmpeg从缓存区获取数据再写入缓存区----视频解码

这里使用了FFmpeg部分库,但并没有按照input、find_steam…那个流程走,而是把自己缓存区的数据填充AVPacket 进行视频解码,然后再将数据存入缓存区。
FFmpeg.h

#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "swscale.lib")
#pragma comment(lib, "swresample.lib")

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
int DataHandle(unsigned char **cBufOut, unsigned char* cBufIn);
bool CreateDecoder(unsigned char **cBufOut, unsigned char* cBufIn);

FFmpeg.cpp

#include"FFmpeg.h"

//对socket接过来的数据进行处理
int DataHandle(unsigned char **cBufOut, unsigned char* cBufIn){

	return 1;
}

//对传入的视频进行解码
bool CreateDecoder(unsigned char **cBufOut, unsigned char* cBufIn)
{
	AVCodec *pVideoCodec;
	AVCodecContext *pCodecCtx;
	AVFrame *pFrameYUV;
	AVFrame *pFrame;
	AVPacket pktData;
	int nGopPicture;
	int iRetOpen;
	int iSize;
	int iRetDecode;
	int iHeight;
	int iWidth;
	struct SwsContext *SwrCtxVideo;
	
	//1.注册组件
	av_register_all();
	
	//2.确定解码的数据格式
	pVideoCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
	if (pVideoCodec == NULL) {
		printf("Codec not found\n");
		return false;
	}

	//3.存储对应流的解码信息
	pCodecCtx = avcodec_alloc_context3(pVideoCodec);
	if (pCodecCtx == NULL) {
		printf("avcodec_alloc_context3  err\n");
		return false;
	}

	//4.初始化参数,下面的参数应该由具体的业务决定  
	pCodecCtx->time_base.num = 1;
	pCodecCtx->frame_number = 1; //每包一个视频帧  
	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;//视频
	pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;//解码样式
	pCodecCtx->time_base.den = 228;//帧率--外部参数填充  
	pCodecCtx->width = 1280;//视频宽--外部参数填充  
	pCodecCtx->height = 720;//视频高--外部参数填充 

	//5.打开视频解码器
	iRetOpen=avcodec_open2(pCodecCtx, pVideoCodec, NULL);
	if (iRetOpen<0) {
		printf("Could not open codec\n");
		return false;
	}

	//6.设置视频参数
	//手动为 pFrameYUV分配数据缓存空间
	pFrameYUV = av_frame_alloc();
	uint8_t * VideoOutBuffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height));
	// 将分配的数据缓存空间和AVFrame关联起来
	avpicture_fill((AVPicture *)pFrameYUV, VideoOutBuffer, AV_PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);
	SwrCtxVideo = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
		pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUVJ420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);

	//7.填充的数据
	pFrame = av_frame_alloc();
	//仅仅是把pkt的参数设为默认值,要求pkt的内存已经分配好了,如果为NULL,则此处会崩溃
	nGopPicture = 1;
	av_init_packet(&pktData);
	pktData.size = 49152;//数据长度--外部参数填充
	//pktData.dts = cBuf[1];//解码时间戳--外部参数填充
	pktData.data = cBufIn;//原始数据--外部参数填充

	//8.该函数的作用是实现压缩视频的解码。 
	iRetDecode = avcodec_decode_video2(pCodecCtx, pFrame, &nGopPicture, &pktData);
	if (iRetDecode < 0) {
		printf("Decode Error.\n");
		return -1;
	}
	//9.解码成功
	if (nGopPicture) {
		sws_scale(SwrCtxVideo, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
			pFrameYUV->data, pFrameYUV->linesize);

		//外面申请内存  
		iHeight = pCodecCtx->height;
		iWidth = pCodecCtx->width;
		//写入数据  
		int iTemp = 0, i;
		for (i = 0; i<iHeight; i++)
		{
			memcpy(*cBufOut + iTemp, pFrameYUV->data[0] + i * pFrameYUV->linesize[0], iWidth);
			iTemp += iWidth;
		}
		for (i = 0; i<iHeight/2; i++)
		{
			memcpy(*cBufOut + iTemp, pFrameYUV->data[1] + i * pFrameYUV->linesize[1], iWidth /2);
			iTemp += iWidth/2;
		}
		for (i = 0; i<iHeight/2; i++)
		{
			memcpy(*cBufOut + iTemp, pFrameYUV->data[2] + i * pFrameYUV->linesize[2], iWidth /2);
			iTemp += iWidth/2;
		}

	}

	//10.释放资源
	av_free_packet(&pktData);
	av_free(VideoOutBuffer);
	av_frame_free(&pFrame);
	avcodec_close(pCodecCtx);
	return true;
}

main.c

#include"FFmpeg.h"
#include<iostream>


int main(int argc,char *argv[]) 
{
	unsigned  char *BufInt;
	BufInt = (unsigned  char *)malloc(5548016);

	int width = 1280;
	int height = 720;
	int picSize = width *height;
	int newSize = picSize * 1.5;
	unsigned char *BufOut = (unsigned  char *)malloc(newSize);

	//读数据
	FILE* fpH264 = fopen("tx.H.264","rb+");
	fread(BufInt, 49152,1,fpH264);
	//写数据
	FILE* fpOut=fopen("out.yuv","wb+");
	CreateDecoder(&BufOut, BufInt);
	fwrite(BufOut, newSize,1, fpOut);
	
	fclose(fpOut);
	fclose(fpH264);


	system("pause");
	return 0;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值