top.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 2,300 行 · 第 1/4 页
C
2,300 行
#ifdef JPEG_DEC
JPG_start(is_jpeg);
#endif
}
/***************************************************************************
Start everything.
***************************************************************************/
void system_start()
{
ABV_start_filling();
#ifdef AVI_DEC
if (is_jpeg != 2)
#endif
VBV_start_filling();
#ifndef ZERO_BUFFER
#ifndef ECHO
/*
* With zero buffer, we only do PCM_start_take_out once, then
* it will be done continously without stopping.
*/
PCM_start_take_out();
#endif
#endif
}
/***************************************************************************
Video decoding task.
***************************************************************************/
static void TSK_decode_video(void)
{
if (vcx_playaudio_only
#ifdef FIXEFM
|| TDM_skip_sectors
#endif
) {
#ifdef ANTI_SHOCK
int delta;
/* For ANTISHOCK, the VBV is too big. Don't reset the VBV in
* VCD trick mode. Instead try to maintain 5:1 ratio of
* VBV_fullness to ABV_fullness.
*/
if (vcx_bitstream_type == MPEG1_PS) {
ABV_update_occupancy(ABV_fullness);
VBV_update_occupancy(VBV_fullness);
delta = (VBV_fullness/6 - ABV_fullness)/VBV_write;
if (delta < 0) delta = 0;
VBV_rdptr_advance(delta*VBV_write);
} else
#endif
{
VBV_rdptr = VBV_wrptr;
}
/* Need this since huffdec buscon never finish */
if (!VBV_filling) VBV_start_filling();
} else {
int error_code;
DBG_mark_current_time(2);
HUFF_switch_to_video();
#ifdef JPEG_DEC
error_code = (is_jpeg) ? VID_decode_jpeg() : VID_decode();
#else
error_code = VID_decode();
#endif
DBG_check_elapsed(2);
if (error_code
#ifdef ERROR_CONCEALMENT
|| VID_error_concealment
#endif
) {
#if defined(ERROR_CONCEALMENT) && !defined(USE_C2PO_MODE)
video_error++;
#endif
TDM_hw_error = 1;
KEYDEBUGINC(1, bad_video);
oh_my(1);
hardware_reset(1);
#ifdef ERROR_CONCEALMENT
VID_copy();
#endif
#ifdef VSCALE
/*
* To fix the checker board problem on playing
* scratch disc, we re-page the scaling ucode
* again if video error found.
*/
if (vcx_scn_vscale != 0x10) {
initVscale(disp_mem_mode);
}
#endif
#ifdef ERROR_CONCEALMENT
if (VID_error_concealment) {
VID_error_concealment = 0;
#if 0
VID_error_timeout = 1;
#endif
VID_load_quantizer(); /* for safety */
} else
#endif /* ERROR_CONCEALMENT */
{
VID_init();
}
}
}
}
/***************************************************************************
Audio decoding task.
***************************************************************************/
#ifdef TRACE_MP3_AUDIOBREAK
int mp3_error[20], error_num = 0;
#endif
void TSK_decode_audio(void)
{
#ifdef ANTI_SHOCK
if (TDM_isCDDA) {
/* do simultaneous ADPCM decoding and PCM volume adjustment */
ITU_decode();
return;
}
#endif ANTI_SHOCK
if (vcx_playvideo_only
#ifdef FIXEFM
|| TDM_skip_sectors
#endif
) {
ABV_rdptr = ABV_wrptr;
if (!ABV_filling) ABV_start_filling();
} else {
int status;
DBG_mark_current_time(1);
#ifdef AVI_DEC
if (STREAM_type != AVI_ID)
#endif
{
HUFF_wait_idle();
HUFF_switch_to_audio();
}
#ifdef MP3
if ((STREAM_type == MP3_ID) && (MPG_layer == 3)) {
#ifdef ID3
if (ID3_ABV_offset) {
/* ID3_ABV_offset already in DW */
dram_clear(ABV_start, ID3_ABV_offset);
/* Adjust ABV_rdptr in multiples of ABV_read size */
ABV_rdptr = ABV_start;
while (ID3_ABV_offset >= ABV_read) {
ABV_rdptr += ABV_read;
ID3_ABV_offset-=ABV_read;
}
ABV_byte_rdptr = dram(ABV_rdptr);
ID3_ABV_offset = 0;
}
#endif ID3
status = MP3_decode();
} else
#endif
#ifdef WMA_DEC
if (STREAM_type == WMA_ID) {
status = WMA_decode();
} else
#endif
#ifdef AVI_DEC
if (STREAM_type == AVI_ID) {
status = AVI_demux();
} else
#endif
status = AUD_decode();
DBG_check_elapsed(1);
/* We might not need this. Should think it thru carefully. */
if (status) {
KEYDEBUGINC(1, bad_audio);
oh_my(2);
/* hardware_reset(0); */
#ifdef TRACE_MP3_AUDIOBREAK
mp3_error[error_num] = status;
error_num++;
if (error_num > 19) error_num = 0;
#endif
#ifdef MP3
if ((STREAM_type == MP3_ID) && MPG_layer) MP3_start();
#endif
}
DBG_dump_pcm_when_full();
}
}
#ifdef KARAOKE
/***************************************************************************
key shifting task.
***************************************************************************/
static void TSK_karaoke(void)
{
int status;
DBG_mark_current_time(3);
status = karaoke_shift(&KARAvcd);
#ifndef ZERO_BUFFER
#ifndef ECHO
if (PCM_starved) {
PRINTF(("Manual PCM take out\n"));
PCM_take_out();
}
#endif
#endif
DBG_check_elapsed(3);
if (status) {
KEYDEBUGINC(1, bad_kara);
oh_my(3);
hardware_reset(0);
}
DBG_dump_pcm_when_full();
}
#endif
#ifdef ECHO
/***************************************************************************
ECHO task.
***************************************************************************/
static void TSK_echo(void)
{
DBG_mark_current_time(6);
ECHO_main(1);
DBG_check_elapsed(6);
}
#endif
/***************************************************************************
PCM encoding task.
***************************************************************************/
#ifdef ANTI_SHOCK
static void TSK_encode_audio(void)
{
REC_aud_channels = 2;
#ifdef NO_CDDA_COMPRESS
/* NO Compression */
REC_1to1_coder(ABV_rdptr, AS_ABV_wrptr);
AS_ABV_wrptr_advance(G721_CODING_SZ);
ABV_rdptr_advance(G721_CODING_SZ);
#else
/* default G.721 */
/* Compressing ABV_write blocks */
REC_4to1_coder(ABV_rdptr, AS_ABV_wrptr, 0);
AS_ABV_wrptr_advance(G721_CODING_SZ/4);
ABV_rdptr_advance(G721_CODING_SZ);
#endif
}
static void ITU_decode(void)
{
REC_aud_channels = 2;
#ifdef NO_CDDA_COMPRESS
REC_1to1_decoder(AS_ABV_rdptr, PCM_volume_start);
PCM_volume_adjust(PCM_volume_start, PCM_raw_wrptr);
AS_ABV_rdptr_advance(ABV_write);
#else
/* default G.721 */
REC_4to1_decoder(AS_ABV_rdptr, PCM_volume_start, 0);
PCM_volume_adjust(PCM_volume_start, PCM_raw_wrptr);
AS_ABV_rdptr_advance(ABV_write/4);
#endif /* NO_CDDA_COMPRESS */
PCM_raw_wrptr_advance(ABV_write);
PCM_fake_data = 0;
AUD_n_samples += ABV_write; /* n*ABV_write */
AUD_n_frames++;
}
#endif ANTI_SHOCK
/***************************************************************************
CDDA task.
***************************************************************************/
static void TSK_cdda(void)
{
int tmp;
DBG_mark_current_time(4);
PCM_volume_adjust(ABV_rdptr,PCM_raw_wrptr);
ABV_rdptr_advance(ABV_write);
PCM_raw_wrptr_advance(ABV_write);
PCM_fake_data = 0;
AUD_n_samples += ABV_write; /* n*ABV_write */
AUD_n_frames++;
#ifndef KARAOKE
#ifndef ZERO_BUFFER
#ifndef ECHO
if (PCM_starved) PCM_take_out();
#endif
#endif
#endif
DBG_check_elapsed(4);
}
#ifdef PRE_EMPHASIS
/* Defines for de-emphasis */
#define DM_OFFSETL 256 /* (32*16)/2 unit in words */
#define DM_OFFSETR 416 /* (32*26)/2 unit in words */
#define DP_OFFSETC 64*4 /* (128/2)*4 */
#define HIST_OFFSETL (32*16 + 64*4)/2
#define HIST_OFFSETR (32*26 + 64*4)/2
#endif
static void PCM_volume_adjust(int in, int out)
{
int tmp;
int HIST_inptr;
VP_load_ucode(rcdda);
VP_cmdq_wait(6+4+4+6); /* For the worst case */
VP_xfer(0, VPCMD_W_DP, 0, 0, in, ABV_write, 1);
VP_block_twice(0, UCODE_IDLE);
VP_cmdq_wait_empty;
mvd[riface_irqsuppress] = 0;
if (vcx_audio_channel < 2) {
VP_cmdq_wait(NCMDQ_VP_data + NCMDQ_VP_ucode + NCMDQ_VP_block_twice);
vp_data_only(vcx_audio_channel);
VP_ucode(0, VPCMD_WAIT + cdda_mono);
VP_block_twice(0, UCODE_IDLE);
}
/*
* If we are not in the middle of audio fade (i.e. vcx_fade_audio_volume
* is 0x8080, then use vcx_audio_volume to determine volume; otherwise,
* vcx_fade_audio_volume has the required volume value.
*/
tmp = (vcx_fade_audio_volume == 0x8080) ? vcx_audio_volume
: vcx_fade_audio_volume;
#if 0
{
int left = (tmp >> 10);
int right = ((tmp & 0xff) >> 2);
tmp = (left << 8) | right;
}
#endif
vp_data_only(tmp);
VP_ucode(0, VPCMD_WAIT + cdda_volume_control);
VP_block_twice(0, UCODE_IDLE);
#ifdef PRE_EMPHASIS
if (vcx_deemphasis) {
if (vcx_deemphasis_init) {
CDDA_init();
vcx_deemphasis_init = 0;
}
VP_load_ucode(rdemphasis);
VP_cmdq_wait(6+4+4+6);
HIST_inptr = EMPH_SAVE_start + 16;
/* DMA filter coefficients into DP */
VP_xfer(13*NCMDQ_VP_xfer, VPCMD_W_DP, DP_OFFSETC,
VPDMA_INC1+VPDMA_USEDX, EMPH_BP_start, EMPH_BP_size, 1);
/* DMA history data into DM */
VP_xfer(0, VPCMD_W_DPCM, DM_OFFSETL, VPDMA_INC1+VPDMA_USEDX,
EMPH_SAVE_start, 16, 1);
VP_xfer(0, VPCMD_W_DPCM, DM_OFFSETR, VPDMA_INC1+VPDMA_USEDX,
HIST_inptr, 16, 1);
/* Do demphasis bandpass filtering using VP microcode */
VP_ucode(0, demphasis);
wait4l_only; wait4l_only;
/* DMA out history */
VP_xfer(0, VPCMD_R_DPCM, HIST_OFFSETL, VPDMA_INC1+VPDMA_USEDX,
EMPH_SAVE_start, 16, 1);
VP_xfer(0, VPCMD_R_DPCM, HIST_OFFSETR, VPDMA_INC1+VPDMA_USEDX,
HIST_inptr, 16, 1);
/* DMA out output PCM data */
}
#endif
VP_xfer(0, VPCMD_R_DP, 0, 0, out, ABV_write, 1);
VP_block_twice(0, UCODE_IDLE);
VP_cmdq_wait_empty;
}
#ifndef VCDLC
/* For use in delay loops, etc.. for uninterrupted audio/video */
void AUD_service(void)
{
#ifdef ANTI_SHOCK /* for VCD antishock */
#ifdef JPEG_DEC
if(STREAM_type == JPEG_ID) return; /* not for JPEG */
#endif
/* use current_task so that watchdog can monitor */
current_task = what_to_do();
switch(current_task) {
case 1:
if (AUD_n_frames) {
/* Call this only after decoding has started..
* since we have VCD anti-shock, we need to call
* TSK_decode_audio() for HUFF_switch_to_audio(),etc..
* Previously, AUD_service() was only for audio decode.
*/
TSK_decode_audio();
}
break;
case 2:
TSK_decode_video();
break;
#ifdef KARAOKE
case 3:
TSK_karaoke();
break;
#endif
#ifdef VSCALE
case 5:
vscale2();
break;
#endif
#ifdef ECHO
case 6:
TSK_echo();
break;
#endif
case 7:
/* ADPCM encoding task */
TSK_encode_audio();
break;
default:
break;
}
current_task = 0;
#endif /* ANTI_SHOCK */
}
#endif /* !VCDLC */
#ifdef ERROR_CONCEALMENT
#if defined(DSC_ENABLE_C2PO) && defined(USE_C2PO_MODE)
void C2PO_error_mode()
{
/* Check the last 1 second for video error info, */
/* then set the concealment_mode on the fly */
if(((glbTimer - last_check_time) >= ONE_SECOND)||(concealment_mode==BLOCKY))
{
static int jerky_start_time;
/* We make the Jerky Keeping Time adaptive !! */
Time_K_Threshold = Time_K_Threshold>>1;
Time_K_Threshold += (C2PO_video_error>>1);
if(Time_K_Threshold<1) Time_K_Threshold = 2;
if(Time_K_Threshold>30) Time_K_Threshold = 30;
if ((C2PO_video_error > 0 /*VID_error_threshold*/) &&
/*(C2PO_video_error <= 30) &&*/ (picture_type == 0xe0))
{
/* This is due to too many C2PO_video_error (It is mare than
VID_error_threshold), so need to changed mode to JERKY
1. if Old Mode is BLOCKY, we need to record the time when
we switch to JERKY mode from BLOCKY
2. if Old Mode has already been JERKY, nothing to do */
if(concealment_mode==BLOCKY)
{
jerky_start_time = glbTimer;
/* Set the mode to JERKY */
concealment_mode = JERKY;
}
/* In case of continuous incoming C2PO, *
* move checking window by half length */
last_check_time = glbTimer - HALF_SECOND;
C2PO_video_error = VID_error_threshold / 2;
} else {
/* If the error is less the threshold, Just keep in BLOCKY mode */
last_check_time = glbTimer;
concealment_mode = BLOCKY;
C2PO_video_error =0;
}
/* Do not hold in jerky mode too long, let it show something */
if (glbTimer > jerky_start_time + TEN_SECOND*Time_K_Threshold)
{
last_check_time = glbTimer;
concealment_mode = BLOCKY;
C2PO_video_error =0;
}
}
}
#else
/****************************************************************
EC_Index is the index for JERKY & BLOCKY.
<-- More Blocky --- (+) --- More Jerky --->
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
EC_Index = 1: (Always Blocky)
EC_Index = 15: (Always Jerky)
EC_Index = 2,3,4: (More Blocky Less Jerky)
EC_Index = 5,6,7,8,9: (Average Blocky & Jerky)
EC_Index = 10,11,12,13,14: (Less Blocky More Jerky)
<1> Switch from JERKY to BLOCKY only based on frames elapsed.
<2> Switch from BLOCKY to JERKY when video_error larger than 4.
<3> Don't clear video_error when switch from BLOCKY to JERKY.
*****************************************************************/
void cust_error_mode()
{
int frame_interval;
extern int VID_frame_count;
if (error_concealment_mode != 0) { /* Not auto mode */
video_error = 0; /* need to be cleared */
return;
}
if (EC_Index <= 1 || EC_Index >= 15) {
/* To have a pure JERKY/BLOCKY mode for auto mode */
video_error = 0;
concealment_mode = (EC_Index <= 1) ? BLOCKY : JERKY;
return;
}
/* Adaptive switch between JERKY & BLOCKY */
if (concealment_mode == JERKY) { /* Jerky Mode */
frame_interval = VID_frame_count - last_check_frame;
/* Switch to BLOCKY after certain amount of time */
if (frame_interval >= (6 + EC_Index )) {
concealment_mode = BLOCKY;
video_error = 0;
last_check_frame = VID_frame_count;
}
} else { /* BLOCKY Mode */
/* Switch to JERKY when video_error larger than 4 and Don't clear
* the variable video_error.
*/
if (video_error >= 4) {
concealment_mode = JERKY;
last_check_frame = VID_frame_count;
}
}
}
#endif
#endif
/***************************************************************************
High priority background house-keeping.
***************************************************************************/
extern void CUST_background();
extern int microKeyPending();
extern char wait_pause;
void TSK_background_high_priority(void)
{
static uint tsk_timer;
static int count = 0;
/* No need to do it so frequently */
count++;
switch (count & 0x7) { /* 0,1,2,3,4,5,6,7,..(repeat) */
case 0:
if (!(count & 0x18)) { /* 1/4 of count & 7 = 0 */
#ifdef TWO_FIELDS_OSD
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?