📄 player.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 + -