⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 player.cpp

📁 symbian下的FLV播放视频源码 可以快速便捷的播放FLV格式的视频
💻 CPP
字号:
#include "Player.h"
#include "YUVtoRGB.h"

int AVIdx, AVIdy;
AVCodecContext* avctx;
AVCodec* codec;
AVPicture avpict;
int SRCMAXLENGTH = 100000;
unsigned char* src;
bool is_decoded;
int numframeskipped;
bool g_CanAutoAlign;
int g_RectWidth, g_RectHeight;

CNeoFILE* g_NeoFile;

extern TFLVGlobalVar flvGlobalVar;

void OpenFlvAndInit(char* fname, MNeoStreamBufferManager* aNeoStreamBufferManager)
{
	libavcodec_init();
	ClearKeyFrame();
	
	numframeskipped = 0;
	is_decoded = false;

	src = (unsigned char*)malloc(SRCMAXLENGTH);
	memset(&avpict,0,sizeof(avpict));
	set_ff_idct((void*)1);
	
	g_NeoFile = CNeoFILE::NewL();
	g_NeoFile->FOpen(fname, EFileRead | EFileStream | EFileShareAny);
	unsigned char header_flag;
	flv_read_header(g_NeoFile, header_flag);
	int retType;
	ResetFrameRateAndCodecID();
	flv_read_if_metabody(g_NeoFile, retType);
	FLVCalculateFrameRate(g_NeoFile);
	InitVideoCodec(g_NeoFile);
	InitAudioCodec(g_NeoFile, aNeoStreamBufferManager);
	flv_read_pts(g_NeoFile, retType);
}

void PlayerSetRect(int width, int height)
{
	g_RectWidth = width;
	g_RectHeight = height;
	DestroyTransformTable();
}

int InitVideoCodec(CNeoFILE* aNeoFile)
{
	int retVal, buf_size, pts, retType;
	int pos = aNeoFile->FTell();

	while (true)
	{
		retVal = flv_read_next_packet(aNeoFile, src, buf_size, pts, retType);
		if (retVal)	// Have Error!
		{
			aNeoFile->FSeek(pos, SEEK_SET);
			return -1;
		}
		if (retType == FLV_TAG_TYPE_VIDEO)
		{
			switch (((src[3] & 0x03) << 1) + ((src[4] >> 7) & 0x01))
			{
			case 0:
				AVIdx = ((src[4] << 1) & 0xFE) + ((src[5] >> 7) & 0x01);
				AVIdy = ((src[5] << 1) & 0xFE) + ((src[6] >> 7) & 0x01);
				break;
			case 1:
				AVIdx = ((src[4] & 0x7F) << 9) + (src[5] << 1) + ((src[6] >> 7) & 0x01);
				AVIdy = ((src[6] & 0x7F) << 9) + (src[7] << 1) + ((src[8] >> 7) & 0x01);
				break;
			case 2:
				AVIdx = 352;
				AVIdy = 288;
				break;
			case 3:
				AVIdx = 176;
				AVIdy = 144;
				break;
			case 4:
				AVIdx = 128;
				AVIdy = 96;
				break;
			case 5:
				AVIdx = 320;
				AVIdy = 240;
				break;
			case 6:
				AVIdx = 160;
				AVIdy = 120;
				break;
			default:
				AVIdx = AVIdy = 0;
				break;
			}
			
			avctx = (AVCodecContext*)malloc(sizeof(AVCodecContext));
			memset(avctx, 0, sizeof(AVCodecContext));
			avctx->width  = AVIdx;
			avctx->height = AVIdy;

			codec = avcodec_find_decoder(CODEC_ID_FLV1);
			if (!codec)
			{
				aNeoFile->FSeek(pos, SEEK_SET);
				return -1;
			}

			if (avcodec_open(avctx, codec) < 0)
			{
				aNeoFile->FSeek(pos, SEEK_SET);
				return -1;
			}

			aNeoFile->FSeek(pos, SEEK_SET);
			return 0;
		}
	}
}

int InitAudioCodec(CNeoFILE* aNeoFile, MNeoStreamBufferManager* aNeoStreamBufferManager)
{
	int retVal, buf_size, pts;
	int pos = aNeoFile->FTell();
	uint32_t nSampleRate;
	uint32_t nChannels;
	int retType;

	while (true)
	{
		retVal = flv_read_next_packet(aNeoFile, src, buf_size, pts, retType, 0);
		if (retVal)	// Have Error!
		{
			aNeoFile->FSeek(pos, SEEK_SET);
			return -1;
		}
		if (retType == FLV_TAG_TYPE_AUDIO)
		{
			TAudioFrameInfo tAudioFrameInfo;
			CNeoStreamPlayer::GetMp3FrameInfo(src, buf_size-1, tAudioFrameInfo);
			nChannels = tAudioFrameInfo.iChannels;
			nSampleRate = tAudioFrameInfo.iSamplingRate;

			aNeoStreamBufferManager->InitStreamPlayer(nChannels, nSampleRate, 0);

			aNeoFile->FSeek(pos, SEEK_SET);
			return 0;
		}
	}
}

int FetchCodecAndDecode(int& pts, MNeoStreamBufferManager* aNeoStreamBufferManager)
{
	int got_picture = 0;
	int retVal = 0, buf_size;
	char nextvideofound = 0;//, nextaudiofound = 0;
//	int pos;
//	uint32_t nFrameLen;
	int retType;
	
	if (!is_decoded)
	{
		//pos = ftell(fp);
		while (!nextvideofound)
		{
			/*
			if (feof(fp))
				return -3;
			*/
			retVal = flv_read_next_packet(g_NeoFile, src, buf_size, pts, retType);
			if (retVal)	// Have Error!
				return -3;
			if (retType == FLV_TAG_TYPE_AUDIO)
			{
				//int nDataLen;
				//MP3_decode_frame(hMP3Dec, pcmdata, &nDataLen, src, buf_size);
				//aNeoStreamBufferManager->WriteBuffer(pcmdata, nDataLen);
				//aNeoStreamBufferManager->WriteBufferMP3(src, buf_size-1);
				retVal = 2;
			} else if (retType == FLV_TAG_TYPE_VIDEO)
			{
				nextvideofound = 1;
			}
		}
		if (nextvideofound)
		{
			if (src[0] != 0 || src[1] != 0 || (src[2] & 0xFC) != 0x84)
			{
				pts = flvGlobalVar.duration * 1000;
				return -3;
			}
			
			retVal = 0;
			avcodec_decode_video(avctx, &avpict, &got_picture, src, buf_size);
			if (!got_picture)
				return -1;
			is_decoded = true;
		}
	} else {
		retVal = -4;
	}
	
	return retVal;
}

int FetchCodecAndDecodeSoundOnly(int& aPts, MNeoStreamBufferManager* aNeoStreamBufferManager, long& aAudioCurrentFTell)
{
	int retVal = 0, buf_size;
	char nextaudiofound = 0;
	int pos;
	int retType;
	long nextPos;
	int pts;
	
	pos = g_NeoFile->FTell();
	g_NeoFile->FSeek(aAudioCurrentFTell, SEEK_SET);

	while (!nextaudiofound)
	{
		retVal = flv_read_next_packet_header(g_NeoFile, retType, nextPos, pts);
		if (retVal)	// Have Error!
		{
			aAudioCurrentFTell = g_NeoFile->FTell();
			g_NeoFile->FSeek(pos, SEEK_SET);
			return -1;
		}
		else if (pts > aPts)
		{
			// if current position of audio go after video then skip
			aAudioCurrentFTell = g_NeoFile->FTell();
			g_NeoFile->FSeek(pos, SEEK_SET);
			return -1;
		}
		else if (retType == FLV_TAG_TYPE_AUDIO)
		{
			retVal = flv_read_next_packet(g_NeoFile, src, buf_size, pts, retType);
			if (retVal)	// Have Error!
			{
				aAudioCurrentFTell = g_NeoFile->FTell();
				g_NeoFile->FSeek(pos, SEEK_SET);
				return -1;
			}
			aNeoStreamBufferManager->WriteBufferMP3((unsigned char*)src, buf_size-1);
			nextaudiofound = 1;
		}
		else if (retType == FLV_TAG_TYPE_META)
		{
			retVal = flv_read_next_packet(g_NeoFile, src, buf_size, pts, retType);
			if (retVal)	// Have Error!
			{
				aAudioCurrentFTell = g_NeoFile->FTell();
				g_NeoFile->FSeek(pos, SEEK_SET);
				return -1;
			}
		}
		else
		{
			g_NeoFile->FSeek(nextPos, SEEK_SET);
		}
	}	
	aAudioCurrentFTell = g_NeoFile->FTell();
	g_NeoFile->FSeek(pos, SEEK_SET);
	return 0;
}

int DoWithDecoded(unsigned char* dst, unsigned char no_pic, int first_frame_num, int first_frame_timestamp, int& frame_num, int now_timestamp)
{
	const int should_b_frame_num = first_frame_num + (now_timestamp - first_frame_timestamp) * flvGlobalVar.framerate * 0.000001;
	const int diff = frame_num - should_b_frame_num;
	
	if (diff > 0)
		return 0;
		
	if (!no_pic)
	{
		if (diff == 0)
		{
			if (g_RectWidth == AVIdx && g_RectHeight == AVIdy)
				ConvertYUV2BGRFast(avpict.data[0], avpict.data[1], avpict.data[2], dst, avpict.linesize[0], AVIdy, AVIdx);
			else			
				ConvertYUV2BGRNeoFast(avpict.data[0], avpict.data[1], avpict.data[2], dst, avpict.linesize[0], AVIdy, AVIdx, g_RectWidth, g_RectHeight);

			numframeskipped = 0;
		}
		else
		{
			numframeskipped++;
		}
	}

	is_decoded = false;
	frame_num++;

	return numframeskipped;
}

void Flv_GetNextFrame()
{
	
}

void CloseFlvAndDestroy()
{
	if (g_NeoFile)
	{
		delete g_NeoFile;
		g_NeoFile = NULL;
	}
	
	if (src)
	{
		free(src);
		src = NULL;
	}
	
	if (avctx)
	{
		avcodec_close(avctx);
		free(avctx);
		avctx = NULL;  
	}
	DestroyTransformTable();
}

void SeekFileTo(int position)
{
	if (g_NeoFile)
	{
		g_NeoFile->FSeek(position, SEEK_SET);
	}
}

int GetFirstKeyFramePositionBefore()
{
	if (g_NeoFile)
		return GetFirstKeyFramePositionBeforeFP(g_NeoFile);
	else
		return -1;
}

int GetFirstKeyFramePositionAfter()
{
	if (g_NeoFile)
		return GetFirstKeyFramePositionAfterFP(g_NeoFile);
	else
		return -1;
}

long CurrentFTell()
{
	if (!g_NeoFile)
		return 0;
	return g_NeoFile->FTell();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -