📄 asfvideocontrol.c
字号:
/********************************************************************************************
Copyright (C), 2007, Fuzhou Rockchip Co.,Ltd.
File:
AsfVideoControl.c
Description:
Asf video control.
Note:
None.
Author:
ljn
$Log: AsfVideoControl.c,v $
Revision 1.7 2008/07/03 07:48:12 HZF
退出显示最后一屏
Revision 1.6 2008/06/24 02:03:09 HZF
屏幕扩展优化
Revision 1.5 2008/06/19 04:42:31 Administrator
代码整理!
Revision 1.4 2008/06/12 03:05:37 HXY
提交nzy修改的Screen接口调用(增加TV-OUT版本)
Revision 1.3 2008/06/06 09:21:42 HJK
增加TVOUT功能
Revision 1.2 2008/05/24 09:35:26 HZF
WMV 7/8/9的支持;
Revision 1.1 2008/05/20 12:01:41 HZF
asf文件播放提交
********************************************************************************************/
#include "include.h"
#include "fs.h"
#include "hw_include.h"
#include "videowin.h"
#include "DualCoreApi.h"
#include "Mpeg4Contrl.h"
#include "AsfVideoControl.h"
#include "AsfFile.h"
#include "../VideoCodecs/VideoCodecs.h"
#define WMV3_RES_PATH "C:\\SYSTEM\\wmv3_tab.bin"
#define WMV2_RES_PATH "C:\\SYSTEM\\wmv2_tab.bin"
#define ASF_DEC_EXIT 2
#define ASF_FFD_FFW_MIN_INTERVAL 3000
#define ASF_TIME_OUT (0x2fffff)
#define ASF_TIMER_TICK 10
#define ASF_HURRY_MIN_DELAY 400
#define ASF_HURRY_UP_ADD_TIME 350
#define ASF_HURRY_UP_MAX_AHEAD 1500
unsigned int asfCurFrame, asfCurTime, lastSeekTime, timerCnt;
int asffilledBlock, dispYuvNum;
int asfTimeOut, hurry, videoDecErrCnt;
char *asfBitStreamBuf;
char *asfYuvBuf;
char *asfVideoBufRemain;
char *asfMbMvInfoBuf;
BACKGRND *asfVideoScreen;
DWDMALLP *asfVideoLLPList;
BACKGRND *asfVideoScreenTemp;
DWDMALLP *asfVideoLLPListTemp;
extern unsigned short *frameList;
extern int lastYuvBufId ;
extern __inline int AsfAudioSeek(int msTime);
extern __inline int AsfAudioGetCurTime(void);
extern BOOLEAN gSDModeFlag;
UINT16 gasfFunPmu;
static void AsfVideoHurryUp(void);
//int tempVal = 1;
//MY_FILE *pfBitStream;
static int WmvDecLoadRes(char *addr)
{
AsfFILE *pfRes = 0;
switch (asf.m_video_stream->m_type_specific.m_video.m_encoding)
{
case fccWMV3:
pfRes = AsfFopen(WMV3_RES_PATH, "rb");
break;
case fccWMV2:
case fccWMV1:
pfRes = AsfFopen(WMV2_RES_PATH, "rb");
break;
default:
return -1;
}
if (!pfRes)
return -1;
if (AsfFread(addr, 1, pfRes->FileSize, pfRes) <= 0)
return -1;
AsfFClose(pfRes);
return 0;
}
void AsfCtrlInit(void)
{
/* initialize share memory. */
ShareMemInit((unsigned int *)asfBitStreamBuf, (unsigned int *)asfYuvBuf, (unsigned int *)asfMbMvInfoBuf, 1, 0, 0);
/* get start address of frame list. */
frameList = (unsigned short *)GetFrameList();
asffilledBlock = 0;
asfCurFrame = 0;
asfCurTime = 0;
lastSeekTime = 0;
ffd_ffw_times = 0;
dispYuvNum = 0;
timerCnt = 0;
lastYuvBufId = -1;
//asfDispInterval = TIMER_ISR_NUM_PER_FRAME;
asfTimeOut = 0;
hurry = FALSE;
}
int AsfFillBitStream(void)
{
gulong size = BITSREAM_BUFFER_SIZE;
idx1 chunkInfo;
if ((asfPlayState == ASF_STATE_STOP) || (asfPlayState == ASF_STATE_INITIALIZING))
return 0;
if ((asfPlayState != ASF_STATE_PLAYING) && (!AllBufEmpty(asffilledBlock))) //use only one bit stream buf when ffd/ffw
{
return 0;
}
if (!AllBufFull(asffilledBlock))
{
asffilledBlock ++;
/* hurry up */
if (hurry == TRUE)
{
AsfVideoHurryUp();
}
if (AsfVideoGetDataToSDRAM(&asf, (char *)(asfBitStreamBuf + ((asffilledBlock - 1)&0xf)*BITSREAM_BUFFER_SIZE), &size))
{
if ((asfPlayState == ASF_STATE_FFD) || (asfPlayState == ASF_STATE_FFW))
{
asffilledBlock --;
return 0;
}
SendBlock(asffilledBlock);
SendLastBlockInfo(size);
return -1;
}
SendBlock(asffilledBlock);
}
return 0;
}
extern SCALEMODE ScreenMode;
extern INT16 ScreenModeSetSign ;
void AsfCreateVideoScreen(void)
{
int i, width = asf.m_width, height = asf.m_height;
for (i = 0; i < YUV_BUFFER_NUM; i++)
{
Screen_CreatVideo(&asfVideoScreen[i], &asfVideoLLPList[i*1000], (unsigned long)((unsigned long)(asfYuvBuf) + (unsigned long)(YUV_BUFFER_SIZE)*(unsigned long)(i)), width, height, FullScreen);
Screen_CreatVideo(&asfVideoScreenTemp[i], &asfVideoLLPListTemp[i*1000], (unsigned long)((unsigned long)(asfYuvBuf) + (unsigned long)(YUV_BUFFER_SIZE)*(unsigned long)(i)), width, height, LineArity);
}
Screen_CreatVideo(&asfVideoScreen[YUV_BUFFER_NUM], &asfVideoLLPList[YUV_BUFFER_NUM*1000], (unsigned long)((unsigned long)(asfYuvBuf) + (unsigned long)(YUV_BUFFER_SIZE)*(unsigned long)(YUV_BUFFER_NUM)), width, height, FullScreen);
}
void AsfTimerCallBack(void)
{
int audioTime;
if ((asfPlayState == ASF_STATE_STOP) || (asfPlayState == ASF_STATE_INITIALIZING))
{
return ;
}
timerCnt += ASF_TIMER_TICK;
if (IsYuvReady(asfCurFrame))
{
#if 0
/* Buffer ID in frame list is wrong. */
if (frameList[asfCurFrame] >= YUV_BUFFER_NUM)
{
return;
}
#endif
asfCurTime = GetFrameTime(asfCurFrame);
if (asfPlayState == ASF_STATE_PLAYING)
{
audioTime = AsfAudioGetCurTime();
if (!audioTime)
audioTime = timerCnt;
if ((audioTime) && (asfCurTime > (audioTime + asf.m_start_position_time)))
return;
/**********************************************
Skip frames control. We will skip 2 frames
when more than 150 ms are delayed.
***********************************************/
if ((audioTime + asf.m_start_position_time > asfCurTime + 150)
&& (GetDiscrepancy() < 2))
{
SendSkipFrameNum(2);
}
else if (audioTime + asf.m_start_position_time > asfCurTime + ASF_HURRY_MIN_DELAY)
{
/* start hurry-up mode to ensure picture-sound synchronization */
hurry = TRUE;
}
}
/* Change screen and update lcd. */
if (ScreenMode == FullScreen)
Screen_Change(&asfVideoScreen[frameList[asfCurFrame]]);
else if (ScreenMode == LineArity)
Screen_Change(&asfVideoScreenTemp[frameList[asfCurFrame]]);
#ifdef MCU_PANEL
while (Lcdctrl_GetStatus() == 1);
LCDC_UpDate();
#endif
if ((asfPlayState == ASF_STATE_FFW_TEMP) && (asfCurTime < asf.m_seek_seg.object_start + 1000))
asfPlayState = ASF_STATE_PLAYING;
/* Redress lcd update delay in the begining. */
if (dispYuvNum < 2)
{
dispYuvNum ++;
}
else
{
SendYuvFinish(asfCurFrame);
}
/* save last buffer id for video cap. */
lastYuvBufId = frameList[asfCurFrame];
/* Change to next. */
asfCurFrame = (++asfCurFrame) % YUV_BUFFER_NUM;
asfTimeOut = 0;
}
}
void AsfDecExit(void)
{
int timeOutCnt = 0;
if (asfPlayState == ASF_STATE_STOP)
return;
/* Stop frame display timer. */
Timer_PowerOffDeinit(0);
/* Close video file. */
AsfFileClose(&asf);
//RKFSFileClose(pfBitStream);
#if 1
if (asfPlayState != ASF_STATE_INITIALIZING)
{
/* set dsp nmi interrupt to exit. */
ClrRegBit32(0x1801c028, 16);
delay_nops(300);
SetRegBit32(0x1801c028, 16); /* nmi interrupt. */
delay_nops(2000);
ClrRegBit32(0x1801c028, 16);
/* wating for decoder exit. */
while ((GetDecStatus()) != ASF_DEC_EXIT)
{
delay_nops(300);
if ((timeOutCnt++) > 0x1ffff)
{
break;
}
}
}
#endif
asfPlayState = ASF_STATE_STOP;
/* Disable Dsp */
//PMU_ExitModule(PMU_VIDEOHIGH);
if (gSDModeFlag == 0)
{
if (gasfFunPmu == 2)
PMU_ExitModule(PMU_VIDEOMEDLOW);
else if (gasfFunPmu == 3)
PMU_ExitModule(PMU_VIDEOMED);
else if (gasfFunPmu == 4)
PMU_ExitModule(PMU_VIDEOMEDHIGH);
else if (gasfFunPmu == 5)
PMU_ExitModule(PMU_VIDEOHIGH);
else if (gasfFunPmu == 6)
PMU_ExitModule(PMU_VIDEOLOWL);
else if (gasfFunPmu == 7)
PMU_ExitModule(PMU_VIDEOLOWLL);
gasfFunPmu = 0;
}
else if (gSDModeFlag == 1)
{
PMU_ExitModule(PMU_VIDEOHIGH);
}
if ((asfYuvBuf == NULL) || (lastYuvBufId == -1))
return;
memcpy((asfYuvBuf+(YUV_BUFFER_NUM) * YUV_BUFFER_SIZE),(asfYuvBuf+(lastYuvBufId) * YUV_BUFFER_SIZE),YUV_BUFFER_SIZE);
Screen_Change(&asfVideoScreen[YUV_BUFFER_NUM]);
}
void AsfFrameDispCtrl(void)
{
/* set timer tick . */
StartHWVideoTimer(ASF_TIMER_TICK * 1000, AsfTimerCallBack);
}
int AsfIsLastFrame(void)
{
if ((asfPlayState != ASF_STATE_PLAYING) || (asfTimeOut++ > ASF_TIME_OUT)
|| (asfCurTime >= asf.m_time_stamp_bak - 200) || (GetDecStatus() == ASF_DEC_EXIT))
return 1;
return 0;
}
int AsfVideoDecBufMalloc(void)
{
#if 0 /* use malloc. */
if ((asfBitStreamBuf = MALLOC(BITSREAM_BUFFER_SIZE * MAX_BITSREAM_BLOCK_NUM)) == 0)
return -1;
if ((asfYuvBuf = MALLOC(YUV_BUFFER_NUM * YUV_BUFFER_SIZE)) == 0)
return -1;
//if((asfMbMvInfoBuf = MALLOC(((asf.width + 15)>>4)*((asf.height + 15)>>4)*32)) == 0)
// return -1;
if ((asfVideoScreen = (BACKGRND *)MALLOC(YUV_BUFFER_NUM * (sizeof(BACKGRND)))) == 0)
return -1;
if ((asfVideoLLPList = (DWDMALLP *)MALLOC(YUV_BUFFER_NUM * 1000 * (sizeof(DWDMALLP)))) == 0)
return -1;
#else /* use fixed buffer. */
/* bit stream buffer for video decoder. */
asfBitStreamBuf = gVideoBufferMix;
/* yuv buffer for decoder output. */
asfYuvBuf = gVideoBufferMix + (BITSREAM_BUFFER_SIZE * MAX_BITSREAM_BLOCK_NUM);
/* mb/mv information buffer for decoder. */
asfMbMvInfoBuf = asfYuvBuf + ((YUV_BUFFER_NUM+1) * YUV_BUFFER_SIZE);
/* video screen buffer for lcd update. */
asfVideoScreen = (BACKGRND *)(asfMbMvInfoBuf + (((asf.m_width + 15) >> 4) * ((asf.m_height + 15) >> 4) * 32));
/* dwdma llp list for each video screen. */
asfVideoLLPList = (DWDMALLP *)((char *)asfVideoScreen + ((YUV_BUFFER_NUM+1) * (sizeof(BACKGRND))));
asfVideoScreenTemp = (BACKGRND *)((char*)asfVideoLLPList + ((YUV_BUFFER_NUM+1) * 1000 * (sizeof(DWDMALLP))));
asfVideoLLPListTemp = (DWDMALLP *)((char *)asfVideoScreenTemp + (YUV_BUFFER_NUM * (sizeof(BACKGRND))));
/* buffer remain. */
asfVideoBufRemain = (char *)((char *)asfVideoLLPListTemp + (YUV_BUFFER_NUM * 1000 * (sizeof(DWDMALLP))));
#endif
return 0;
}
int AsfFileInit(char *path)
{
int err;
asfPlayState = ASF_STATE_INITIALIZING;
/* open video stream file. */
if (AsfFileOpen(&asf, path))
{
asfPlayState = ASF_STATE_STOP;
AsfFileClose(&asf);
return ASF_FILE_OPEN_ERR;
}
/* parse video file. */
if ((err = AsfFileParsing(&asf)))
{
if (err == ASF_FILE_AUDIO_CODEC_ERR) /* audio codec error is allowable. */
{
goto parse_ok;
}
AsfFileClose(&asf);
asfPlayState = ASF_STATE_STOP;
return err;
}
parse_ok:
/* load vld table for decoder. */
if (WmvDecLoadRes((char *)(gVideoBufferMix + SYSCFG_VIDEOBUF_LEN - (150*1024))))
{
AsfFileClose(&asf);
return ASF_FILE_OPEN_ERR;
}
return err;
}
int AsfVideoDecInit(void)
{
int i;
if (asfPlayState != ASF_STATE_INITIALIZING)
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -