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 + -
显示快捷键?