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