ChinaFFmpeg

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 11786|回复: 2

[Windows] 直接向解码器按帧发送裸码流解码失败

[复制链接]
发表于 2017-5-16 15:28:54 | 显示全部楼层 |阅读模式
我这里是直接创建一个h264的解码器,然后从本地裸码流文件中按帧读取h264编码数据,然后赋值个avpacket,并传个解码器解码,不过一直都是显示的解码失败,不知道有什么地方不对的,请各位大神指点,谢谢!
源码如下:
[C++] 纯文本查看 复制代码

#include <stdio.h>

extern "C"
{
#include <libavcodec/avcodec.h>
};


#define ASSERT(X) if(!(X)){printf("####[%s:%d]assert failed:%s\n", __FUNCTION__, __LINE__, #X);}
#define _FILE_NAME_LEN 64		//长度文件名长度
#define _READ_BUF_SIZE (10<<20) //输入码流缓存大小
#define _FRAME_NUM	20			//码流帧数 
#define _VID_WIDTH 1920
#define _VID_HEIGHT 1080

int main()
{
	
	AVCodec* ptCodec = NULL;				//解码器
	AVCodecContext* ptCodecCtx = NULL;		//解码器上下文
	AVFrame* ptFrame = NULL;				//解码后帧
	AVPacket tPacket;						//待解码帧, 这里的tPacket得保证是完成的一帧
	
	//必须先注册编解码器之后, 才能查找解码器等操作
	avcodec_register_all();		

	//查找解码器
	enum AVCodecID	emCodecId = AV_CODEC_ID_H264;
	ptCodec = avcodec_find_decoder(emCodecId);
	ASSERT(ptCodec != NULL);

	ptCodecCtx = avcodec_alloc_context3(ptCodec);
	ASSERT(ptCodecCtx != NULL);
	
	ptCodecCtx->width = _VID_WIDTH;
	ptCodecCtx->height = _VID_HEIGHT;
	ptCodecCtx->coded_width = _VID_WIDTH;
	ptCodecCtx->coded_height = _VID_HEIGHT;
	ptCodecCtx->codec = ptCodec;
	ptCodecCtx->codec_type = ptCodec->type;

	printf("cur log level:%d\n", av_log_get_level());
	av_log(NULL, AV_LOG_ERROR,"ssssss\n");
	
	printf("codec:%p, %p codectype:%d\n", ptCodec, ptCodecCtx->codec, ptCodec->type);
	printf("coded_width:%d, coded_height:%d, (%d,%d)\n", 
		ptCodecCtx->coded_width,
		ptCodecCtx->coded_height, ptCodecCtx->width, ptCodecCtx->height);
	//初始化解码后ptFrame
	ptFrame = av_frame_alloc();
	ASSERT(ptFrame != NULL);
	
	//初始化解码前tPacket
	av_init_packet(&tPacket);

	const char* pszInputFileName = "1080P.h264";//输入为待解码码流文件
	const char* pszOutPutFileName = "1080P.yuv";//解码后图像保存文件
	
	char arbyInputLenFileName[_FILE_NAME_LEN];	//输入码流长度文件,按该文件数据读取固定长度码流为一帧
	memset(arbyInputLenFileName, 0, _FILE_NAME_LEN);
	sprintf(arbyInputLenFileName, "%s.len", pszInputFileName);
	printf("InputLenFileName:%s\n", arbyInputLenFileName);
	
	//打开输入码流文件
	FILE* pfInputFile = fopen(pszInputFileName, "rb");
	ASSERT(pfInputFile != NULL);
	//打开输入码流长度文件
	FILE* pfInputLenFile = fopen(arbyInputLenFileName, "rb");
	ASSERT(pfInputLenFile != NULL);
	//打开输出图像文件
	FILE* pfOutputFile = fopen(pszOutPutFileName, "wb");
	ASSERT(pfOutputFile != NULL);


	uint8_t* pbyInputbuf = new uint8_t[_READ_BUF_SIZE];		//输入码流缓冲
	memset(pbyInputbuf, 0, _READ_BUF_SIZE * sizeof(uint8_t));
	
	int* pbyPacketLen = new int[_FRAME_NUM];			//输入码流每帧长度数组
	memset(pbyPacketLen, 0, _FRAME_NUM * sizeof(int));

	//读取输入码流到buf中
	int dwRealBufSize = fread(pbyInputbuf, sizeof(uint8_t), _READ_BUF_SIZE, pfInputFile);
	printf("Read Buf Size:%d\n", dwRealBufSize);
	fclose(pfInputFile);
	pfInputFile = NULL;

	//获取实际输入码流帧数即每帧码流长度
	int dwRealFrameNum = 0;
	for (; dwRealFrameNum < _FRAME_NUM; dwRealFrameNum++)
	{
		fscanf(pfInputLenFile, "%d", &pbyPacketLen[dwRealFrameNum]);
		if (feof(pfInputLenFile))
		{
			//防止输入码流帧数比 _FRAME_NUM 少的情况
			fclose(pfInputLenFile);
			pfInputLenFile = NULL;
			delete []arbyInputLenFileName;
			break;
		}
	}
	
	tPacket.data = pbyInputbuf;
	tPacket.size = pbyPacketLen[0];
	for (int dwIdex = 0; dwIdex < dwRealFrameNum; dwIdex++)
	{
		
		printf("Idex:%d, FrameLen:%d\n", dwIdex, pbyPacketLen[dwIdex]);
		//fwrite(tPacket.data, 1, tPacket.size, pfOutputFile);
		av_log(NULL, AV_LOG_ERROR, "pbyInputbuf:%p,%p tPacket.data:%p, %p\n", 
			pbyInputbuf, pbyInputbuf+dwRealBufSize,
			tPacket.data, tPacket.data + pbyPacketLen[0]);

		int dwGotPicture = 0;
		int dwRet = avcodec_decode_video2(ptCodecCtx, ptFrame, &dwGotPicture, &tPacket);
		if (dwRet < 0)
		{
			printf("decoder error:%d, FrameNum:%d\n", dwRet, dwIdex);
			goto NEXT;
		}

		if (dwGotPicture)
		{
			printf("num:%d w:%d, h:%d, line:%d,%d,%d\n", dwIdex, ptFrame->width, ptFrame->height,
				ptFrame->linesize[0], ptFrame->linesize[1], ptFrame->linesize[2]);

			uint8_t* byTempPtr = NULL;
			byTempPtr = ptFrame->data[0];
			for (int dwHIdex = 0; dwHIdex < ptFrame->height; dwHIdex++)
			{
				fwrite(byTempPtr, 1, ptFrame->width, pfOutputFile);
				byTempPtr += ptFrame->linesize[0];
			}

			byTempPtr = ptFrame->data[1];
			for (int dwHIdex = 0; dwHIdex < ptFrame->height/2; dwHIdex++)
			{
				fwrite(byTempPtr, 1, ptFrame->width/2, pfOutputFile);
				byTempPtr += ptFrame->linesize[1];
			}

			byTempPtr = ptFrame->data[2];
			for (int dwHIdex = 0; dwHIdex < ptFrame->height/2; dwHIdex++)
			{
				fwrite(byTempPtr, 1, ptFrame->width/2, pfOutputFile);
				byTempPtr += ptFrame->linesize[2];
			}
		}
		else
		{
			printf("decoder failed:%d, FrameNum:%d\n", dwRet, dwIdex);
		}
NEXT:
		tPacket.data += pbyPacketLen[dwIdex];
		tPacket.size = pbyPacketLen[dwIdex+1];
	}
	fclose(pfOutputFile);


}



回复

使用道具 举报

发表于 2017-5-16 16:00:56 | 显示全部楼层
裸流有下载链接不,发给我看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-5-16 16:16:32 | 显示全部楼层
孙悟空 发表于 2017-5-16 16:00
裸流有下载链接不,发给我看看

码流是正确的, 忘avcodec_open2解码器了,这错误我也是服了自己了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|Archiver|ChinaFFmpeg

GMT+8, 2024-4-26 04:42 , Processed in 0.053104 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表