tdm.c

来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 957 行 · 第 1/2 页

C
957
字号
		     * we pause/FF/FB, we'll continue to get data from		     * the same neighborhood. If we don't skip the data,		     * we'll end up showing moving garbage all the time.		     * The "neighborhood" is usually no more than 40 secotrs		     * (that's why I set it to 40. You can adjust it		     * according to your loader behavior).		     */		    TDM_skip_sectors = 40;#endif /* FIXEFM */		    /* 		     * Current CD time should be equal to the		     * previous CD time + 1		     */		    TDM_expectBreak = 1;		    currCDtime = adjCDtime(prevCDtime, 1, 1);		    /*		     * There is a XPORT bug. When CD time is wrong,		     * it is usually due to one byte dropped from the		     * XPORT to RISC FIFO. In which case, the observation		     * told me that another byte will also be dropped.		     * Which usually means subheader will be gone too.		     * Therefore, the next word will be 1Ex/1C0. 		     * Let's read ahead and continue from there.		     */#ifdef XPORT11		    /* Prevent a bogus filenumber, use previous one */		    filenumber = TDM_tracknumber; #endif		    subheader = 0;	/* Assume subheader is 0 */		    while (argcnt) { 			packid = *pfifo++;			tmp = packid & 0xfff0;			/*			 * If we found pack ID, then continue from			 * there			 */			if ((tmp == 0x1c0) || (tmp == 0x1e0))			  goto error_recovery;			/*			 * Adjust argcnt late; if goto is taken, 			 * we'll decrement argcnt there!			 */			argcnt--;		    }		    return;		}	    }	}    }#ifdef XPORT20    /* Tell outside that XPORT has started copying. */    if (begCDtime == currCDtime) {	XPORT_active = 1;	TDM_found_begCDtime = 1;        TDM_hw_error = 0;    }        /*     * For 2.0 players, we are done if:     *	1) We match a user specified end location, or     *	2) We are at the end of CD     *     *  3) If XPORT stops from copying (to be extra cautious)     */    if (in_stop_state) {	/*	 * If XPORT stops, then regardless of what the currCDtime	 * is, just STOP! currCDtime may be wrong due to a variety	 * of reasons, but if XPORT is not copying, then don't	 * sit there and wait!	 *	 * This is an escape clause.	 */	/*	 * CDDA's copy_cdda is at the same location as STOP_STATE,	 * but we'll not get TDM interrupt for CDDA. However, we do	 * have to check XPORT_active since we may have stopped, then	 * we get an extra TDM interrupt.	 */	TDM_stop();    }    /*     * If disk is seriously scratched, currCDtime after a jump is     * not reliable. We shouldn't turn off CD accidentally by     * that value! We'll let the next sector to make the judgement.     */    if (((currCDtime >= endCDtime) || (currCDtime > second_endCDtime))) {	if(!CDtime_check(currCDtime)) { 	    if (currCDtime==endCDtime || TDM_prepare_stop || in_stop_state) {		/* 		 * We say if we get two times currCDtime >= endCDtime		 * or XPORT already stopped, TDM already get to the 		 * point that need stop 		 */		TDM_force_stop(0);	    } else TDM_prepare_stop = 1;	} else {	    /* "bad" currCDtime from some very scratchy disc can 	     * prematurely stop disc..increment by 1 frame.	     */	    currCDtime = adjCDtime(prevCDtime, 0x01, 1); 	}    } else TDM_prepare_stop = 0;#endif /* XPORT20 */    TDM_expectBreak = 0;	/* Next currCDtime should be sequential	*/    /* Return if there is nothing left in the FIFO */    if (!argcnt || !XPORT_active) return;#ifdef XPORT11    /*     * For 1.1 players, if the current sector is INFO.VCD, then the     * transport microcode will send us:     *	1) 2B of VCD version number     *	2) 4B of PSD size     *	3) 2B of maximum segment number     *	4) 2B for the first 2 segment play item bytes     */    if (currCDtime == 0x000400) {	if (argcnt == 5) {	    /* If number of item is not right, don't even process it! */	    unsigned int szPsd;	    unsigned short szSeg;	    unsigned short dataPSD;	    unsigned char seg1;	    vcdVersion = *pfifo++;	    vcdVersion += 0x3030;	/* From BCD to character */	    szPsd = ((unsigned int) (*pfifo++)) << 16;	    szPsd |= ((unsigned int) (*pfifo++));	    szSeg = *pfifo++;	    dataPSD = *pfifo++;	    seg1 = dataPSD >> 8;	    if ((vcdVersion == 0x3131) || (szPsd == 0)) {		/* If PSD size is 0, then then is 1.1 disc */		vcdVersion = 0x3131;		if (vcx_digest || skipTk1) TDM_send_skip = 1;	    }	    foundVCDversion = 1;	/* Found a new VCD version	*/	    tmp = 0x1e1;#ifdef E2E1_BASED_ON_1ST	    /* 	     * With E2E1_BASED_ON_1ST defined, we will miss E1 stills if	     * the 1st play item is an E2 still.	     *	     * Don't define E2E1_BASED_ON_1ST if your customer prefers not 	     * to miss any stills. But the limitation is that all the stills,	     * including "E2", will be shown in E1 resolution.	     */	    if (szSeg) {		/* 		 * If there are segments, we'll look at bits [4:2] by		 * masking other bits off. If the first segment play item		 * contents byte is 0x8 or 0x18, then we have high		 * resolution still (E2). Otherwise, assume low resolution		 * still (E1)		 */		if ((seg1 == (unsigned char) 0x8) ||		    (seg1 == (unsigned char) 0x18))		  tmp = 0x1e2;	    }#endif /* E2E1_BASED_ON_1ST */	    /* Reload PID to reflect E1/E2 requirement */	    XPORT_loadstill(tmp);	#if (P1O || P2O || P3O || P4O)	    keepStillType = tmp & 0xff;#endif	}	return;    }     /* If we get here, then we have file number! */    filenumber = *pfifo++;    argcnt--;#endif /* XPORT11 */    subheader = *pfifo++;    argcnt--;    /*      * If there is no packid, then we don't look at subheader info.     * In addition, if there is only 1 entry left, then it is CD     * time of the next sector. Don't read it!!     */    if (argcnt < 2) {#ifdef XPORT11	/*	 * When using XPORT11, we need to look at the filenumber here	 * because sometimes we are not getting 1Ex/1C0 yet we still	 * need to find the track number.	 */	if ((filenumber & 0xff00) == 0x200) {	    /* Mode byte has to be 2; otherwise, we ignore filenumber */	    TDM_tracknumber = filenumber & 0xff;	    if (TDM_most_recent_video & 0xf) {		/* 		 * We were playing still pictures. If we believe that		 * we have finished all the data, then skip to the next		 * track.		 */		if (skipTk1) {		    register unsigned int codeinfo = subheader & 0xff;		    if ((codeinfo != 0)		&&	/* Empty	*/			(codeinfo != 0xf)	&& 	/* E0		*/			(codeinfo != 0x1f)	&& 	/* E1/padding	*/			(codeinfo != 0x3f)	&&	/* E2		*/			(codeinfo != 0x7f)) {		/* Audio	*/			TDM_send_skip = !TDM_skip_sent;		    }		}	    }	}#endif	return;    }    tmp = subheader & 0x4eff;    if ((tmp != 0x420f) && (tmp != 0x447f)) {	/*	 * If subheader looks suspecious, then clear trigger bit and EOF.	 * This prevents false autopause.	 *	 * 620F is the usual submode/coding_info for video	 * 647f is the usual submode/coding_info for audio	 */	subheader &= (~(CDSUBMODE_T | CDSUBMODE_EOF));    }    packid = *pfifo++;  error_recovery:    argcnt --;    if ((packid & 0xff00) == 0) {	/* This is NOT pack ID!! To be on the safe side, just return */	return;    }    tmp = packid & 0xfff0;    if ((tmp == 0x1c0) || (tmp == 0x1e0)) {#if defined(DSC_ENABLE_C2PO) && !defined(ANTI_SHOCK)        if (C2PO_interrupt) {	    /*	     * If we have found a C2PO error since the last TDM interrupt,	     * then make a note if the data is audio so we can flush	     * ABV later.	     */	    C2PO_audio_error = (tmp == 0x1c0);	    if (tmp == 0x1e0) C2PO_video_error++;        }#endif	/* 	 * We only process subheader if packid checked OK (i.e. subheader	 * must be right)	 *//*#ifdef WATCHDOG*/#if 0	if (XPORT_start) {	    /* 	     * When we just start, there is a short period of time that	     * data starts to come in, but no huffman has completed.	     * If timer hit, the current longjmp algorithm will yank	     * us out. This is dangeous because we will miss the first	     * still picture. So I fake VBV_huffman_xfer_count to prevent	     * this long jump.	     */	    VBV_ABV_xport_xfer_count = VBV_ABV_huffman_xfer_count = 1;		    XPORT_start = 0;	}#endif#ifdef PLAY20	/*	 * If XPORT sees 000001b7, it'll do a CAM look up. Here, we check	 * the last matched CAM entry, if it is XPORT_PID_B7, then we know	 * that a 1b7 is found!	 */	if ((mvd[xport_read_cam_channel] & 0x1f) == XPORT_PID_B7)	  end_of_sequence = currCDtime;	if (subheader & CDSUBMODE_EOR) {	    if ((tmp == 0x1e0) && ((packid & 0xf) != 0)) {		end_of_still = 2;#ifdef JPEG_DEC		if (is_jpeg == 1) {		    TDM_needs_flush = 0;		    flush_thy_video = 2;		    dont_need_flush_video = 0;		}#endif	    }	}	/*	 * Usually when CDSUBMODE_T appears, it appears in consecutive CD	 * sectors.  Therefore, we need to set another flag such that once	 * we set the "trigger" bit, we'll not set it again within these 	 * consecutive sectors. In other words, we'll only stop once for 	 * a consecutive bunch of CDSUBMODE_T.	 */	if (set_trigger && (PBC_on#ifdef MIC_RECORD            || (REC_mode != REC_OFF)#endif	    )) {	    if (subheader & CDSUBMODE_T) {		/*		 * After seeing trigger bit, we set: VBV_trigger, 		 * VBV_trigger_ref, VBV_trigger_check, to mark 		 * when we should stop decoding.		 */		VBV_trigger = VBV_wrptr;		VBV_trigger_check = (VBV_trigger > VBV_rdptr);		VBV_trigger_ref = VBV_wrap_count;				TDM_trigger = 3;	/* Will be cleared when handled	*/		set_trigger = 0;	/* Don't set trigger again til	*					 * we are done with the		*					 * consecutive CDSUBMODE_T's	*/		trigger_time = glbTimer + FIVE_SECOND;#ifdef MIC_RECORD		if (REC_mode != REC_OFF) {		    if (disc_isFUDU) {			if (!repeat_a2b) {			    if (subheader & CDSUBMODE_A) {				if (auto_pause_state == 1) {				    rec_msf[1] = currCDtime;				    auto_pause_state = 2;				    TDM_trigger = 0;				} else if (auto_pause_state == 2) {				    rec_msf[2] = currCDtime;				    auto_pause_state = 0;				} else {				    rec_msf[0] = currCDtime;				    TDM_trigger = 0;				}			    } else if (subheader & CDSUBMODE_V) {				if (auto_pause_state == 0) {				    rec_msf[0] = currCDtime;				    auto_pause_state = 1;				    TDM_trigger = 0;				} else if (auto_pause_state == 1) {				    rec_msf[1] = rec_msf[2] = currCDtime;				} else if (auto_pause_state == 2) {				    rec_msf[2] = currCDtime;				    auto_pause_state = 1;				}			    }			} else {			    TDM_trigger = 0;			    set_trigger = 1;			}                    } else TDM_trigger = 0;		}#endif MIC_RECORD	    }	} else if (glbTimer > trigger_time)	  set_trigger = 1;	/* Ignore other triggers for 5 seconds	*/#endif /*  PLAY20 */#ifdef PLAYONLY	TDM_tracknumber = filenumber & 0xff;	/* Assign file number	*/	/* 	 * Record the last video type, so we can compare it with	 * keepStillType.	 */	if (tmp == 0x1e0) TDM_most_recent_video = packid & 0xff;	if (vcx_digest) {	    if (TDM_most_recent_video & 0xf) {		/*		 * No still picture inside digest.		 */		TDM_send_skip = !TDM_skip_sent;	    }	}	if (subheader & CDSUBMODE_EOR) {	    if ((TDM_most_recent_video == keepStillType) && !vcx_digest) {		/*		 * For 3208/3210, vcx_user_video_stream is set to		 * E2 during digest. However, we don't want to pause		 * and see 'SELECT' inside INTRO screen.		 */	        if ((tmp == 0x1e0) && ((packid & 0xf) != 0)) {		    end_of_still = 2;		}		osdSelect = pbcON;	/* Show "select" + pause */	    } else /* For E0, this means end of track in some disc  */	      end_of_track++;	} else if (subheader & CDSUBMODE_EOF) end_of_track++;#endif /* PLAYONLY */    }    /*     * argcnt can only be 1 (no PTS) or 3 (with PTS). No other value     * is expected.     */    if (argcnt == 3)      TDM_getPTS(pfifo, packid);}/* * Get Stream ID, PTS from the RISC fifo. * * Stream ID is always present (otherwise, this routine shouldn't be * called.) * * PTS is optionsl, so there are 3 possibilities: *	1) Neither PTS nor DTS:	 *		<junk:0xf> *	2) PTS only: *		<junk:PTS[4]> <PTS[3]:PTS[2]> <PTS[1]:PTS[0]> *	3) PTS + DTS, but XPORT sends in PTS only: *		<junk:PTS[4]> <PTS[3]:PTS[2]> <PTS[1]:PTS[0]> * Only case 2 and 3 will call this routine. * * Input: *	pfifo:  Pointer to the FIFO array *	packid:	Pack ID * * Return: *	None. */PRIVATE void TDM_getPTS(pfifo, packid)unsigned short *pfifo;unsigned short packid;{    unsigned short d1, d2, d3;    unsigned int pts;    static unsigned last_pts = 0;    /* PTS or PTS portion of PTS/DTS */    d1 = *pfifo++;    d2 = *pfifo++ & 0xfffe;    d3 = *pfifo++;	    /* Drop 1 least significant bits so our clock is 45000 Hz */    pts  = (d1 & 0xe) << 28;    pts |= (d2 << 13);    pts |= (d3 >> 2);		/* Drop 1 bit !! */    if (pts != last_pts) {    	last_pts = pts;	/* We only care about e0 and c0. */	if (packid == 0x1e0) {	    PTS_vid = pts;	} else if (packid == 0x1c0) {	    PTS_aud = pts;	} else	    return;	/* When the type of PTS change we take notice */	if (packid != PTS_last) {	    PTS_xsit++;	    PTS_last = packid;	}    }}

⌨️ 快捷键说明

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