nav_svcd.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:253k
源码类别:

DVD

开发平台:

Others

  1.  /* **************************************************************************************
  2.  *  Copyright (c) 2002 ZORAN Corporation, All Rights Reserved
  3.  *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
  4.  *
  5.  *  File: $Workfile: nav_svcd.c $             
  6.  *
  7.  * Description:
  8.  * ============
  9.  * SVCD Navigator implementation
  10.  * 
  11.  * Log:
  12.  * ====
  13.  * $Revision: 131 $
  14.  * Last Modified by $Author: Leslie $ at $Modtime: 04-04-03 13:35 $ 
  15.  ****************************************************************************************
  16.  * Updates:
  17.  ****************************************************************************************
  18.  * $Log: /I76/I76_Common/I76_Reference/Playcore/Nav_SVCD/nav_svcd.c $
  19.  * 
  20.  * 131   04-04-03 14:06 Leslie
  21.  * Set initial Drive MSF when start a new playback
  22.  * 
  23.  * 130   04-04-01 23:38 Leslie
  24.  * Change type definition
  25.  * 
  26.  * 129   4/01/04 10:50p Johnk
  27.  * support HW POWER_ON_RESUME 
  28.  * 
  29.  * 128   04-04-01 17:14 Williaml
  30.  * it can't play from a accurate REPA point time when RepAB function in
  31.  * use
  32.  * 
  33.  * 127   04-04-01 15:41 Hansenw
  34.  * fix OSD flashes 00:00 at  repeat AB
  35.  * 
  36.  * 126   04-03-30 16:13 Williaml
  37.  * set the play mode to normal from program, intro or shuffle after full
  38.  * stop
  39.  * 
  40.  * 125   04-03-30 11:08 Williaml
  41.  * Merge the latest code for K1
  42.  * 
  43.  * 124   3/28/04 9:08p Nmaurer
  44.  * Rename to drv_bin2bcd
  45.  * 
  46.  * 123   3/25/04 11:36p Johnk
  47.  * merged the latest code for S1
  48.  * 
  49.  * 122   04-03-24 15:09 Angieh
  50.  * For Alco,support previous func when play the first track.
  51.  * 
  52.  * 121   3/11/04 3:31p Terencet
  53.  * add check for VCD version2.0
  54.  * 
  55.  * 120   04-03-09 18:52 Angieh
  56.  * Add SVCD_DIGEST_SUPPORT macro.
  57.  * 
  58.  * 119   2/27/04 5:20p Johnk
  59.  * Merged  the latest S1 changes
  60.  * 
  61.  * 118   2/24/04 3:05p Robinj
  62.  * Patch SVCD with MPEG1 format
  63.  * when "STOP", change g_disc_type to DEC_DISC_TYPE_VCD
  64.  * 
  65.  * 117   2/20/04 6:19p Glenl
  66.  * Merged S1 code
  67.  * 
  68.  * 116   2/20/04 4:34p Leonh
  69.  * not start stucktrigger for cdda on vcd
  70.  * 
  71.  * 115   2/16/04 5:13p Lyncolnc
  72.  * Merged S1 Changes.
  73.  * 
  74.  * 114   1/25/04 8:22 Nmaurer
  75.  * Add drv_ prefix to Drive routines
  76.  * 
  77.  * 113   11/28/03 5:49p Fwang
  78.  * Detect squence header on menu also.
  79.  * 
  80.  * 112   11/26/03 11:05p Leslie
  81.  * Re-Schedule StuckTrigger bit when peform error recovery
  82.  * 
  83.  * 111   11/26/03 11:10a Leslie
  84.  * Don't do byte swap for getting Segment Start Address
  85.  * 
  86.  * 110   11/19/03 11:40a Leslie
  87.  * Add sampling rate detection for SVCD discs
  88.  * 
  89.  * 109   11/03/03 4:09p Leslie
  90.  * Fix playback out of range proble when do sequence header detection for
  91.  * Entry Items
  92.  * 
  93.  * 108   10/15/03 8:46a Leslie
  94.  * Remove Karaoke Recording
  95.  * 
  96.  * 107   9/29/03 11:59a Chaol
  97.  * 
  98.  * 106   9/05/03 11:58a Mikex
  99.  * make the repeat mark B point not at the last 2 second of current track
  100.  * signature: MikeX_0905_2003_A
  101.  * 
  102.  * 105   03-08-29 0:02 Leslie
  103.  * Code cleanup
  104.  * 
  105.  * 104   8/27/03 7:04p Mikex
  106.  * Add the recovery error mechanism in digest mode.
  107.  * Signature: mikex_0827_2003_a
  108.  * 
  109.  * 103   8/27/03 3:51p Leonh
  110.  * avoid black back ground when digest with PBC ON
  111.  * 
  112.  * 102   8/21/03 7:43p Mikex
  113.  * roll back mikex_0821_2003_b change, because this bug was fixed by
  114.  * deleting the repeat single choice on mode menu and run time mode menu.
  115.  * 
  116.  * 101   8/21/03 1:29p Mikex
  117.  * Add a judgement for the single repeat on OnNextItem function
  118.  * 
  119.  * 100   8/21/03 10:55a Mikex
  120.  * add a delay on digest mode after canceling the AB repeat
  121.  * 
  122.  * 99    03-08-17 18:51 Leslie
  123.  * Add comments
  124.  * 
  125.  * 98    03-07-28 17:03 Leslie
  126.  * Check in changes for Task Force
  127.  * 
  128.  * 97    03-07-17 14:37 Mikelv
  129.  * Using a more accurate condition "iCurrentTime == 10" to judge the
  130.  * finish of playing a item in intro mode,instead of the previous
  131.  * condition "iCurrentTime > 10" 
  132.  * 
  133.  * 96    03-07-16 17:59 Mikelv
  134.  * If current played item is the first one in the program list,then
  135.  * prohibit skipb operation,as customer required. 
  136.  * 
  137.  * 95    03-07-11 18:13 Mikelv
  138.  * pause not cancel intro mode(request by vestel)
  139.  * 
  140.  * 94    03-07-11 16:57 Mikelv
  141.  * donnot clear intro mode at some state(skip,skipb,scan,ect.)
  142.  * 
  143.  * 93    03-07-08 20:48 Tonnyg
  144.  * no skipfb if repeat single and PBC on
  145.  * 
  146.  * 92    03-07-04 15:11 Mikelv
  147.  * For svcd using pts to measure time,we also need to update current entry
  148.  * number.
  149.  * 
  150.  * 91    03-06-25 11:40 Hannahh
  151.  * 
  152.  * 90    03-06-19 17:40 Hannahh
  153.  * 
  154.  * 89    03-06-19 10:43 Mikelv
  155.  * For a playlist,if itemcnt is 0,should jump to next list
  156.  * 
  157.  * 88    03-06-18 22:15 Mikelv
  158.  * 
  159.  * 87    03-06-17 19:58 Fwang
  160.  * 
  161.  * 86    03-06-17 16:43 Mikelv
  162.  * remove patch for setting TV_SYS_AUTO problem
  163.  * 
  164.  * 85    03-06-17 15:00 Fwang
  165.  * Optimize NVM_BMK parameter.
  166.  * 
  167.  * 84    03-06-16 21:55 Mikelv
  168.  * 
  169.  * 83    03-06-12 11:12 Fwang
  170.  * Elapsed time by PTS
  171.  * 
  172.  * 82    03-06-10 21:54 Leslie
  173.  * Fix the type conversion problem when calculating playsectors for
  174.  * laylist Playtime.
  175.  * 
  176.  * 81    03-06-09 15:13 Mikelv
  177.  * When bookmark encountered,PE_CD_AbortPlayback() was called and the
  178.  * current time went to zero,at this time,continuely pressed repAB,it will
  179.  * set bookmarkA at 00:00:00,and it is not right.So,prohibit setting
  180.  * bookmarkA at time 00:00:00.
  181.  * 
  182.  * 80    03-06-05 14:51 Mikelv
  183.  * Enlarge the least time for repeatAB
  184.  * 
  185.  * 79    03-06-04 21:05 Mikelv
  186.  * 
  187.  * 78    6/04/03 3:32p Clifflv
  188.  * add mute for amplifier
  189.  * 
  190.  * 77    03-06-03 17:51 Fwang
  191.  * Cancel scan mode when enter digest.
  192.  * 
  193.  * 76    03-06-02 18:24 Fwang
  194.  * Set NVM bookmark by parameter
  195.  * 
  196.  * 75    03-05-29 11:34 Leslie
  197.  * Handle DVP Decoding stucking
  198.  * 
  199.  * 74    03-05-28 11:19 Fwang
  200.  * Specified auto postion in NVM_BMK_SET()
  201.  * 
  202.  * 73    03-05-28 9:40 Fwang
  203.  * Set bookmark type in NVM_BMK_SET()
  204.  * 
  205.  * 72    03-05-27 22:44 Fwang
  206.  * Add NVM bookmark
  207.  * 
  208.  * 71    03-05-23 22:49 Leslie
  209.  * Enable Watchdog for still picture presentation
  210.  * 
  211.  * 70    03-05-22 11:48 Leslie
  212.  * Add jmp table for error recovery
  213.  * Code cleanup
  214.  * 
  215.  * 69    03-05-21 21:41 Leslie
  216.  * Notify UI operation error for time search if time is invalid
  217.  * 
  218.  * 68    03-05-16 22:20 Leslie
  219.  * New error recovery implementation
  220.  * 
  221.  * 67    5/15/03 9:13a Tonnyg
  222.  * enable disc search when PBC on for s/vcd.
  223.  * 
  224.  * 66    03-04-29 22:32 Leslie
  225.  * Add Entry Information parse
  226.  * 
  227.  * 65    03-04-23 11:41 Mikelv
  228.  * if play mode changed,clear the bookmarks.
  229.  * 
  230.  * 64    03-04-17 17:51 Tonnyg
  231.  * fix the bug that can't set A-B after set A/A-B then repeat single 
  232.  * 
  233.  * 63    03-04-17 15:45 Tonnyg
  234.  * add prohibit information display to illegal selection
  235.  * 
  236.  * 62    03-04-17 14:51 Tonnyg
  237.  * Prohibit pre/next when repeat single, just jump to the beginning, same
  238.  * as DVD.
  239.  * 
  240.  * 61    03-04-09 20:04 Leslie
  241.  * 
  242.  * 60    03-04-07 14:48 Billt
  243.  * don't cancel repeat when play from stopresume
  244.  * 
  245.  * 59    03-03-26 16:45 Hannahh
  246.  * 
  247.  * 58    03-03-26 11:21 Leslie
  248.  * Fix the Slow Backward Track boundary problem
  249.  * 
  250.  * 58    03-03-22 17:40 Leslie
  251.  * Fix Slow Backward Track boundary problem
  252.  * 
  253.  * 57    03-03-15 20:33 Leslie
  254.  * 
  255.  * 56    03-03-13 15:15 Leslie
  256.  * Fix SVCD Slow/Fast back problem on boundary of tracks
  257.  * 
  258.  * 56    3/03/03 7:02p Rinata
  259.  * Update g_pSVCDNav->m_dwSecondTrackAddress before return when VCD is
  260.  * detected on scratch disc
  261.  * 
  262.  * 55    03-03-03 10:35 Leslie
  263.  * 
  264.  * 54    03-02-28 14:55 Leslie
  265.  * Set correct list item number when switch from PBC on to off
  266.  * 
  267.  * 53    03-02-27 15:13 Leslie
  268.  * Update with ZCH change
  269.  * 
  270.  * 54    2/26/03 9:50p Rinata
  271.  * fixed calculation of wTotalElpasedTime 
  272.  * 
  273.  * 53    03-02-24 14:19 Hannahh
  274.  * Replace printf to debug
  275.  * 
  276.  * 52    03-02-24 14:09 Hannahh
  277.  * Replace printf to debug
  278.  * 
  279.  * 51    2/21/03 7:19a Stephaneh
  280.  * Added functions to access SVCD navigator variables from UI, in order to
  281.  * check zoom availability (especially during SVCD menu)
  282.  * 
  283.  * 50    03-02-18 10:34 Leslie
  284.  * Support SVCD Total elapsed time
  285.  * 
  286.  * 49    2/07/03 10:48p Tomasp
  287.  * - changed SW feature selection to compilation switch
  288.  * - code clean up
  289.  * 
  290.  * 48    03-01-28 2:26 Leslie
  291.  * Support DISC_TRACK_DIGEST_VIEW_ENABLE mode
  292.  * Using Sc-Pad instead of Heap to save memory for Digest Mode
  293.  * 
  294.  * 47    03-01-24 20:33 Leslie
  295.  * Support Intro Play Mode for VCD/SVCD/CVD
  296.  * 
  297.  * 46    1/23/03 4:28a Rinata
  298.  * Change Dacs API name and add more Dacs support
  299.  * 
  300.  * 45    03-01-14 1:41 Leslie
  301.  * Fix Slow Reverse problem
  302.  * 
  303.  * 44    03-01-10 12:23 Leslie
  304.  * Update with File-System Change
  305.  * 
  306.  * 43    12/09/02 6:12p Leslie
  307.  * Code cleanup
  308.  * 
  309.  * 42    11/29/02 7:44a Leslie
  310.  * Infor Error to UI if Return operation is not valid
  311.  * 
  312.  * 41    11/13/02 10:48a Leslie
  313.  * Set the right Audio SID for VCD Entry items playback
  314.  * 
  315.  * 40    11/10/02 10:10a Leslie
  316.  * Fix Slow-Rev->Pause->Play freezing problem
  317.  * 
  318.  * 39    10/30/02 19:14 Yarone
  319.  * change error recovery print to tr
  320.  * 
  321.  * 38    10/30/02 17:49 Rond
  322.  * 
  323.  * 68    4/06/02 10:14 Nirm
  324.  * - Corrected COP_MASK handling for NEXT: should only be during PBC-Off.
  325.  * 
  326.  * 67    2/06/02 15:46 Nirm
  327.  * - Allowed time-display during MPEG-2 segments.
  328.  * 
  329.  * 66    27/05/02 18:21 Nirm
  330.  * - Cleaned-up compilation-warnings.
  331.  * 
  332.  * 65    27/05/02 10:46 Ettim
  333.  * Changed the number of available bookmarks to 5.
  334.  * 
  335.  * 64    5/16/02 11:43a Dingming
  336.  * fix the svcd total time problem
  337.  * 
  338.  * 63    15/05/02 9:23 Ettim
  339.  * Removed some compilation warning messages.
  340.  * 
  341.  * 62    13/05/02 20:18 Nirm
  342.  * - Expilict casting of some fields, to prevent unwanted trancation.
  343.  * 
  344.  * 61    12/05/02 17:53 Ettim
  345.  * Disabling zoom when playing CDDA tracks (Bug #198).
  346.  * Cancle any ongoing zoom when returning to still menu (Bug #197).
  347.  * 
  348.  * 60    5/10/02 12:15p Dingming
  349.  * fix shuffle stuck problem
  350.  * 
  351.  * 59    9/05/02 18:22 Ettim
  352.  * Enabled Next on Repeat All from the last track back to the first track.
  353.  * (Bug #240)
  354.  * 
  355.  * 58    9/05/02 15:48 Ettim
  356.  * Emulating an EndList to overcome authoring errors.
  357.  * 
  358.  * 57    5/08/02 10:12a Dingming
  359.  * support disc time search(required by china customer)
  360.  * 
  361.  * 56    7/05/02 17:55 Nirm
  362.  * - Automatic cancellation of A-B Repeat upon invocation of Digest.
  363.  * 
  364.  * 55    7/05/02 16:41 Ettim
  365.  * Added PowerOnResume playback support.
  366.  * 
  367.  * 54    6/05/02 14:30 Ettim
  368.  * Added Remaining time value.
  369.  * 
  370.  * 53    29/04/02 18:53 Nirm
  371.  * - Code cleanup.
  372.  * 
  373.  * 52    23/04/02 14:42 Ettim
  374.  * Performing Prev in a play list when the current item is not the first
  375.  * one, even if Prev Offset is 0xFFFF (Added switch
  376.  * SVCD_FORCE_PERVIOUS_ITEM)
  377.  * 
  378.  * 51    23/04/02 9:35 Nirm
  379.  * - Added dependency in "Config.h".
  380.  *
  381.  * 50    22/04/02 18:43 Ettim
  382.  * Fixing some bugs reported by FFM:
  383.  * =============================
  384.  * Clearing Scan & Slow COP_MASK when displaying still images, i.e. slides
  385.  * (FFM VCD bug #5).
  386.  * When performing fast backwards on PROHIBIT_SCAN_ACROSS... from a CDDA
  387.  * track to a VCD track switching to Normal playback of the current track
  388.  * (FFM VCD bug #4).
  389.  * Disabling trigger bit notification when PBC is set to off (worked fine
  390.  * inspite FFM bug #18 was reported).
  391.  * 
  392.  * 49    4/16/02 1:15p Dingming
  393.  * If current track is the last track(PBC off mode),disable next
  394.  * operation
  395.  * 
  396.  * 48    14/04/02 18:31 Ettim
  397.  * Avoid updating the time when during STOP state.
  398.  * 
  399.  * 47    4/11/02 1:08p Dingming
  400.  * fix bookmark can not use item 3.
  401.  * remove Sequence header check for non-vcd
  402.  * 
  403.  * 46    11/04/02 9:46 Ettim
  404.  * Getting the parameters for the digest (digest mode & intro frames
  405.  * count) from the UI.
  406.  * 
  407.  * 45    10/04/02 12:25 Ettim
  408.  * Moved here the structure Digest_Unit_TAG from digest 
  409.  * 
  410.  * 44    3/31/02 14:43 Ettim
  411.  * Performing resume play when getting play command while in digest mode.
  412.  * Removing the digest prev/next handling from the navigator.
  413.  * 
  414.  * 43    25/03/02 21:00 Nirm
  415.  * Added #include.
  416.  * 
  417.  * 42    20/03/02 1:32 Nirm
  418.  * - Fixed a bug in _getPSDRecord(): When the PSD file size is reported to
  419.  * be  less than SVCD_PSD_CACHE_SIZE, the cache-hit logic malfunctions for
  420.  * data-requests that exceed the expected range (i.e. authoring-error).
  421.  * 
  422.  * 41    3/11/02 17:42 Ettim
  423.  * Initializing the rand seed
  424.  * 
  425.  * 40    3/10/02 17:30 Ettim
  426.  * Added Motion Digest support. 
  427.  * 
  428.  * 39    4/03/02 20:49 Nirm
  429.  * Integrated support for Full-Stop.
  430.  * 
  431.  * 38    4/03/02 16:18 Nirm
  432.  * - Fixed wrong time-search in case of SVCD: Time need not be multiplied
  433.  * by two.
  434.  * 
  435.  * 37    2/28/02 14:55 Ettim
  436.  * + Updating Next / Prev operation mask while on Digest mode
  437.  * + Performing stop/resume only on track-digest and not disc-digest
  438.  * 
  439.  * 36    2/27/02 17:31 Ettim
  440.  * Added Digest support.
  441.  * 
  442.  * 35    19/02/02 19:26 Nirm
  443.  * Cancelled Trigger-Bit notification request on transition PBC-On -> PBC
  444.  * Off.
  445.  * 
  446.  * 34    2/18/02 17:57 Ettim
  447.  * Implementing the audio sid selection both in the ui and in the
  448.  * navigator.
  449.  * 
  450.  * 33    18/02/02 11:26 Nirm
  451.  * Fixed typo in uCurrAudioSID.
  452.  * 
  453.  * 32    2/18/02 11:23 Ettim
  454.  * Updated Audio SID setting for the channels C0 & C1
  455.  * 
  456.  * 31    2/18/02 11:10 Ettim
  457.  * Updated Audio SID setting for the channels C0 & C1
  458.  * 
  459.  * 30    2/18/02 11:01 Ettim
  460.  * Updated Audio SID setting for the channels C0 & C1
  461.  * 
  462.  * 29    2/17/02 16:40 Ettim
  463.  * Clearing and setting trigger bit notification on scanning and stop
  464.  * scanning.
  465.  * 
  466.  * 28    2/14/02 13:08 Ettim
  467.  * Fixed some warning messages.
  468.  * 
  469.  * 27    2/13/02 19:36 Ettim
  470.  * Disabling SLOW & STEP while playing a CDDA track.
  471.  * Implementing AB-Repeat inside a CDDA track.
  472.  * Setting prev on the first play item to jump to the beginning of that
  473.  * item.
  474.  * 
  475.  * 26    2/11/02 17:30 Ettim
  476.  * Updating the TimeOffset after scan stopped. (Fixed the FB->Item
  477.  * boundary reached->Play->Absolute time error problem)
  478.  * 
  479.  * 25    2/10/02 15:04 Ettim
  480.  * Using the Array for SDRAM allocations.
  481.  * Enabling play, next and prev on Auto Pause.
  482.  * 
  483.  * 24    2/06/02 17:17 Ettim
  484.  * Enabling play after slow mode.
  485.  * Fixing the problem of Fast reverse & play - retrying before abandoning
  486.  * the PTS-based measurement
  487.  * Canceling scanning when moving to the previous or the next item.
  488.  * 
  489.  * 23    31/01/02 13:49 Nirm
  490.  * Changed CVD support implementation.
  491.  * 
  492.  * 22    30/01/02 20:48 Nirm
  493.  * Compilation-Warnings removal.
  494.  * 
  495.  * 21    30/01/02 19:34 Nirm
  496.  * Removed unneeded debugging-messages.
  497.  * 
  498.  * 20    27/01/02 20:05 Nirm
  499.  * Corrected renewal of Pause across Track boundaries.
  500.  * 
  501.  * 16    1/21/02 17:45 Ettim
  502.  * Fixing the feature SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES - while
  503.  * perfoming Pause->Next waiting for the first frame of the next track to
  504.  * be displayed.
  505.  * Handling the sequence FF->Pause->Play so that the play continues from
  506.  * the point of the pause.
  507.  * 
  508.  * 15    19/01/02 13:05 Atai
  509.  * Change error debug printing
  510.  * 
  511.  * 14    1/17/02 19:14 Ettim
  512.  * Handling the CVD encryption
  513.  * 
  514.  * 13    16/01/02 18:24 Nirm
  515.  * Replaced dbprintf's with dbg_printf.
  516.  * 
  517.  * 12    1/16/02 16:18 Ettim
  518.  * Updating the latest changes performed in the I54 svcd navigator (VBR &
  519.  * Tracks.svd file parsing).
  520.  * Setting the operation mask to enable play while scanning.
  521.  * Updating the macro PE_CD_SetDiscType to get only 1 argument.
  522.  * 
  523.  * 9     1/14/02 18:53 Ettim
  524.  * Implementing the AB Repeat option for SVCD_USE_ABSOLUTE_TIME feature.
  525.  * 
  526.  * 8     1/13/02 18:18 Ettim
  527.  * 
  528.  * 7     1/10/02 18:01 Ettim
  529.  * Implementing the feature SVCD_USE_ABSOLUTE_TIME
  530.  * Fixing the scan - corrected playback resumption from scanning
  531.  * 
  532.  * 6     1/07/02 12:04 Ettim
  533.  * 
  534.  * 5     1/02/02 14:49 Ettim
  535.  * 
  536.  * 4     1/01/02 15:32 Ettim
  537.  * 
  538.  * 3     1/01/02 14:03 Atai
  539.  * Code cleaning
  540.  * 
  541.  * 
  542.  **************************************************************************************** */
  543. #include "Config.h" // Global Configuration - do not remove!
  544. #ifdef _DEBUG
  545. #define IFTRACE if (gTraceNavigator)
  546. #include "DebugDbgMain.h"
  547. #endif
  548. #include "includesysdefs.h"
  549. #include "includestring_ex.h"
  550. #include "Kernelker_api.h"
  551. #include "Kerneleventdef.h"
  552. #include "playcorecoremaincoregdef.h"
  553. #include "Drivedrv_api.h"
  554. #include "PlaycoreAuxCacheAuxCache.h"
  555. #include "playcoreFileSysFileSystem.h"
  556. #include "Decoderdecoder.h"
  557. #include "Decoderdec_io.h"
  558. #include "playcorePlayModeplaymode.h"
  559. #include "playcorenav_cddape_cd.h"
  560. #include "playcorenav_svcdnav_svcd.h"
  561. #include "playcoreScpadscmgr.h" //SDRAM operations
  562. #include "playcoreDataStructuresArray.h"
  563. #include "PlaycoreTimingTiming.h"
  564. #include "Playcorenav_cddaCdnav_err.h"
  565. #include "Customerdevicedacaudio_dac.h"
  566. #include "stringsstrings.h"
  567. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  568. #ifdef HW_POWER_ON_RESUME
  569. #include "PlaycoreCoremainnvm_bmk.h"
  570. #endif
  571. #endif //EXINO2
  572. #ifdef WATCHDOG_TRIGGERED_BY_FE
  573. #include "Playcorenav_svcdsvcd_error_jmp_tbl.c"
  574. #endif
  575. #if defined(SVCD_DIGEST_SUPPORT) 
  576. #include "PlaycoreDigestdigest.h"
  577. #ifndef SVCD_DIGEST_INTRO_FRAMES_CNT
  578. #define SVCD_DIGEST_INTRO_FRAMES_CNT 5
  579. #endif
  580. #endif
  581. /////////////////////////////////////////////////////////////////////////////////////////////////
  582. // Globals & Singletons
  583. extern BOOL g_in_full_stop;
  584. static WORD g_uNextStaticAllocationOffset = SC_SVCD_NAV_ADDR;
  585. BYTE g_DigestReadDiscError = 0;
  586. #if defined(ENHANCED_SEQ_HDR_READING) || defined(EXINO2)
  587. BOOL g_ucReadSeqHdr = FALSE;
  588. #endif 
  589. //////////////////////////////////////////////////////////////////////////////////////////////////
  590. //Function prototypes
  591. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  592. #ifdef HW_POWER_ON_RESUME
  593. BOOL SVCDNAV_NvmBmk_Match(NVM_GENERIC_BMK* pGenric_bmk);
  594. void SVCDNAV_NvmBmk_Set( WORD sc_handle);
  595. void SVCDNAV_NvmBmk_Play(NVM_GENERIC_BMK *pGenric_bmk);
  596. #endif
  597. #endif //EXINO2
  598. /////////////////////////////////////////////////////////////////////////////
  599. // Constants and Enumerations
  600. #define SVCD_ENTRY_SIZE 4 //size in bytes of each entry in the VCD
  601. #define SCR_RATE 90000L
  602. #define SVCD_TRACKS_TABLE_ENTRY_SIZE sizeof(SVCD_TracksInfo)
  603. #define TIME_TILL_VIDEO_ACTIVE 100000L
  604. #define SVCD_PTS_MONOTONITY_GRACE_RETRIES 10
  605. #define SLOW_SCAN_SPEED (SHARED_INFO.m_iSlowSpeed)//-1
  606. #define MAX_WATCHDOG_RETRY_TIMES 50//LX051302: Maximum retry times for error recovery, otherwise, skip to next play item
  607. #define NUM_OF_SECTORS_PER_SECOND ( ( DEC_DISC_TYPE_VCD == g_pSVCDNav->m_uDiscStandard ) ? 75L : 150L )//LX051302
  608. /////////////////////////////////////////////////////////////////////////////
  609. // Macros
  610. #define SHARED_INFO     (gns.svcd)
  611. #define SVCDMessageGap     SHARED_INFO.SVCDMessageGap
  612. #define g_hEntriesTable     SHARED_INFO.g_hEntriesTable
  613. #define g_hSegmentsContentTable SHARED_INFO.g_hSegmentsContentTable
  614. #define g_hTracksTable          SHARED_INFO.g_hTracksTable
  615. #define g_pSVCDNav SHARED_INFO.g_pSVCDNav
  616. #define SCAN_FINISH_GAP 30
  617. //Macros for working seamlessly with "Big Endian" and "Little Endian" platforms
  618. #ifdef MOTOROLA
  619. #define BE_DWORD(a) a
  620. #define BE_WORD(a) a
  621. #else
  622. #define BE_DWORD(a) (DWORD)((a << 24) | ((a & 0xFF00) << 8) | ((a & 0xFF0000L) >> 8) | ((a & 0xFF000000L) >> 24))
  623. #define BE_WORD(a) (WORD)((a << 8) | (a >> 8))
  624. #endif //MOTOROLA
  625. /////////////////////////////////////////////////////////////////////////////
  626. // Common Data-Structures
  627. typedef struct SVCD_Tracks_Info_TAG 
  628. {
  629. UINT16 uTrackTime; //Track's time
  630. BYTE uAudioInfo; //Track's audio info
  631. } SVCD_TracksInfo;
  632. typedef struct Digest_Unit_TAG
  633. {
  634. DWORD dwAddress;
  635. UINT16 uSize;
  636. } Digest_Unit;
  637. #ifdef D_USE_VARIABLE_FOR_LIB
  638. extern WORD svcd_skip_back_threshold;
  639. #endif
  640. /////////////////////////////////////////////////////////////////////////////////////////////////
  641. // Private Services - Prototype declaration
  642. // Internal Services
  643. static void Constructor(void);
  644. static void Destructor(void);
  645. static BOOL _getPSDRecord(DWORD i_dwPSD_Offset, WORD i_uBytesCnt, BYTE *o_pBuffer);
  646. static ULONG _getBlocksPerSecond(UINT uTrackNumber, ULONG ulTrackSize);
  647. #ifdef SVCD_DIGEST_SUPPORT
  648. static void _terminateDigestMode(void);
  649. #endif
  650. static void UpdateAudioInfo(UINT uTrackNumber);
  651. static void SetMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber);
  652. static void ClearMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber);
  653. static WORD FindDefaultSelectionOffset(DWORD dwCurrentLocation);
  654. static BOOL PlayItem(WORD uPlayItemNumber, DWORD dwStartPosition);
  655. static BOOL InvokePlayback(void);
  656. static DWORD CalculateRecoveryAddress(DWORD dwErrorAddress);
  657. static void PerformErrorRecovery(void);
  658. static void CancelRepeatModes(BYTE uModesMask);
  659. // Internal Events Handlers
  660. static void OnTimeout(void);
  661. static void OnWaitTimeExpired(void);
  662. static void OnPausePeriodExpired(void);
  663. // Event Handlers
  664. static void OnTick(void);
  665. #ifdef D_ENABLE_ELAPSEDTIME_FOR_SLIDESHOW
  666. static void OnTickOneSec(void);
  667. #endif
  668. static void OnPlay(void);
  669. static void OnRendezvousPoint(enSVCD_RendezvousType eType);
  670. static void OnPlaybackFinished(void);
  671. static void OnAutoPauseEngaged(void);
  672. static void OnStop(enSVCD_StopType eStopType);
  673. static void OnStep(void);
  674. static void OnModeChange(void);
  675. static void OnSetMarkerA(void);
  676. static void OnSetMarkerB(void);
  677. static void OnCancelABRepeat(void);
  678. static void OnGoToBookmark(WORD uBookmarkNumber);
  679. #ifdef D_ENABLE_DISC_TIMESEARCH
  680. static void OnGotoDiscTime(ULONG ulTime);
  681. #endif
  682. static void OnGotoTime(ULONG ulTime);
  683. #ifdef SVCD_DIGEST_SUPPORT
  684. static void OnDigest(UINT16 Param);
  685. #endif 
  686. static void OnScan(int iSpeed);
  687. static void OnSlow(int Speed);
  688. static void OnIFrameDisplayed(void);
  689. static void OnNextItem(void);
  690. static void OnPreviousItem(void);
  691. static void OnNumericSelection(WORD uSelection);
  692. static void OnGotoEntry(WORD uSelection);
  693. static void OnReturn(void);
  694. static void OnAudioSelection(WORD uSelection);
  695. static void OnStatusReport(void);
  696. static void OnIntro(void);
  697. #ifdef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  698. #ifdef HW_POWER_ON_RESUME
  699. static WORD GetResumeLeadOutInfo(void);
  700. static void GetCurretnLocationStructure(void);
  701. static void GetPSDAvaiableInfo(void);
  702. static void GetCurrentListInfo(void);
  703. static void GetVideoTypeInfo(void);
  704. static void SetResumeLeadOutInfo(void);
  705. static void SetCurretnLocationStructure(void);
  706. static void SetPSDAvaiableInfo(void);
  707. static void SetCurrentListInfo(void);
  708. static void SetVideoTypeInfo(void);
  709. static void ClearResumeLeadOutInfo(void);
  710. #endif 
  711. #endif //EXINO2
  712. /////////////////////////////////////////////////////////////////////////////////////////////////
  713. // Public Services
  714. /////////////////////////////////////////////////////////////////////////////////////////////////
  715. /////////////////////////////////////////////////////////////////////////////////////////////////
  716. // int SVCD_Navigator(HDLR_OP Op, EVENT Event, void *Param) -
  717. // The main router for SVCD-Navigation Events.
  718. //
  719. // Input:
  720. // Op - The type of operation being invoked
  721. // Event - The event to route
  722. // Param - An optional parameter for the event being routed
  723. //
  724. // Output:
  725. // Zero if the routing is successful.
  726. int SVCD_Navigator(HDLR_OP Op, EVENT Event, void *Param)
  727. {
  728. UINT16 status2 = inport(I64_STATUS_2);
  729. switch (Op) 
  730. {
  731. case HDLR_ENTER: Constructor();
  732. break;
  733. case HDLR_EXIT: Destructor();
  734. break;
  735. case HDLR_EVENT:
  736. //In case the allocation failed there is no point in handling the event
  737. if (NULL == g_pSVCDNav)
  738. return -1;
  739. switch (Event) 
  740. {
  741. case IE_CORE_PAUSE:
  742. OnStop(ePause);
  743. break;
  744. case IE_CORE_STEP:
  745. OnStep();
  746. break;
  747. case IE_CORE_STOP:
  748. {
  749. enSVCD_StopType eStopType;
  750. if ((g_disc_type == DEC_DISC_TYPE_SVCD) && (status2 & DEC_LL_STATUS2_SVCD_MPEG1))
  751. g_disc_type = DEC_DISC_TYPE_VCD;
  752. #ifndef SVCD_ALLOW_NONPBC_RESUME
  753. eStopType= eFullStop;
  754. #else
  755. #ifdef SVCD_DIGEST_SUPPORT
  756. if (g_pSVCDNav->m_bDigestMode) 
  757. if (eTrackView == Digest_getDigestMode())
  758. eStopType= eStopResume;
  759. else
  760. eStopType= eFullStop;
  761. else
  762. eStopType= eStopResume;
  763. #else
  764. eStopType= eStopResume;
  765. #endif //SVCD_DIGEST_SUPPORT
  766. #endif  //SVCD_ALLOW_NONPBC_RESUME
  767. #ifndef SVCD_ALLOW_PBC_RESUME
  768. // Prohibit "Resume" for PBC on
  769. if (PM_IsPBC(PM_GetPlaybackMode()))
  770. eStopType= eFullStop;
  771. #endif //SVCD_ALLOW_PBC_RESUME
  772. if (TRUE == (BOOL)Param)
  773. eStopType= eFullStop;
  774. OnStop(eStopType);
  775. }
  776. break;
  777. case IE_CORE_RESTART:
  778. #ifdef EXINO2 //ZKR JK0331 : for power_on_resume in EEPORM
  779. #ifdef HW_POWER_ON_RESUME
  780. ClearMarker(eResumePlayback, 0);
  781.                      
  782. if ( GetResumeLeadOutInfo() == gns.svcd.wTotalPlaybackTime)
  783. {
  784. ClearResumeLeadOutInfo();
  785. GetCurretnLocationStructure();
  786. GetPSDAvaiableInfo();
  787. GetCurrentListInfo();
  788. GetVideoTypeInfo();
  789. if ( g_pSVCDNav->m_bIsUsingPSD )
  790. {
  791. PM_SetPBC(TRUE);
  792. g_pSVCDNav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  793. if ( ( g_pSVCDNav->m_iCurrVideoType == STILL_LOWRES ) || ( g_pSVCDNav->m_iCurrVideoType == STILL_HIRES ) )
  794. gns.svcd.m_CurrPosition.dwStartAddress = -1;
  795. // <<< SEC shKang122203 : takes too many times for resume playback when menu on status
  796. #ifdef DISABLE
  797. g_pSVCDNav->m_dwPSD_CacheBase= 0xFFFF;
  798. #endif // DISABLE
  799. // SEC shKang122203 >>>
  800. }
  801. else
  802. {
  803. PM_SetPBC(FALSE);
  804. PM_SetPlaybackMode((BYTE) PM_PLAYBACK_NORMAL);
  805. g_pSVCDNav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  806. }
  807. // <<< ZKR GL50104 : Eliminate unnecessary sequence header reads.
  808. #if defined(ENHANCED_SEQ_HDR_READING) || defined(EXINO2)
  809. g_ucReadSeqHdr = TRUE;
  810. #endif 
  811. // >>>
  812. }
  813. else
  814. #endif
  815. #else //EXINO2                
  816. #ifdef HW_POWER_ON_RESUME
  817. ClearMarker(eResumePlayback, 0);
  818. if ((TRUE == (BOOL)Param)&&(NVM_BMK_Play()))
  819. {
  820. dbg_printf(("nNVM Bookmark restart. "));
  821. }
  822. else
  823. #endif//HW_POWER_ON_RESUME                  
  824. #endif //EXINO2               
  825.            
  826. {
  827. #ifdef K1_WL
  828. if (resume_play_request)
  829.                            {
  830. memcpy(&(gns.svcd.m_CurrPosition), &(g_pSVCDNav->m_ResumePlayback), sizeof(SVCD_Marker));
  831.                               resume_play_request = 0;
  832.                            }
  833. else
  834. #endif
  835. {
  836. #ifdef K1_WL
  837. ClearMarker(eResumePlayback,0);
  838. #endif
  839. (gns.svcd.m_CurrPosition).ListType= Undetermined;
  840. (gns.svcd.m_CurrPosition).dwPSD_Offset= 0;
  841. (gns.svcd.m_CurrPosition).uListItem= 1; // Start playback from the first Item
  842. }
  843. }
  844. // Fall-Through!
  845. case IE_CORE_PLAY:
  846. OnPlay();
  847. // <<< ZKR GL050104 : Eliminate unnecessary sequence header reads.
  848. #if defined(ENHANCED_SEQ_HDR_READING) || defined(EXINO2)
  849. g_ucReadSeqHdr = FALSE;
  850. #endif 
  851. // >>>
  852. break;
  853. case IE_CORE_TITLE_MENU:
  854. case IE_CORE_DIGEST:
  855. #ifdef SVCD_DIGEST_SUPPORT
  856. OnCancelABRepeat();
  857. usleep(400000L); //mikex_0821_2003_a: add a delay after canceling the AB repeat
  858. OnDigest((UINT16)Param & 0xFFFF);
  859. #endif //SVCD_DIGEST_SUPPORT
  860. break;
  861. case IE_CORE_NEXT_CHAPTER:
  862. OnNextItem();
  863. break;
  864. case IE_CORE_PREVIOUS_CHAPTER:
  865. OnPreviousItem();
  866. break;
  867. case IE_CORE_GOTO_ENTRY:
  868. OnGotoEntry((UINT16)Param);
  869. break;
  870. case IE_CORE_MENU_NUMERICAL_SELECTION:
  871. case IE_CORE_NUM_SELECTION:
  872. OnNumericSelection((UINT16)Param);
  873. break;
  874. case IE_CORE_RETURN:
  875. OnReturn();
  876. break;
  877. case IE_CORE_CDNAV_RENDEZVOUS:
  878. OnRendezvousPoint((enSVCD_RendezvousType)Param);
  879. break;
  880. case IE_CORE_CDNAV_FINISHED:
  881. OnPlaybackFinished();
  882. break;
  883. case IE_CORE_CDNAV_TRIGGER:
  884. OnAutoPauseEngaged();
  885. break;
  886. case IE_CORE_AB_REPEAT:
  887. if (FALSE == (BOOL)Param) {
  888. OnCancelABRepeat();
  889. break;
  890. }
  891. if (PM_GetRepeatAB() & PM_REPEAT_AB_B)
  892. OnCancelABRepeat();
  893. else { //after set A or A-B, set repeat single, then A will never be setted for the dwStartAddress is still there. 
  894. if ((0 == PM_GetRepeatAB())) //&& (-1 == (g_pSVCDNav->m_PositionA).dwStartAddress))      // so I remove this condition, if this is necessary, let me know please, tonnyg
  895. OnSetMarkerA();
  896. else if (PM_REPEAT_AB_A == PM_GetRepeatAB())
  897. OnSetMarkerB();
  898. }
  899. break;
  900. case IE_CORE_SET_BOOKMARK:
  901. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  902. #ifdef HW_POWER_ON_RESUME
  903. NVM_BMK_SET((int)Param);
  904. #endif
  905. #endif
  906. SetMarker(eBookmark, (UINT16)Param -1);
  907. break;
  908. case IE_CORE_GOTO_BOOKMARK:
  909. OnGoToBookmark((UINT16)Param - 1);
  910. break;
  911. case IE_CORE_SLOW:
  912. OnSlow((int)Param);
  913. break;
  914. case IE_CORE_SCAN:
  915. OnScan((int)Param);
  916. break;
  917. case IE_CORE_TICK_200:
  918. OnTick();
  919. break;
  920. case IE_CORE_TICK_ONE_SEC:
  921. #ifdef D_ENABLE_ELAPSEDTIME_FOR_SLIDESHOW
  922. OnTickOneSec();
  923. #endif
  924. break;
  925. case IE_CORE_I_FRAME:
  926. OnIFrameDisplayed();
  927. break;
  928. case IE_CORE_SEAMLESS_MODE_CHANGE:
  929. OnModeChange();
  930. break;
  931. case IE_CORE_AUDIO_STREAM_SELECTION:
  932. OnAudioSelection((UINT16)Param);
  933. break;
  934. case IE_CORE_PM_RESET:
  935. // Reset the PM mode : program,repeat, random , reset play -A-B
  936. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  937. PM_ClearRepeat();
  938. break;
  939. //<<<Leslie_0828_2003_B: Comment out
  940. #if 0
  941. case IE_CORE_PAUSE_DRIVE: // Fall-Through!
  942. case IE_CORE_RESUME_DRIVE:
  943. break;
  944. #endif
  945. //Leslie_0828_2003_B>>>
  946. case IE_CORE_GOTO_TIME:
  947. OnGotoTime((ULONG)Param);
  948. // <<< SEC BK.LIM092203 // ZKR GLV778
  949. #ifdef EXINO2
  950. ie_send(IE_UI_REFRESH_TIME);
  951. #endif
  952. //SEC BK.LIM092203>>>
  953. break;
  954. case IE_CORE_GOTO_DISC_TIME:
  955. #ifdef D_ENABLE_DISC_TIMESEARCH
  956. OnGotoDiscTime((ULONG)Param);
  957. #endif
  958. break;
  959. #ifdef WATCHDOG_TRIGGERED_BY_FE
  960. case IE_CORE_DRIVE_READ_FAIL:
  961. if ( DRV_READ_ERROR_ECC == (DRV_READ_ERROR_TYPE)Param){
  962. (g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter = 0;
  963. break;
  964. }
  965. dbg_printf(("SVCD_Nav: DriveDriver_ReadFail encountered.n"));
  966. // Force Error-Recovery
  967. (g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout= 1;
  968. (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam = PE_CD_GetCurrentLocation();
  969. tr_printf(("Current location is %lxn", (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam));
  970. PerformErrorRecovery();
  971. break;
  972. case IE_CORE_PICTURE_DECODING_STUCK:
  973. tr_printf((" Picture Decoding Stuckingn"));
  974. ie_send_ex(IE_CORE_DRIVE_READ_FAIL, (void *)DRV_READ_ERROR_FROM_BE );
  975. break;
  976. #endif //WATCHDOG_TRIGGERED_BY_FE
  977. case EVENT_CLASS_CORE:
  978. #ifdef _DEBUG
  979. OnStatusReport();
  980. #endif //_DEBUG
  981. break;
  982. case IE_CORE_CDNAV_INTRO:
  983. OnIntro();
  984. break;
  985. default:
  986. dbg_printf(("SVCD_Nav: Unexpected Event (%04x)n", (Event & 0xFFFF)));
  987. break;
  988. }
  989. break;
  990. default:
  991. dbg_printf(("SVCD_Nav: Unknown Operation requested (%d)n", Op));
  992. break;
  993. }
  994. return 0;
  995. }
  996. /////////////////////////////////////////////////////////////////////////////////////////////////
  997. // Private Services
  998. /////////////////////////////////////////////////////////////////////////////////////////////////
  999. /////////////////////////////////////////////////////////////////////////////////////////////////
  1000. // Internal Services
  1001. /////////////////////////////////////////////////////////////////////////////////////////////////
  1002. // void Constructor() -
  1003. // A Constructor for a SVCD-Navigator instance.
  1004. //
  1005. // Input:
  1006. // None
  1007. //
  1008. // Output:
  1009. // None. The Navigator is constructed.
  1010. //
  1011. // Remarks:
  1012. // This method constructs a new SVCD-Navigator, whose internal data and status
  1013. // are kept in the global SVCD_Nav structure.
  1014. static void Constructor(void)
  1015. {
  1016. WORD uEntriesUsedCnt;
  1017. WORD uCurrTrack= 0;
  1018. ULONG ulTemp;
  1019. BYTE aBuffer[SVCD_INFO_HDR_SIZE+1];
  1020. //WORD uSegmentTableEntryOffset;
  1021. //WORD uCurrEntryOffset;
  1022. DWORD dwDiscOffset;
  1023. DWORD dwEncryptionInfoAddr;
  1024. DWORD dwEncryptionInfoSize;
  1025. TrackInfo TrackTwo, LastTrack;
  1026. DWORD dwTemp;
  1027. WORD  wTemp;
  1028. dbg_printf(("SVCD_Constructor()n"));
  1029. dbg_printf(("--> SVCD-Navigator size is: %d Bytes.n", sizeof(SVCD_Nav_Info)));
  1030. #ifndef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  1031. #ifdef HW_POWER_ON_RESUME
  1032. NVM_BMK_Hook(BMK_SVCD, SVCDNAV_NvmBmk_Match, SVCDNAV_NvmBmk_Set, SVCDNAV_NvmBmk_Play);
  1033. NVM_BMK_Verify();
  1034. #endif
  1035. #endif
  1036. // Initialize the Default Program-List (in case of a VCD1.1 disc, or
  1037. // when PSD-Usage is explicitly disabled).
  1038. SVCDMessageGap.ScanFinishGap = 0;
  1039. PM_InitializeProgramList();
  1040. for (ulTemp=1; ulTemp < (((ULONG)PE_CD_GetTracksCnt()==1)?2:(ULONG)PE_CD_GetTracksCnt()); ulTemp++)
  1041. PM_SetProgramListEntry((WORD)ulTemp, (WORD)(ulTemp+1));
  1042. //Allocating the SVCD Navigator struct
  1043. g_pSVCDNav = (SVCD_Nav_Info *)malloc(sizeof(SVCD_Nav_Info));
  1044. if (NULL == g_pSVCDNav) {
  1045. dbg_printf(("Failed to allocate resources for the SVCD Navigator struct.n"));
  1046. return;
  1047. }
  1048. //initializing the rand seed
  1049. srand((UINT16)timing_get_clock());
  1050. // Assume playback NOT using the Playback-Sequence-Descriptor (PSD)
  1051. g_pSVCDNav->m_bIsUsingPSD= FALSE;
  1052. // General initializations
  1053. memset(&(g_pSVCDNav->m_NavigationInfo), 0, sizeof(g_pSVCDNav->m_NavigationInfo));
  1054. #ifdef SVCD_DIGEST_SUPPORT
  1055. g_pSVCDNav->m_bDigestMode = FALSE;
  1056. g_pSVCDNav->m_uiDigestUnits = NULL;
  1057. #endif //SVCD_DIGEST_SUPPORT
  1058. g_pSVCDNav->m_bPendingEvent= FALSE;
  1059. g_pSVCDNav->m_dwWaitTime= SVCD_INFINITE;
  1060. g_pSVCDNav->m_dwTimeout= SVCD_INFINITE;
  1061. g_pSVCDNav->m_dwPausePeriod= SVCD_INFINITE;
  1062. g_pSVCDNav->m_uFirstCDDA_Track= 100;
  1063. SHARED_INFO.m_iScanSpeed= 0;
  1064. SHARED_INFO.bIsIntroPlayMode = FALSE;
  1065. // Clear all Markers and Bookmarks
  1066. ClearMarker(eResumePlayback, 0);
  1067. ClearMarker(eMarkerA, 0);
  1068. ClearMarker(eMarkerB, 0);
  1069. for (ulTemp=0; ulTemp < SVCD_MAX_BOOKMARKS; ulTemp++)
  1070. ClearMarker(eBookmark, (WORD)ulTemp);
  1071. // Initialize the Playback-Mode to "Normal"
  1072. PM_SetPlaybackMode(PM_PLAYBACK_NORMAL);
  1073. g_pSVCDNav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  1074. // Reset Time-Measurement Info
  1075. #ifdef USE_PTS_TO_MEASURE_TIME
  1076. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= TRUE; // By default, measuer using PTS's
  1077. #else
  1078. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= FALSE; // Measuer not using PTS's
  1079. #endif
  1080. (g_pSVCDNav->m_TimeMeasurementInfo).bAcquireStartPTS= TRUE;
  1081. (g_pSVCDNav->m_TimeMeasurementInfo).dwStartPTS= 0;
  1082. // Set the deafult values for the Current-Position marker
  1083. (SHARED_INFO.m_CurrPosition).ListType= Undetermined; // The type of the first List is yet undetermined
  1084. (SHARED_INFO.m_CurrPosition).dwPSD_Offset= 0; // The first List is at the beginning of the PSD
  1085. (SHARED_INFO.m_CurrPosition).uListItem= 1; // By default, begin with the first item in the List
  1086. (SHARED_INFO.m_CurrPosition).dwStartAddress= -1; // The address is yet undefined
  1087. // Reset the Current-Location Change indicator
  1088. g_pSVCDNav->m_bLocationChanging= FALSE;
  1089. g_pSVCDNav->m_dwTargetLocation= 0;
  1090. // Initialize the settings of the Global variables
  1091. SHARED_INFO.iCurrentTime= 0;
  1092. SHARED_INFO.uCurrentTrackNumber= 2;
  1093. gns.svcd.bEntryInfoAvaiable = FALSE;
  1094. gns.svcd.wCurrentEntryNumber = 0xFFFF;
  1095. //configure the disc type to VCD by default
  1096. // PE_CD_SetDiscType(DEC_DISC_TYPE_VCD);//LX0713: Comment out, in case teh Dec Cache is flushed
  1097. if (! PE_CD_GetTrackInfo( (PE_CD_GetTracksCnt()==1)?1:2, &TrackTwo) || 
  1098. ! PE_CD_GetTrackInfo(PE_CD_GetTracksCnt(), &LastTrack)) 
  1099. {
  1100. SHARED_INFO.wTotalPlaybackTime= 0;
  1101. SHARED_INFO.wRemainingPlaybackTime = 0;
  1102. }
  1103. else 
  1104. {
  1105. if(PE_CD_GetTracksCnt()==1)
  1106. {
  1107. BYTE aBuffer[SVCD_INFO_HDR_SIZE];
  1108. if (AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, 0, SVCD_ENTRIES_HDR_SIZE, aBuffer)) 
  1109. {
  1110. if ((0 == strncmp((LPSTR)aBuffer, "ENTRYVCD", 8)) ||
  1111. (0 == strncmp((LPSTR)aBuffer, "ENTRYSVD", 8)))
  1112. if ( AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, 12, 4, aBuffer)) 
  1113. {
  1114. TrackTwo.dwStartAddress = drv_msf2lbn(drv_bcd2bin(aBuffer[1]), drv_bcd2bin(aBuffer[2]), drv_bcd2bin(aBuffer[3]));
  1115. }
  1116. }
  1117. }
  1118. SHARED_INFO.wTotalPlaybackTime= 
  1119. (WORD)(((LastTrack.dwStartAddress + LastTrack.ulBlocksCnt) - 
  1120.  TrackTwo.dwStartAddress) / SVCD_BLOCKS_PER_SECOND);
  1121. SHARED_INFO.wRemainingPlaybackTime = SHARED_INFO.wTotalPlaybackTime;
  1122. }
  1123. gcs.pstate= PST_STOP;
  1124. //setting the operation mask
  1125. SET_COP_MASK(0xFFFFFFFFL);
  1126. #ifdef SVCD_DIGEST_SUPPORT
  1127. CLEAR_COP_MASK(COP_ROOT_MENU | COP_ANGLE_CHANGE | COP_SUBPIC_CHANGE);
  1128. SET_COP_MASK(COP_TITLE_MENU);
  1129. #else
  1130. CLEAR_COP_MASK(COP_TITLE_MENU | COP_ROOT_MENU | COP_ANGLE_CHANGE | COP_SUBPIC_CHANGE);
  1131. #endif //SVCD_DIGEST_SUPPORT
  1132. //Set default value 
  1133. {
  1134. SHARED_INFO.uCurrentAudioSIDChannel = 1;
  1135. SHARED_INFO.bPBC_Available = FALSE;
  1136. SHARED_INFO.bIsVCD20 = FALSE;
  1137. }
  1138. // Parse the "INFO.VCD" file, and extract the necessary information:
  1139. // First of all, get the System-Identification information
  1140. //if( PE_CD_GetTracksCnt() ==1 )
  1141. // return;
  1142. //ML0618 remove for not being used
  1143. if (! AuxCache_GetBytes(SVCD_INFO_FILE_ADDRESS, 0, SVCD_INFO_HDR_SIZE, aBuffer)) {
  1144. dbg_printf(("Failed to parse INFO.VCD!n"));
  1145. return;
  1146. }
  1147. aBuffer[SVCD_INFO_HDR_SIZE]= 0;
  1148. //Setting the default value to a non encrypted disk
  1149. g_pSVCDNav->m_bIsEncrypted= FALSE;
  1150. // Find-out the type of Standard used in this disc (VCD or SVCD)
  1151. // if (_isSimilarStrings((LPCSTR)aBuffer, "VIDEO_CD")) {
  1152. if ( DEC_DISC_TYPE_VCD == g_disc_type ){//LX0713: Direct check disc type
  1153. dbg_printf(("<<< VCD Disc Detected >>>n"));
  1154. g_pSVCDNav->m_uDiscStandard= DEC_DISC_TYPE_VCD;
  1155. CLEAR_COP_MASK(COP_AUDIO_CHANGE);
  1156. }
  1157. // else if (_isSimilarStrings((LPCSTR)aBuffer, "SUPERVCD") ||
  1158. //  _isSimilarStrings((LPCSTR)aBuffer, "HQ-VCD  "))
  1159. else if ( DEC_DISC_TYPE_SVCD == g_disc_type ){//LX0713: Direct check disc type
  1160. dbg_printf(("<<< SVCD Disc Detected >>>n"));
  1161. g_pSVCDNav->m_uDiscStandard= DEC_DISC_TYPE_SVCD;
  1162. // Check whether or not the streams are encrypted (CVD)
  1163. if ((eISO9660 == FileSys_determineType()) && FileSys_selectType(eISO9660) &&
  1164. FileSys_initialize(FALSE)) 
  1165. {
  1166. if (FileSys_changeDir(L"EXT") && FileSys_fileExists(L"DISK.ID")) {
  1167. FindData fdInfo;
  1168. UINT16 hFileFind= FileSys_findFirstFile(L"DISK.ID", &fdInfo);
  1169. if (NULL != hFileFind) {
  1170. g_pSVCDNav->m_bIsEncrypted= TRUE;
  1171. dwEncryptionInfoAddr= fdInfo.dwStartAddr;
  1172. dwEncryptionInfoSize= (DWORD)fdInfo.cbFileSizeLow;
  1173. dbg_printf(("<<< CVD (Encrypted SVCD) Detected >>>n"));
  1174. FileSys_findClose(hFileFind);
  1175. }
  1176. }
  1177. } // endof ISO-9660
  1178. }
  1179. //<<<LX071703: Comment out, meaningless to do this here, alreay know either it is VCD or SVCD
  1180. #if 0
  1181. else {
  1182. BOOL bSuccess;
  1183. g_pSVCDNav->m_dwSecondTrackAddress = TrackTwo.dwStartAddress; // update m_dwSecondTrackAddress
  1184. bSuccess = AuxCache_GetBytes(SVCD_KARINFO_FILE_ADDRESS, 0, 11, aBuffer);
  1185. if (!bSuccess) {
  1186. dbg_printf(("Failed to read the KARINFO.BIH file!n"));
  1187. return;
  1188. }
  1189. if (_isSimilarStrings((LPCSTR)aBuffer, "KARINFO.BIH")) {
  1190. dbg_printf(("<<< VCD 1.1 Disc Detected >>>n"));
  1191. }
  1192. else {
  1193. dbg_printf(("ERROR! The file INFO.VCD is corrupted. Assuming VCD 1.1.n"));
  1194. }
  1195. return;
  1196. }
  1197. #endif
  1198. //LX071703>>>
  1199. dbg_printf(("Version number: %02x.%02xn", aBuffer[8], aBuffer[9]));
  1200. dbg_printf(("Album-ID: %sn", (LPSTR)&aBuffer[10]));
  1201. //check if it is version 2.0 for VCD discs
  1202. if( (aBuffer[8]==0x02)&&(aBuffer[9]==0x00))
  1203. SHARED_INFO.bIsVCD20 = TRUE;
  1204. // Now, get selected Navigation-Information
  1205. // We assume that the following information is already resident in the cache
  1206. // Therefore there is no need to encapsulate the calls with exception ingoring
  1207. if ( ! AuxCache_GetBytes( SVCD_INFO_FILE_ADDRESS, SVCD_INFO_HDR_SIZE + 18, 4, (BYTE *)(&(dwTemp)) ) ) {
  1208. dbg_printf((" Failed to parse PSD Size!n"));
  1209. g_pSVCDNav->m_NavigationInfo.ulPSD_Size= 0;
  1210. return;
  1211. }
  1212. else
  1213.   g_pSVCDNav->m_NavigationInfo.ulPSD_Size = BE_DWORD(dwTemp);
  1214. if (0 == g_pSVCDNav->m_NavigationInfo.ulPSD_Size)
  1215. SHARED_INFO.bPBC_Available = FALSE;
  1216. if ( ! AuxCache_GetBytes( SVCD_INFO_FILE_ADDRESS, SVCD_INFO_HDR_SIZE + 22, 3, (BYTE *)(g_pSVCDNav->m_NavigationInfo.aFirstSegmentAddress) ) ) {
  1217. dbg_printf((" Failed to parse First Segment Address!n"));
  1218. return;
  1219. }
  1220. //Leslie_1125_2003: Temporarily comment out, need to check why we need to do byte swap here
  1221. #if 0
  1222. else
  1223. {
  1224. BYTE bTemp = g_pSVCDNav->m_NavigationInfo.aFirstSegmentAddress[1];
  1225. g_pSVCDNav->m_NavigationInfo.aFirstSegmentAddress[1] = g_pSVCDNav->m_NavigationInfo.aFirstSegmentAddress[0];
  1226. g_pSVCDNav->m_NavigationInfo.aFirstSegmentAddress[0] = bTemp;
  1227. }
  1228. #endif
  1229. if ( ! AuxCache_GetBytes( SVCD_INFO_FILE_ADDRESS, SVCD_INFO_HDR_SIZE + 25, 1, (BYTE *)(&(g_pSVCDNav->m_NavigationInfo.uOffsetMultiplier)) ) ) {
  1230. dbg_printf((" Failed to parse Offset Multiplier!n"));
  1231. return;
  1232. }
  1233. if ( ! AuxCache_GetBytes( SVCD_INFO_FILE_ADDRESS, SVCD_INFO_HDR_SIZE + 28, 2, (BYTE *)(&wTemp) ) ) {
  1234. dbg_printf((" Failed to parse Maximum segment Number!n"));
  1235. return;
  1236. }
  1237. else
  1238. g_pSVCDNav->m_NavigationInfo.uMaxSegmentNumber = BE_WORD(wTemp);
  1239. // If a PSD exists, then parse the Segment Play-Item Contents Table, and convert it into 
  1240. // a collection of SVCD_SegmentPlayItem structures
  1241. if (0 != (g_pSVCDNav->m_NavigationInfo).ulPSD_Size) {
  1242. WORD uCurrSegmentNumber= 1, uSegmentIndex = 0;
  1243. BYTE uSegmentContents;
  1244. SVCD_SegmentPlayItem CurrPlayItem;
  1245. dwDiscOffset= SVCD_SEGMENT_OFFSET_IN_INFO;
  1246. // Get the first Segment's Contents
  1247. //EttiM 27/11/2001 - Nutralizing all calls for exception_xxx
  1248. if (! AuxCache_GetBytes(SVCD_INFO_FILE_ADDRESS, dwDiscOffset++, 1, &uSegmentContents)) {
  1249. dbg_printf(("Failed to parse the Segments Play-Items Table!n"));
  1250. return;
  1251. }
  1252. CurrPlayItem.uSegmentNumber= uCurrSegmentNumber;
  1253. CurrPlayItem.uContents= uSegmentContents;
  1254. CurrPlayItem.uSubSegmentCnt = 1;
  1255. // Make sure that the Maximal-Segment Number is valid. If not, assume the maximal possible
  1256. // number of Segments.
  1257. //EttiM TODO: needs to be reconsidered in the future
  1258. //if (0 == (g_pSVCDNav->m_NavigationInfo).uMaxSegmentNumber)
  1259. // (g_pSVCDNav->m_NavigationInfo).uMaxSegmentNumber= SVCD_SEGMENTS_TABLE_SIZE;
  1260. // Allocate enough memory for the Segments table
  1261. //g_uSegmentsContentTable= sc_Malloc(((g_pSVCDNav->m_NavigationInfo).uMaxSegmentNumber * sizeof(SVCD_SegmentPlayItem))/ BYTE_PER_CONTAINER);
  1262. g_hSegmentsContentTable = Array_construct((g_pSVCDNav->m_NavigationInfo).uMaxSegmentNumber, 
  1263. sizeof(SVCD_SegmentPlayItem), NULL);
  1264. if (NULL == g_hSegmentsContentTable) {
  1265. dbg_printf(("Failed to allocate resources for the Segments Table.n"));
  1266. return;
  1267. }
  1268. //uSegmentTableEntryOffset = g_uSegmentsContentTable;
  1269. while (uCurrSegmentNumber <= (g_pSVCDNav->m_NavigationInfo).uMaxSegmentNumber) {
  1270. if (! AuxCache_GetBytes(SVCD_INFO_FILE_ADDRESS, dwDiscOffset++, 1, &uSegmentContents)) {
  1271. dbg_printf(("Failed to parse the Segments Play-Items Table!n"));
  1272. return;
  1273. }
  1274. uCurrSegmentNumber++;
  1275. // Check if the current Contents byte starts a new Play-Item
  1276. if (0 == (uSegmentContents & 0x20)) {
  1277. // First, store the previous Play-Item in the Table
  1278. //sc_Write(uSegmentTableEntryOffset, (sizeof(SVCD_SegmentPlayItem) / BYTE_PER_CONTAINER), (Sc_cont*)&CurrPlayItem);
  1279. Array_setAt(g_hSegmentsContentTable, uSegmentIndex, (BYTE *)&CurrPlayItem);
  1280. uSegmentIndex++;
  1281. //uSegmentTableEntryOffset += (sizeof(SVCD_SegmentPlayItem) / BYTE_PER_CONTAINER);
  1282. // Now fill-in a new Play-Item
  1283. CurrPlayItem.uSegmentNumber= uCurrSegmentNumber;
  1284. CurrPlayItem.uContents= uSegmentContents;
  1285. //holding the number of sub segments per play item instead of the actual number of blocks
  1286. CurrPlayItem.uSubSegmentCnt = 1;
  1287. }
  1288. else 
  1289. CurrPlayItem.uSubSegmentCnt++;
  1290. } // endof while
  1291. // Request for notifications of Trigger-Bit occurrence
  1292. PE_CD_RequestNotification(TriggerBit);
  1293. // Engage PSD-usage
  1294. g_pSVCDNav->m_bIsUsingPSD= TRUE;
  1295. #ifdef STORE_PBC_VALUE_IN_PS
  1296.        if(PS_GetPBC())
  1297.     PM_SetPBC(TRUE);
  1298. else
  1299.       PM_SetPBC(FALSE);
  1300. #else
  1301. //mikel_0912_2003_b add compile switch for pbc default setting off
  1302. #ifdef CONFIG_4MB_FLASH
  1303. #ifndef D_DEFAULT_PBCOFF
  1304. // Update the final decision regarding PBC
  1305. PM_SetPBC(TRUE);
  1306. #endif
  1307. #else
  1308. #ifdef D_DEFAULT_PBCOFF//tecobest gxd 20051010
  1309. PM_SetPBC(FALSE);
  1310. #endif
  1311. //IFNDEF(CdMedia_Macro.bD_DEFAULT_PBCOFF)
  1312. // Update the final decision regarding PBC
  1313. // PM_SetPBC(TRUE);
  1314. //ENDIF
  1315. #endif
  1316. #endif //STORE_PBC_VALUE_IN_PS
  1317. }
  1318. else { // A PSD file doesn't exist
  1319. // Do nothing
  1320.       PM_SetPBC(FALSE);//LX0713: Set PBC Mode FALSE
  1321. }
  1322. // Now parse the ENTRIES file, which must exist
  1323. memset((void *)aBuffer, 0, SVCD_ENTRIES_HDR_SIZE+1);
  1324. //EttiM 27/11/2001 - Nutralizing all calls for exception_xxx
  1325. if (! AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, 0, SVCD_ENTRIES_HDR_SIZE, aBuffer)) {
  1326. dbg_printf(("Failed to parse ENTRIES.VCD!n"));
  1327. g_pSVCDNav->m_NavigationInfo.ulPSD_Size= 0;
  1328. g_pSVCDNav->m_bIsUsingPSD= FALSE;
  1329. return;
  1330. }
  1331. if (_isSimilarStrings((LPCSTR)aBuffer, "ENTRYVCD")) {
  1332. g_pSVCDNav->m_wEntriesUsedCnt = ((aBuffer[10] << 8) | aBuffer[11]);
  1333. dbg_printf(("Entries-File Version: %02x.%02xn", aBuffer[8], aBuffer[9]));
  1334. dbg_printf(("Number of used Entries: %un", g_pSVCDNav->m_wEntriesUsedCnt));
  1335. }
  1336. else {
  1337. // The Entries-File is possibly corrupted: don't use the PSD information
  1338. g_pSVCDNav->m_wEntriesUsedCnt = 0;
  1339. g_pSVCDNav->m_NavigationInfo.ulPSD_Size= 0;
  1340. g_pSVCDNav->m_bIsUsingPSD= FALSE;
  1341. dbg_printf(("Entries-File Header is currupted.n"));
  1342. }
  1343. // For each of the reported entries in the file do the following:
  1344. //  - If it is the first entry within a given Track, verify that the start-address is accurate,
  1345. //    by cross-checking against the TOC entry for that Track; in case of a mismatch, override
  1346. //    the Entries information with the TOC information.
  1347. //  - Copy the Entry information to the designated place in Entries-Table.
  1348. dwDiscOffset = SVCD_ENTRIES_HDR_SIZE;
  1349. uEntriesUsedCnt = g_pSVCDNav->m_wEntriesUsedCnt;
  1350. g_hEntriesTable = Array_construct((1 + g_pSVCDNav->m_wEntriesUsedCnt),
  1351.   SVCD_ENTRY_SIZE, 
  1352.   &g_uNextStaticAllocationOffset);
  1353. if ( ( g_pSVCDNav->m_wEntriesUsedCnt > 0 ) && ( NULL != g_hEntriesTable ) )
  1354. gns.svcd.bEntryInfoAvaiable = TRUE;
  1355. while (uEntriesUsedCnt > 0) 
  1356. {
  1357. if (! AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, dwDiscOffset, 4, aBuffer)) {
  1358. dbg_printf(("Failed to parse the Entries file!n"));
  1359. g_pSVCDNav->m_bIsUsingPSD = FALSE;
  1360. return;
  1361. }
  1362. dwDiscOffset += 4;
  1363. if (drv_bcd2bin(aBuffer[0]) != uCurrTrack) {
  1364. TrackInfo CurrTrack;
  1365. // This is the first occurrence of the Track - cross-check it against the TOC
  1366. uCurrTrack= (WORD)drv_bcd2bin(aBuffer[0]);
  1367. if (! PE_CD_GetTrackInfo(uCurrTrack, &CurrTrack)) {
  1368. dbg_printf(("Failed to access the TOC for Track %d.n", (int)uCurrTrack));
  1369. continue;
  1370. }
  1371. if (drv_msf2lbn(drv_bcd2bin(aBuffer[1]), drv_bcd2bin(aBuffer[2]), drv_bcd2bin(aBuffer[3])) != CurrTrack.dwStartAddress) {
  1372. WORD wMin, wSec, wFrm;
  1373. dbg_printf(("Mismatch between Entries info and TOC info for Track %d.n", (int)uCurrTrack));
  1374. // Override the erroneous location with the TOC information
  1375. PE_CD_GetTrackInfoEx(uCurrTrack, &wMin, &wSec, &wFrm);
  1376. aBuffer[1]= drv_bin2bcd(wMin);
  1377. aBuffer[2]= drv_bin2bcd(wSec);
  1378. aBuffer[3]= drv_bin2bcd(wFrm);
  1379. }
  1380. }
  1381. // Copy the (possibly corrected) information to the Entries-Table
  1382. Array_setAt(g_hEntriesTable, 
  1383. (g_pSVCDNav->m_wEntriesUsedCnt - uEntriesUsedCnt), 
  1384. (BYTE *)aBuffer);
  1385. uEntriesUsedCnt--;
  1386. }
  1387. //We add another dummy item at the end of the entries table to mark the last entry
  1388. aBuffer[0] = 0xFF;
  1389. aBuffer[1] = 0xFF;
  1390. aBuffer[2] = 0xFF;
  1391. aBuffer[3] = 0xFF;
  1392. Array_setAt(g_hEntriesTable, g_pSVCDNav->m_wEntriesUsedCnt, (BYTE *)aBuffer);
  1393. //PSD caching handling - the PSD caching area starts at the end of the entries table.
  1394. if (g_pSVCDNav->m_bIsUsingPSD)
  1395. {
  1396. BYTE ucDummy;
  1397. BOOL bPSDRecordAvaliable;
  1398. //setting the PSD caching address to start at the end of the entries table
  1399. g_pSVCDNav->m_wPSD_CacheOffset = g_uNextStaticAllocationOffset;
  1400. g_uNextStaticAllocationOffset += CONTAINER_COUNT(SVCD_PSD_CACHE_SIZE);//Angie_1117_2004: Add the current malloc size for the next static SCPad malloc.
  1401. SHARED_INFO.bPBC_Available = TRUE;
  1402. // Force caching of the PSD
  1403. g_pSVCDNav->m_dwPSD_CacheBase = NULL_HANDLE;
  1404. bPSDRecordAvaliable = _getPSDRecord(0, 1, &ucDummy);
  1405. if (FALSE == bPSDRecordAvaliable){
  1406. tr_printf(("Can't get PSD Recodern"));
  1407. }
  1408. // bPSDRecordAvaliable = _getPSDRecord(0, 1, &ucDummy);//LX0713: Comment out, no need to do twice
  1409. if (!bPSDRecordAvaliable) 
  1410. {
  1411. dbg_printf(("Failed to cache PSD information.n"));
  1412. g_pSVCDNav->m_bIsUsingPSD = FALSE;
  1413. SHARED_INFO.bPBC_Available = FALSE;
  1414. if (PM_IsPBC(PM_GetPlaybackMode()))
  1415. PM_SetPBC(FALSE);
  1416. return;
  1417. }
  1418. }
  1419. // Mark the base for all CDDA Tracks (if any) in this disc. The first CDDA Track in
  1420. // a SVCD disc is located past the last non-CDDA Track.
  1421. g_pSVCDNav->m_uFirstCDDA_Track= (1 + uCurrTrack);
  1422. // Verify that this track indeed exists and that it actually holds CDDA data.
  1423. // This is done by cross-checking against the TOC info for that track.
  1424. while (g_pSVCDNav->m_uFirstCDDA_Track <= (WORD)PE_CD_GetTracksCnt()) {
  1425. BYTE ucCtrlField;
  1426. DWORD dwDummy;
  1427. if (! PE_CD_GetTrackTOC(g_pSVCDNav->m_uFirstCDDA_Track, &ucCtrlField, &dwDummy, &dwDummy)) {
  1428. dbg_printf(("Failed to acquire TOC information for Track %d.n", g_pSVCDNav->m_uFirstCDDA_Track));
  1429. break;
  1430. }
  1431. // Check if this Track is marked as a CDDA track
  1432. if (0x0 == (ucCtrlField & 0x4))
  1433. break;
  1434. // This track is a Data track - continue to the next one
  1435. g_pSVCDNav->m_uFirstCDDA_Track++;
  1436. }
  1437. //by default there is no MPEG2 directory on the VCD 
  1438. g_pSVCDNav->m_bIsMPEG2 = FALSE;
  1439. g_pSVCDNav->m_uCurrAudioSID = MPEG_SID0;
  1440. SHARED_INFO.uCurrentAudioSIDChannel = 1;
  1441. // For SVCD discs, collect the AV-Tracks information
  1442. if (DEC_DISC_TYPE_SVCD == g_pSVCDNav->m_uDiscStandard) 
  1443. {
  1444. UINT uTracksCnt= (UINT)PE_CD_GetTracksCnt();
  1445. //UINT cbTracksFileSize= SVCD_TRACKS_HDR_SIZE + (SVCD_TRACKS_RECORD_SIZE * uTracksCnt);
  1446. //we keep only the playback time for each track
  1447. //UINT uTracksTableSize = (SVCD_TRACKS_TABLE_ENTRY_SIZE * uTracksCnt);
  1448. DWORD dwTracksFileAddr;
  1449. //g_uTracksTableOffset = sc_Malloc(uTracksTableSize / BYTE_PER_CONTAINER);
  1450. g_hTracksTable = Array_construct(uTracksCnt, SVCD_TRACKS_TABLE_ENTRY_SIZE, NULL);
  1451. if (NULL == g_hTracksTable) {
  1452. dbg_printf(("Failed to allocate memory for the AV-Tracks Table.n"));
  1453. return;
  1454. }
  1455. // Load the TRACKS file
  1456. if ((eISO9660 == FileSys_determineType()) && FileSys_selectType(eISO9660) &&
  1457. FileSys_initialize(FALSE) && FileSys_changeDir(L"SVCD") &&
  1458. FileSys_getFileLocation(L"TRACKS.SVD", &dwTracksFileAddr))
  1459. {
  1460. UINT uInd;
  1461. SVCD_TracksInfo TracksInfo;
  1462. //checking if there is a directory named MPEG2 
  1463. FileSys_goToRootDir();
  1464. g_pSVCDNav->m_bIsMPEG2 = FileSys_changeDir(L"MPEG2");
  1465. //reading the tracks file into the tracks table 
  1466. for (uInd = 0; uInd < uTracksCnt; uInd++)
  1467. {
  1468. if (! AuxCache_GetBytes(dwTracksFileAddr, (SVCD_TRACKS_HDR_SIZE + (SVCD_TRACKS_RECORD_SIZE * uInd)), 
  1469. SVCD_TRACKS_RECORD_SIZE, aBuffer)) 
  1470. {
  1471. dbg_printf(("Failed to load TRACKS.SVD!n"));
  1472. Array_destruct(g_hTracksTable);
  1473. g_hTracksTable = NULL;
  1474. //SHARED_INFO.wTotalPlaybackTime *= 2;
  1475. return;
  1476. }
  1477. //writing the calculated time to the table
  1478. TracksInfo.uTrackTime = ( (drv_bcd2bin(aBuffer[0]) * 60) + //minute
  1479.   (drv_bcd2bin(aBuffer[1]))); //second
  1480. TracksInfo.uAudioInfo = aBuffer[4];
  1481. Array_setAt(g_hTracksTable, uInd, (BYTE *)&TracksInfo);
  1482. //DM051602 no need for this,we already get the total time at the beginning
  1483. //adding it to the total playback time
  1484. //SHARED_INFO.wTotalPlaybackTime += (WORD)TracksInfo.uTrackTime;
  1485. }
  1486. }
  1487. else 
  1488. {
  1489. dbg_printf(("Failed to acquire TRACKS.SVDn"));
  1490. Array_destruct(g_hTracksTable);
  1491. g_hTracksTable = NULL;
  1492. //SHARED_INFO.wTotalPlaybackTime *= 2;
  1493. }
  1494. SHARED_INFO.wRemainingPlaybackTime = SHARED_INFO.wTotalPlaybackTime;
  1495. } // endof if (DEC_DISC_TYPE_SVCD)
  1496. //getting the second track's address for absolute time calculations purposes
  1497. g_pSVCDNav->m_dwSecondTrackAddress = TrackTwo.dwStartAddress;
  1498. // Update the final state of PBC and the Playback-Mode
  1499. if (PM_IsPBC(PM_GetPlaybackMode()) && ! g_pSVCDNav->m_bIsUsingPSD)
  1500. PM_SetPBC(FALSE);
  1501. g_pSVCDNav->m_bIsUsingPSD = PM_IsPBC(PM_GetPlaybackMode());
  1502. g_pSVCDNav->m_ulSecondTrackBlocksPerSecond = _getBlocksPerSecond(2, TrackTwo.ulBlocksCnt);
  1503. PM_SetPBC(g_pSVCDNav->m_bIsUsingPSD);
  1504. // If no PBC is being used, then disable the Return Key
  1505. if (! g_pSVCDNav->m_bIsUsingPSD)
  1506. CLEAR_COP_MASK(COP_RETURN);
  1507. // Update the current Playback-Mode
  1508. g_pSVCDNav->m_uCurrPlaybackMode= PM_GetPlaybackMode();
  1509. // Reset the Error-Recovery mechanism
  1510. (g_pSVCDNav->m_ErrorRecoveryInfo).eRecoveryType= eNoError;
  1511. (g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout= 0;
  1512. (g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter = 0;//LX051302
  1513. #ifdef CVD_ENABLED
  1514. if (g_pSVCDNav->m_bIsEncrypted) {
  1515. // Writing the encoding information to the SDRAM
  1516. if (!PE_CD_EnableCVDDecryption(TRUE, dwEncryptionInfoAddr, dwEncryptionInfoSize))
  1517. {
  1518. dbg_printf(("Failed to extract the Disk-ID.n"));
  1519. g_pSVCDNav->m_bIsEncrypted = FALSE;
  1520. }
  1521. }
  1522. #endif //CVD_ENABLE
  1523. //default setting of the current track information
  1524. g_pSVCDNav->m_aCurrTrack[0]= 0;
  1525. g_pSVCDNav->m_aCurrTrack[1]= -1;
  1526. g_pSVCDNav->m_aCurrTrack[2] = 1;
  1527. //setting the actual value of the disc type
  1528. PE_CD_SetDiscType(g_pSVCDNav->m_uDiscStandard);
  1529. return;
  1530. }
  1531. /////////////////////////////////////////////////////////////////////////////////////////////////
  1532. // void Destructor() -
  1533. // A Destructor for a SVCD-Navigator instance.
  1534. //
  1535. // Input:
  1536. // None.
  1537. //
  1538. // Output:
  1539. // None.
  1540. //
  1541. // Remarks:
  1542. // This method destructs an existing instance of the SVCD-Navigator.
  1543. static void Destructor(void)
  1544. {
  1545. dbg_printf(("SVCD_Destructor()n"));
  1546. #ifdef EXINO2 //ZKR JK0331 : for power_on_resume in EEPROM
  1547. #ifdef HW_POWER_ON_RESUME
  1548. if (g_power_state == POWER_SEQUENCE_OFF_REQUESTED)
  1549. {
  1550. if( (g_in_full_stop != TRUE ) && (PlayList == (gns.svcd.m_CurrPosition).ListType) )
  1551. {
  1552.          SetPSDAvaiableInfo();
  1553.          SetResumeLeadOutInfo();
  1554.          SetCurretnLocationStructure();
  1555.          SetCurrentListInfo();
  1556.          SetVideoTypeInfo();
  1557. }
  1558. }
  1559. #endif//HW_POWER_ON_RESUME
  1560. #else //EXINO2
  1561. #ifdef HW_POWER_ON_RESUME
  1562. NVM_BMK_UnHook();
  1563. #endif
  1564. #endif //EXINO2
  1565. // Abort any playback
  1566. gcs.pstate = PST_STOP;
  1567.     PE_CD_CancelNotification(TriggerBit);   // Cancel the Trigger Bit for Auto Pause
  1568.     
  1569. PE_CD_AbortPlayback(FALSE); // Force a complete stop
  1570. PE_CD_DisplayLogo();
  1571. if (PST_SCAN == gcs.pstate)
  1572. OnScan(0);
  1573. #ifdef CVD_ENABLED
  1574. if (g_pSVCDNav->m_bIsEncrypted) 
  1575. PE_CD_EnableCVDDecryption(FALSE, 0, 0);
  1576. #endif
  1577. #ifdef SVCD_DIGEST_SUPPORT
  1578. if (g_pSVCDNav->m_bDigestMode)
  1579. _terminateDigestMode();
  1580. #endif
  1581. // Free resources
  1582. if (NULL != g_hSegmentsContentTable)
  1583. Array_destruct(g_hSegmentsContentTable);
  1584. if (NULL != g_hEntriesTable)
  1585. {
  1586. Array_destruct(g_hEntriesTable);
  1587. //AngieHe_0114_2005: Should intialize it when destruct,Or it will add again and again when doing open/close many times.
  1588. g_uNextStaticAllocationOffset = SC_SVCD_NAV_ADDR;
  1589. }
  1590. if (NULL != g_hTracksTable)
  1591. Array_destruct(g_hTracksTable);
  1592. g_hSegmentsContentTable = NULL;
  1593. g_hEntriesTable = NULL;
  1594. g_hTracksTable = NULL;
  1595. if (NULL != g_pSVCDNav)
  1596. free(g_pSVCDNav);
  1597. // Cancel any PBC
  1598. PM_SetPBC(FALSE);
  1599. g_in_full_stop = TRUE; /* forces next PLAY to be mapped to RESTART */
  1600. return;
  1601. }
  1602. /////////////////////////////////////////////////////////////////////////////////////////////////
  1603. // BOOL _getPSDRecord( DWORD dwPSD_Offset, WORD uBytesCnt, BYTE *pBuffer) -
  1604. // Retreives a PSD record from the PSD-Cache.
  1605. //
  1606. // Input:
  1607. // This - Points to the current instance of the SVCD-Navigator
  1608. // dwPSW_Offset - The offset within the PSD file of the desired record
  1609. // uBytesCnt - The size of the record to retrieve, in Bytes
  1610. // pBuffer - A pointer to a buffer whose size is at least uBytesCnt Bytes, which
  1611. //   will holds the retrieved record.
  1612. //
  1613. // Output:
  1614. // TRUE on success; FALSE otherwise.
  1615. //
  1616. // Remarks:
  1617. // This function is used to both retrieve a PSD record from the PSD-Cache, and to manage the
  1618. // PSD Cache, which is held in the Scratch-Pad.
  1619. // If the requested PSD-Offset is not found in the Cache, the function flushes the entire
  1620. // Cache, and fills it with PSD information starting from the requested Offset, and until
  1621. // the Cache is full.
  1622. static BOOL _getPSDRecord(DWORD i_dwPSD_Offset, WORD i_uBytesCnt, BYTE *o_pBuffer)
  1623. {
  1624. // First of all, check if the required Record is inside the PSD-Cache
  1625. if ( (NULL_HANDLE == g_pSVCDNav->m_dwPSD_CacheBase) || 
  1626. (i_dwPSD_Offset < (DWORD)g_pSVCDNav->m_dwPSD_CacheBase) ||
  1627. ((i_dwPSD_Offset + i_uBytesCnt) > (g_pSVCDNav->m_dwPSD_CacheBase + SVCD_PSD_CACHE_SIZE)) ) 
  1628. {
  1629. dbg_printf(("PSD-Cache Miss: Caching %d Bytes.n", SVCD_PSD_CACHE_SIZE));
  1630. if (! sc_CopyFromDisc(SVCD_PSD_FILE_ADDRESS, i_dwPSD_Offset, SVCD_PSD_CACHE_SIZE, 
  1631.   g_pSVCDNav->m_wPSD_CacheOffset)) 
  1632. {
  1633. dbg_printf(("Failed to Cache PSD information.n"));
  1634. return FALSE;
  1635. }
  1636. g_pSVCDNav->m_dwPSD_CacheBase = i_dwPSD_Offset;
  1637. }
  1638. // Retrieve the required record from the PSD-Cache in the Scratch-Pad
  1639. sc_GetBytes(g_pSVCDNav->m_wPSD_CacheOffset, (WORD)(i_dwPSD_Offset - g_pSVCDNav->m_dwPSD_CacheBase), (WORD)i_uBytesCnt, o_pBuffer);
  1640. return TRUE;
  1641. }
  1642. //////////////////////////////////////////////////////////////////////////////////
  1643. // Function name : _getBlocksPerSecond
  1644. //
  1645. // Purpose : Calculating the VBR for SVCD according to the TRACKS.SVD
  1646. // file content.
  1647. //
  1648. // Input Parameters : 
  1649. // UINT uTrackNumber
  1650. // ULONG ulTrackSize
  1651. //
  1652. // Return Value : ULONG 
  1653. //
  1654. // Description : Reading the value from the appropriate table in the SDRAM, 
  1655. // while taking under consideration cases in which the values
  1656. // are unavailble because of file corruption or wrong data.
  1657. //////////////////////////////////////////////////////////////////////////////////
  1658. static ULONG _getBlocksPerSecond(UINT uTrackNumber, ULONG ulTrackSize)
  1659. {
  1660. ULONG ulBlocksPerSec= SVCD_BLOCKS_PER_SECOND;
  1661. SVCD_TracksInfo TracksInfo;
  1662. if (DEC_DISC_TYPE_SVCD == g_pSVCDNav->m_uDiscStandard) 
  1663. {
  1664. #if 0
  1665. //if (NULL_HANDLE != g_uTracksTableOffset) 
  1666. if (NULL != g_hTracksTable) 
  1667. {
  1668. Array_getAt(g_hTracksTable, (uTrackNumber - 2), (BYTE *)&TracksInfo);
  1669. if (TracksInfo.uTrackTime > 0) {
  1670. ulBlocksPerSec= (ulTrackSize / TracksInfo.uTrackTime);
  1671. // Sanity check: make sure that the amount is reasonable for an SVCD
  1672. if (ulBlocksPerSec <= SVCD_BLOCKS_PER_SECOND)
  1673. ulBlocksPerSec= (2 * SVCD_BLOCKS_PER_SECOND);
  1674. }
  1675. else
  1676. // Either the table is illegal or track is less than a second
  1677. ulBlocksPerSec= (2 * SVCD_BLOCKS_PER_SECOND);
  1678. }
  1679. else {
  1680. ulBlocksPerSec= (2 * SVCD_BLOCKS_PER_SECOND);
  1681. }
  1682. #else
  1683. ulBlocksPerSec= (2 * SVCD_BLOCKS_PER_SECOND);
  1684. #endif
  1685. }
  1686. dbg_printf(("BlocksPerSecond= %ld.n", ulBlocksPerSec));
  1687. return ulBlocksPerSec;
  1688. }
  1689. #ifdef SVCD_DIGEST_SUPPORT
  1690. //////////////////////////////////////////////////////////////////////////////////
  1691. // Function name : _terminateDigestMode
  1692. //
  1693. // Purpose : Terminating the on going digest mode.
  1694. //
  1695. // Input Parameters : none
  1696. //
  1697. // Return Value : static void 
  1698. //
  1699. // Description : stopping the digest mode, restoring the operation mask, and
  1700. // freeing the digest items array.
  1701. //////////////////////////////////////////////////////////////////////////////////
  1702. static void _terminateDigestMode(void)
  1703. {
  1704. //terminating the current digest session
  1705. Digest_terminate();
  1706. //restoring the operation mask
  1707. SET_COP_MASK(g_pSVCDNav->m_ulCOP_Mask);
  1708. //freeing the digest items array
  1709. // free(g_pSVCDNav->m_uiDigestUnits);
  1710. Array_destruct(g_pSVCDNav->m_uiDigestUnits);
  1711. g_pSVCDNav->m_uiDigestUnits = NULL;
  1712. g_pSVCDNav->m_bDigestMode = FALSE;
  1713. }
  1714. #endif //SVCD_DIGEST_SUPPORT
  1715. //////////////////////////////////////////////////////////////////////////////////
  1716. // Function name : UpdateAudioInfo
  1717. //
  1718. // Purpose : Updating the shared audio information.
  1719. //
  1720. // Input Parameters : 
  1721. // UINT uTrackNumber - the current played track 
  1722. // Return Value : none 
  1723. //
  1724. // Description : Reading the current track's audio information from the 
  1725. // tracks table and updating the shared information of the 
  1726. // current audio sid - currently available audio channels, and
  1727. // the current selected channel. 
  1728. //////////////////////////////////////////////////////////////////////////////////
  1729. static void UpdateAudioInfo(UINT uTrackNumber)
  1730. {
  1731. BYTE uAudioInfo;
  1732. SVCD_TracksInfo TracksInfo;
  1733. #ifndef ASSUME_SVCD_4_AUDIO_CHANNELS
  1734. BOOL bC0_Channel, bC1_Channel;
  1735. #endif
  1736. #ifdef ASSUME_SVCD_4_AUDIO_CHANNELS
  1737. SHARED_INFO.uTotalNumberOfAudioChannels = 4;
  1738. #else
  1739. bC0_Channel = FALSE;
  1740. bC1_Channel = FALSE;
  1741. if (NULL == g_hTracksTable) {
  1742. SHARED_INFO.uCurrentAudioSIDChannel = 1;
  1743. g_pSVCDNav->m_uCurrAudioSID = MPEG_SID0;
  1744. SHARED_INFO.uTotalNumberOfAudioChannels = 1;
  1745. return;
  1746. }
  1747. //reading the tracks audio information from the tracks table
  1748. Array_getAt(g_hTracksTable, (uTrackNumber - 2), (BYTE *)&TracksInfo);
  1749. //updating the shared information
  1750. //default values
  1751. SHARED_INFO.uTotalNumberOfAudioChannels = 0;
  1752. uAudioInfo = TracksInfo.uAudioInfo;
  1753. //Setting the total number of available channels
  1754. if (uAudioInfo & 0x0F) {
  1755. bC0_Channel = TRUE;
  1756. if ((g_pSVCDNav->m_bIsMPEG2) && (uAudioInfo & 0x03))
  1757. SHARED_INFO.uTotalNumberOfAudioChannels = 2;
  1758. else
  1759. SHARED_INFO.uTotalNumberOfAudioChannels++;  
  1760. }
  1761. if ((uAudioInfo & 0xF0) && (!g_pSVCDNav->m_bIsMPEG2)) {
  1762. bC1_Channel = TRUE;
  1763. SHARED_INFO.uTotalNumberOfAudioChannels++;
  1764. }
  1765. if ((bC0_Channel) && (!bC1_Channel)) {
  1766. g_pSVCDNav->m_uCurrAudioSID = MPEG_SID0;
  1767. SHARED_INFO.uCurrentAudioSIDChannel = 1;
  1768. }
  1769. else if ((bC1_Channel) && (!bC0_Channel)) {
  1770. g_pSVCDNav->m_uCurrAudioSID = MPEG_SID1;
  1771. SHARED_INFO.uCurrentAudioSIDChannel = 2;
  1772. }
  1773. else if ((bC1_Channel) && (bC0_Channel)) {
  1774. g_pSVCDNav->m_uCurrAudioSID = ((1 == SHARED_INFO.uCurrentAudioSIDChannel) ? MPEG_SID0: MPEG_SID1);
  1775. }
  1776. #endif
  1777. }
  1778. /////////////////////////////////////////////////////////////////////////////////////////////////
  1779. // void SetMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber) -
  1780. // Sets a certain Marker.
  1781. //
  1782. // Input:
  1783. // eMarkerType - Identifies the type of Marker to set
  1784. // uBookmarkNumber - If the Marker Type is "Bookmark", this parameter supplies the 
  1785. // serial-number of the Bookmark to set
  1786. //
  1787. // Output:
  1788. // None. The appropriate marker is set.
  1789. //
  1790. static void SetMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber)
  1791. {
  1792. SVCD_Marker *pMarker= NULL;
  1793. switch (eMarkerType) 
  1794. {
  1795. case eMarkerA: pMarker= &(g_pSVCDNav->m_PositionA);
  1796. break;
  1797. case eMarkerB: pMarker= &(g_pSVCDNav->m_PositionB);
  1798. break;
  1799. case eResumePlayback:
  1800. pMarker= &(g_pSVCDNav->m_ResumePlayback);
  1801. break;
  1802. case eBookmark:
  1803. if (uBookmarkNumber >= SVCD_MAX_BOOKMARKS)
  1804. pMarker= NULL;
  1805. else
  1806. pMarker= &(g_pSVCDNav->m_Bookmarks[uBookmarkNumber]);
  1807. break;
  1808. }
  1809. if (NULL == pMarker) {
  1810. dbg_printf(("Failed to set the required Marker.n"));
  1811. return;
  1812. }
  1813. // Set the Marker according to the Current-Position. If the current Playback-Status
  1814. // is "Playing", then also record the current location of the Drive.
  1815. memcpy(pMarker, &(SHARED_INFO.m_CurrPosition), sizeof(SVCD_Marker));
  1816. if ((PST_STOP != gcs.pstate)
  1817. #ifdef K1_WL
  1818. && (PST_STILL != gcs.pstate)    //add by wl032404
  1819. #endif
  1820. )
  1821. {
  1822. // Record the current position
  1823. if (SHARED_INFO.bIsElapsedTimeValid) 
  1824. {
  1825. #ifdef SVCD_USE_ABSOLUTE_TIME
  1826. //if (SHARED_INFO.uCurrentTrackNumber < g_pSVCDNav->m_uFirstCDDA_Track)
  1827. pMarker->dwStartAddress = (g_pSVCDNav->m_dwSecondTrackAddress + 
  1828. (SHARED_INFO.iCurrentTime * g_pSVCDNav->m_aCurrTrack[2]));
  1829. //else
  1830. // pMarker->dwStartAddress = SHARED_INFO.iCurrentTime * g_pSVCDNav->m_aCurrTrack[2];
  1831. #else //SVCD_USE_ABSOLUTE_TIME
  1832. pMarker->dwStartAddress = (g_pSVCDNav->m_aCurrTrack[0] + 
  1833. (SHARED_INFO.iCurrentTime * g_pSVCDNav->m_aCurrTrack[2]));
  1834. #endif //SVCD_USE_ABSOLUTE_TIME
  1835. }
  1836. else if ((SHARED_INFO.m_CurrPosition).dwStartAddress != -1) //jeanz_0316_2005 Don't set start address of PBC menu, because it won't find the right address when bookmark play.
  1837. pMarker->dwStartAddress = (PE_CD_GetCurrentLocation() - SVCD_LOCATION_TOLERANCE);
  1838. }
  1839. //add by wl032404
  1840. #ifdef K1_WL
  1841. if (( g_pSVCDNav->m_iCurrVideoType == STILL_LOWRES ) || ( g_pSVCDNav->m_iCurrVideoType == STILL_HIRES )
  1842. && (SelectionList == ((gns.svcd).m_CurrPosition).ListType))
  1843. pMarker->dwStartAddress = -1;
  1844. #endif
  1845. // <<< SEC CH.KO050404:porting from trino code
  1846. #ifdef EXINO2
  1847. if (PST_STOP != gcs.pstate) 
  1848. {
  1849. if ( eMarkerType == eMarkerA )
  1850. {
  1851. core_set_bookmark_info( 4, pMarker->dwStartAddress/75L );         //FW120501 Record time of marker A
  1852. }
  1853. else
  1854. if ( eMarkerType == eBookmark ){//ZORAN LX0319: set bookmark info
  1855. core_set_bookmark_info( uBookmarkNumber + 1, pMarker->dwStartAddress/75L );
  1856. }
  1857. }
  1858. #endif
  1859. // SEC CH.KO050404>>>
  1860. return;
  1861. }
  1862. /////////////////////////////////////////////////////////////////////////////////////////////////
  1863. // void ClearMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber) -
  1864. // Sets a certain Marker.
  1865. //
  1866. // Input:
  1867. // eMarkerType - Identifies the type of Marker to clear
  1868. // uBookmarkNumber - If the Marker Type is "Bookmark", this parameter supplies the 
  1869. // serial-number of the Bookmark to clear
  1870. //
  1871. // Output:
  1872. // None. The appropriate marker is cleared.
  1873. //
  1874. static void ClearMarker(enSVCD_MarkerType eMarkerType, WORD uBookmarkNumber)
  1875. {
  1876. SVCD_Marker *pMarker= NULL;
  1877. switch (eMarkerType) 
  1878. {
  1879. case eMarkerA: pMarker= &(g_pSVCDNav->m_PositionA);
  1880. break;
  1881. case eMarkerB: pMarker= &(g_pSVCDNav->m_PositionB);
  1882. break;
  1883. case eResumePlayback:
  1884. pMarker= &(g_pSVCDNav->m_ResumePlayback);
  1885. break;
  1886. case eBookmark:
  1887. if (uBookmarkNumber >= SVCD_MAX_BOOKMARKS)
  1888. pMarker= NULL;
  1889. else
  1890. pMarker= &(g_pSVCDNav->m_Bookmarks[uBookmarkNumber]);
  1891. break;
  1892. }
  1893. if (NULL == pMarker) {
  1894. dbg_printf(("Failed to clear the required Marker.n"));
  1895. return;
  1896. }
  1897. // Mark the required Marker as invalid
  1898. pMarker->ListType= Undetermined;
  1899. pMarker->dwPSD_Offset= -1;
  1900. pMarker->dwStartAddress= -1;
  1901. pMarker->uListItem= 1;
  1902. return;
  1903. }
  1904. /////////////////////////////////////////////////////////////////////////////////////////////////
  1905. //WORD FindDefaultSelectionOffset(DWORD dwCurrentLocation) -
  1906. // Searches for a Default-Selection List-Offset.
  1907. //
  1908. // Input:
  1909. // dwCurrentLocation - The absolute address of the current location, or -1 if the 
  1910. // decision should be done not based on the current location.
  1911. //
  1912. // Output:
  1913. // The List-Offset of the correct Default-List, or 0xFFFF if such a List cannot
  1914. // be determined.
  1915. //
  1916. // Remarks:
  1917. // This function can select a default List Offset in two differnet manners:
  1918. // 1. In Random;
  1919. // 2. Using the Current-Location - the function goes over the different Entries
  1920. // in the ENTRIES database, until the first Entry which has the same Track-Number
  1921. // as the current Track is found.
  1922. // It then goes over each of the entries associated with the current List, and
  1923. // searches for the two entries that contain the Current Location.
  1924. //
  1925. // Method 1 is suitable of any Selection-List; Method 2 is only applicable for
  1926. // Multi-Default Selection-Lists.
  1927. static WORD FindDefaultSelectionOffset(DWORD dwCurrentLocation)
  1928. {
  1929. BYTE aBuffer[2];
  1930. WORD uOffset= 0xFFFF; //, uSC_Offset;
  1931. WORD uCurrItem;
  1932. WORD uRemainingItemsCnt= ((SHARED_INFO.m_CurrList).SelectionList).uSelectionsCnt;
  1933. WORD uTrackNumber, uCurrSection;
  1934. BYTE aCurrEntry[4], aNextEntry[4];
  1935. DWORD dwPSD_Base= ((SHARED_INFO.m_CurrPosition).dwPSD_Offset + SVCD_SELECTIONLIST_HDR_SIZE);
  1936. DWORD dwTrackStartAddress;
  1937. UINT16 uIndex=0;
  1938. // First of all, check how to make the selection: in Random, or based on the Current-Location
  1939. if (-1 == dwCurrentLocation) {
  1940. // Make a Random selection
  1941. dbg_printf(("Selecting the first suitable item on the list.n"));
  1942. // Randomly draw some Item in the Selection-List
  1943. if (((SHARED_INFO.m_CurrList).SelectionList).uSelectionsCnt != 0 )//LX0902: Check if zero
  1944. uCurrItem= (rand() % ((SHARED_INFO.m_CurrList).SelectionList).uSelectionsCnt);
  1945. else
  1946. return (WORD)-1;
  1947. // Seek the Items in the List, until an item with a valid offset is found.
  1948. // The list is searched in a cyclic manner.
  1949. while (0 < uRemainingItemsCnt--) {
  1950. // Try to retrieve the appropriate record from the PSD
  1951. if (! _getPSDRecord((dwPSD_Base + (2 * uCurrItem)), 2, aBuffer)) {
  1952. dbg_printf(("Failed to retrieve PSD information.n"));
  1953. return (WORD)-1;
  1954. }
  1955. // Extract and check the value of the Item's offset in the PSD
  1956. uOffset= ((aBuffer[0] << 8) | aBuffer[1]);
  1957. // Check if the current Item has a valid Offset
  1958. if (0xFFFF != uOffset)
  1959. break;
  1960. // The current Item has no valid Offset: continue to check the next item,
  1961. // cyclically.
  1962. uCurrItem= ((uCurrItem+1) % ((SHARED_INFO.m_CurrList).SelectionList).uSelectionsCnt);
  1963. }
  1964. if (0xFFFF == uOffset) {
  1965. dbg_printf(("Cannot find any item on the List suitable for default playback.n"));
  1966. return (WORD)-1;
  1967. }
  1968. return uOffset;
  1969. }
  1970. // Make a selection based on the current Play-Item and the Current-Location (Multi-Default Selection)
  1971. // If the current Play-Item is a Track, find the first Entry containing this Track in the Database.
  1972. if (((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber < 100) {
  1973. uTrackNumber= ((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber;
  1974. }
  1975. else {
  1976. Array_getAt(g_hEntriesTable, 
  1977. (((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber - 100), 
  1978. (BYTE *)aCurrEntry);
  1979. uTrackNumber= (WORD)drv_bcd2bin(aCurrEntry[0]);
  1980. }
  1981. // Go over each of the Entries, until an Entry with the requested
  1982. // Track-Number is found.
  1983. //uSC_Offset = g_uEntriesTableOffset;
  1984. //sc_Read(uSC_Offset, SVCD_ENTRY_SIZE / BYTE_PER_CONTAINER, (Sc_cont*)aCurrEntry);
  1985. uIndex = 0;
  1986. Array_getAt(g_hEntriesTable, uIndex, (BYTE *)aCurrEntry);
  1987. while (uTrackNumber != (WORD)drv_bcd2bin(aCurrEntry[0])) {
  1988. Array_getAt(g_hEntriesTable, ++uIndex, (BYTE *)aCurrEntry);
  1989. }
  1990. // Extract the Start-Address of the Current Track
  1991. dwTrackStartAddress= drv_msf2lbn(drv_bcd2bin(aCurrEntry[1]), drv_bcd2bin(aCurrEntry[2]), drv_bcd2bin(aCurrEntry[3]));
  1992. // In a Multi-Default Selection-List, it is guaranteed that the Track is divided to at least uSelectionsCnt
  1993. // sections, therefore start checking the Current-Location against each of these sections, until the 
  1994. // section containing the Current-Location is found.
  1995. Array_getAt(g_hEntriesTable, ++uIndex, (BYTE *)aNextEntry);
  1996. //checking if the next entry is the last entry in the table
  1997. if ( (0xFF == aNextEntry[0]) && (0xFF == aNextEntry[1]) &&
  1998.  (0xFF == aNextEntry[2]) && (0xFF == aNextEntry[3]) )
  1999. {
  2000. uCurrSection = (uRemainingItemsCnt - 1); //the last section
  2001. }
  2002. else
  2003. {
  2004. for (uCurrSection= 0; uRemainingItemsCnt; uCurrSection++, uRemainingItemsCnt--) {
  2005. DWORD dwStartAddress= drv_msf2lbn(drv_bcd2bin(aCurrEntry[1]), drv_bcd2bin(aCurrEntry[2]), drv_bcd2bin(aCurrEntry[3]));
  2006. DWORD dwEndAddress=   drv_msf2lbn(drv_bcd2bin(aNextEntry[1]), drv_bcd2bin(aNextEntry[2]), drv_bcd2bin(aNextEntry[3]));
  2007. UINT32 uStartTime= ((dwStartAddress - dwTrackStartAddress) / SVCD_BLOCKS_PER_SECOND);
  2008. UINT32 uEndTime=   ((dwEndAddress - dwTrackStartAddress) / SVCD_BLOCKS_PER_SECOND);
  2009. // First, check for an actual match
  2010. if ((dwStartAddress <= dwCurrentLocation) && (dwCurrentLocation < dwEndAddress))
  2011. break;
  2012. // Second, try to match based on the Elapsed-Time, assuming a Fixed-Bitrate and a relation
  2013. // of 75-Sectors per Second.
  2014. if ((uStartTime <= SHARED_INFO.iCurrentTime) && (SHARED_INFO.iCurrentTime < uEndTime))
  2015. break;
  2016. // Third, try to match taking into consideration a fixed Tolerance, which arises from
  2017. // buffering delays.
  2018. if (((dwCurrentLocation - SVCD_LOCATION_TOLERANCE) >= dwStartAddress) &&
  2019. ((dwCurrentLocation - SVCD_LOCATION_TOLERANCE) < dwEndAddress))
  2020. break;
  2021. // There isn't a match under any criterion -- continue to the next Entry
  2022. *(DWORD*)aCurrEntry = *(DWORD*)aNextEntry;
  2023. //uSC_Offset += SVCD_ENTRY_SIZE / BYTE_PER_CONTAINER;
  2024. //sc_Read(uSC_Offset, SVCD_ENTRY_SIZE / BYTE_PER_CONTAINER, (Sc_cont*)aNextEntry);
  2025. uIndex++;
  2026. Array_getAt(g_hEntriesTable, uIndex, (BYTE *)aNextEntry);
  2027. }
  2028. }
  2029. // Now, uCurrSection holds the Zero-based offset inside the current Selection-List, which 
  2030. // holds the offset of the appropriate Default Item.
  2031. if (! _getPSDRecord((dwPSD_Base + (2*uCurrSection)), 2, aBuffer)) {
  2032. dbg_printf(("Failed to retrieve PSD information.n"));
  2033. return (WORD)-1;
  2034. }
  2035. uOffset= ((aBuffer[0] << 8) | aBuffer[1]);
  2036. return uOffset;
  2037. }
  2038. /////////////////////////////////////////////////////////////////////////////////////////////////
  2039. // BOOL PlayItem(WORD uPlayItemNumber, DWORD dwStartPosition) -
  2040. // Executes a playback of a certain Play-Item.
  2041. //
  2042. // Input:
  2043. // uPlayItemNumber - The absolute Number of the Play-Item (PIN)
  2044. // dwStartPosition - The absolute address from which to actually start the playback,
  2045. //   or -1 if the item should be played from its beginning.
  2046. //
  2047. // Output:
  2048. // TRUE if the playback has been started successfully; FALSE otherwise.
  2049. //
  2050. // Remarks:
  2051. // The function determines which kind of Item is being played: a Track, an Entry
  2052. // or a Segment.
  2053. // Accordingly, the correct starting-address, length and Stream-specific paramters
  2054. // are computed.
  2055. // Prior to actually invoking playback, the function calls for Automatic Video-Setting detection,
  2056. // to allow the decoder to perform Scaling when needed.
  2057. static BOOL PlayItem(WORD uPlayItemNumber, DWORD dwStartPosition)
  2058. {
  2059. WORD uCurrTrack= 0;
  2060. DWORD dwSegmentStartAddress= 0;
  2061. DWORD dwPlaybackStartAddress= 0;
  2062. ULONG ulMaxBlocksCnt= 0;
  2063. ULONG ulBlocksCnt= 0;
  2064. DWORD dwActualItemStart;
  2065. UINT16 uIndex;
  2066. enPlaybackType ePBType= eNormalSpeed;
  2067. ULONG ulPlaybackParam= 0;
  2068. dbg_printf(("Playing PIN 0x%04x --> ", uPlayItemNumber));
  2069. g_pSVCDNav->m_bIsSegment = FALSE;
  2070. g_pSVCDNav->m_iCurrVideoType= NoVideo;
  2071. #ifndef ASSUME_SVCD_4_AUDIO_CHANNELS
  2072. g_pSVCDNav->m_uCurrAudioSID= NoAudio;
  2073. #endif
  2074. // Configure the Playback-Type and Parameter according to the current Play-State
  2075. if (PST_SCAN == gcs.pstate) {
  2076. ePBType= eScan;
  2077. ulPlaybackParam= (ULONG)SHARED_INFO.m_iScanSpeed;
  2078. }
  2079. else if (PST_SLOW == gcs.pstate) {
  2080. ePBType= eSlowMotion;
  2081. ulPlaybackParam= (ULONG)SHARED_INFO.m_iSlowSpeed;
  2082. }
  2083. // Envalidate the Elapsed-Time gauge
  2084. SHARED_INFO.bIsElapsedTimeValid= TRUE;
  2085. SET_COP_MASK(COP_ABREPEAT);
  2086. // Clear the Elapsed-Time, if the Item is going to be played from its beginning
  2087. #ifndef SVCD_USE_ABSOLUTE_TIME
  2088. if (-1 == dwStartPosition)
  2089. SHARED_INFO.iCurrentTime= 0;
  2090. #endif //SVCD_USE_ABSOLUTE_TIME
  2091. // Configure the Time-Measurement information:
  2092. // By default, use PTS's for measurement. Invalidate the Start-PTS, and
  2093. // reset the Time-Offset.
  2094. #ifdef USE_PTS_TO_MEASURE_TIME
  2095. if( (ePBType != eScan) && (ePBType != eSlowMotion) )//jeanz_0511_2005 Fix stuck problem during boundary scan.
  2096. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= TRUE; // By default, measuer using PTS's
  2097. #else
  2098. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= FALSE; // Measuer not using PTS's
  2099. #endif
  2100. (g_pSVCDNav->m_TimeMeasurementInfo).bAcquireStartPTS= TRUE;
  2101. #ifndef SVCD_USE_ABSOLUTE_TIME
  2102. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset= 0;
  2103. #endif //SVCD_USE_ABSOLUTE_TIME
  2104. if (uPlayItemNumber < 2) {
  2105. if (! g_pSVCDNav->m_bIsUsingPSD) {
  2106. // If PBC is not used, then this is an invalid PIN.
  2107. dbg_printf(("Invalid PIN: %u.n", uPlayItemNumber));
  2108. return FALSE;
  2109. }
  2110. // <<< SEC shKang032304 : Emergency for Invalid PlayItem
  2111. #ifdef TRINO_MODEL
  2112. else{
  2113. if(PlayList == (SHARED_INFO.m_CurrPosition).ListType && !uPlayItemNumber){
  2114. uPlayItemNumber = 2;
  2115. g_ui_misc_flags.m_bIllegalVCD = TRUE;// <<< SEC CH.KO041404
  2116. PM_SetPBC(FALSE);
  2117. OnModeChange();
  2118. }
  2119. }
  2120. #endif // TRINO_MODEL
  2121. // SEC shKang032304 >>>
  2122. // PBC is being used: this is a special case, of a Play-Item that
  2123. // actually displays nothing. Just pretend to be playing something.
  2124. // For a Selection-List, emulate a single iteration (regardless of the value
  2125. // of the Repeat-Count field).
  2126. if (SelectionList == (SHARED_INFO.m_CurrPosition).ListType)
  2127. ((SHARED_INFO.m_CurrList).SelectionList).uRepeatCnt= 1;
  2128. dbg_printf(("Connectivity Node.n"));
  2129. dbg_printf(("Invalid PIN: %u! skip to next play item.n",uPlayItemNumber));
  2130. ie_send(IE_CORE_CDNAV_FINISHED);
  2131. return TRUE;
  2132. }
  2133. SET_COP_MASK(COP_STOP | COP_PAUSE | COP_SLOW | COP_SCAN | COP_SCAN_BACKWARD | COP_STEP);
  2134. if ((uPlayItemNumber >= 2) && (uPlayItemNumber <= 99)) {
  2135. // The Play-Item is a Track within the Disc: Check if it contains CDDA Audio or not,
  2136. // and arrange for its playback, taking into considertation the value of the Playing-Time
  2137. // in the case of a PlayList.
  2138. TrackInfo CurrTrack;
  2139. dbg_printf(("Track #%u.n", uPlayItemNumber));
  2140. g_pSVCDNav->m_iCurrVideoType= MPEG_2;
  2141. if (uPlayItemNumber < g_pSVCDNav->m_uFirstCDDA_Track) {
  2142. // This is an AV Track
  2143. g_pSVCDNav->m_uCurrAudioSID = (MPEG_SID0|SI_SVCD_AUDIO_NUM-1);
  2144. UpdateAudioInfo(uPlayItemNumber);
  2145. SET_COP_MASK(COP_ZOOM);
  2146. }
  2147. else {
  2148. // This is a CDDA Track
  2149. g_pSVCDNav->m_uCurrAudioSID = CDDA_SID;
  2150. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= FALSE; // For CDDA, use MSF instead of PTS
  2151. if (PST_SCAN == gcs.pstate) 
  2152. ePBType = eSearch;
  2153. //When playnig a CDDA slow & step & zoom are prohibited
  2154. CLEAR_COP_MASK(COP_SLOW | COP_STEP | COP_ZOOM);
  2155. }
  2156. // Acquire information of the associated Track
  2157. if ( PE_CD_GetTrackInfo(((ULONG)PE_CD_GetTracksCnt()==1?1:uPlayItemNumber), &CurrTrack)) 
  2158. {
  2159. if(PE_CD_GetTracksCnt()==1)
  2160. {
  2161. BYTE aBuffer[SVCD_INFO_HDR_SIZE];
  2162. DWORD dwStartAddress;
  2163. if (AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, 0, SVCD_ENTRIES_HDR_SIZE, aBuffer)) 
  2164. {
  2165. if ((0 == strncmp((LPSTR)aBuffer, "ENTRYVCD", 8)) ||
  2166. (0 == strncmp((LPSTR)aBuffer, "ENTRYSVD", 8)))
  2167. if ( AuxCache_GetBytes(SVCD_ENTRIES_FILE_ADDRESS, 12, 4, aBuffer)) 
  2168. {
  2169. dwStartAddress = drv_msf2lbn(drv_bcd2bin(aBuffer[1]), drv_bcd2bin(aBuffer[2]), drv_bcd2bin(aBuffer[3]));
  2170. CurrTrack.ulBlocksCnt = CurrTrack.ulBlocksCnt + CurrTrack.dwStartAddress - dwStartAddress;
  2171. CurrTrack.dwStartAddress=dwStartAddress;
  2172. }
  2173. }
  2174. }
  2175. }
  2176. else
  2177. {
  2178. dbg_printf(("Failed to enumerate Track Information.n"));
  2179. return FALSE;
  2180. }
  2181. uCurrTrack= uPlayItemNumber;
  2182. dwSegmentStartAddress= CurrTrack.dwStartAddress;
  2183. ulMaxBlocksCnt= CurrTrack.ulBlocksCnt;
  2184. // Record the boundaries of the Track
  2185. g_pSVCDNav->m_aCurrTrack[0]= CurrTrack.dwStartAddress;
  2186. g_pSVCDNav->m_aCurrTrack[1]= CurrTrack.dwStartAddress + CurrTrack.ulBlocksCnt;
  2187. g_pSVCDNav->m_aCurrTrack[2] = _getBlocksPerSecond(uCurrTrack, CurrTrack.ulBlocksCnt);
  2188. dwActualItemStart= CurrTrack.dwStartAddress;
  2189. if (! g_pSVCDNav->m_bIsUsingPSD) {
  2190. // When the PSD is NOT being used, then the Play-Items are always Track numbers
  2191. if (-1 == dwStartPosition) {
  2192. dwPlaybackStartAddress= CurrTrack.dwStartAddress;
  2193. ulBlocksCnt= CurrTrack.ulBlocksCnt;
  2194. }
  2195. else {
  2196. dwPlaybackStartAddress= dwStartPosition;
  2197. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2198. }
  2199. }
  2200. else {
  2201. // When the PSD is being used, distinguish between a Play-List and a Selection-List
  2202. if (PlayList == (SHARED_INFO.m_CurrPosition).ListType) {
  2203. ULONG ulListPlaySectors;
  2204. ulListPlaySectors = (ULONG)( 5*(ULONG)gns.svcd.m_CurrList.PlayList.uPlayingTime);
  2205. // For a Play-List, play from the Start-Address, if one is supplied. The amount
  2206. // of Blocks to play is then determined by the Playing-Time for this Item.
  2207. if (-1 == dwStartPosition) {
  2208. dwPlaybackStartAddress= CurrTrack.dwStartAddress;
  2209. ulBlocksCnt= (0 == ((SHARED_INFO.m_CurrList).PlayList).uPlayingTime) ? 
  2210.   CurrTrack.ulBlocksCnt : ulListPlaySectors;
  2211. }
  2212. else {
  2213. dwPlaybackStartAddress= dwStartPosition;
  2214. if (0 == ((SHARED_INFO.m_CurrList).PlayList).uPlayingTime) {
  2215. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2216. }
  2217. else {
  2218. DWORD dwDestinationAddress= (CurrTrack.dwStartAddress + ulListPlaySectors);
  2219. ulBlocksCnt= (dwDestinationAddress - dwPlaybackStartAddress);
  2220. }
  2221. }
  2222. }
  2223. else {
  2224. // For a Selection-List, play from the Start-Address, if one is supplied. Play
  2225. // until the End of the Item.
  2226. if (-1 == dwStartPosition) {
  2227. dwPlaybackStartAddress= CurrTrack.dwStartAddress;
  2228. ulBlocksCnt= CurrTrack.ulBlocksCnt;
  2229. }
  2230. else {
  2231. dwPlaybackStartAddress= dwStartPosition;
  2232. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2233. }
  2234. }
  2235. }
  2236. // Set the Time-Offset for Time Measurement
  2237. #ifdef SVCD_USE_ABSOLUTE_TIME
  2238. if (!g_pSVCDNav->m_bIsUsingPSD)
  2239. {
  2240. if (uPlayItemNumber < g_pSVCDNav->m_uFirstCDDA_Track)
  2241. //calculating the absolute time offset from the beginning of track #2
  2242. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset = (int)((dwPlaybackStartAddress - g_pSVCDNav->m_dwSecondTrackAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2243. else
  2244. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset = (int)(dwPlaybackStartAddress / g_pSVCDNav->m_aCurrTrack[2]);
  2245. }
  2246. else
  2247. //in case PBC on, we use relative time only
  2248. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset = (int)((dwPlaybackStartAddress - CurrTrack.dwStartAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2249. #else //SVCD_USE_ABSOLUTE_TIME
  2250. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset = (int)((dwPlaybackStartAddress - CurrTrack.dwStartAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2251. #endif //SVCD_USE_ABSOLUTE_TIME
  2252. }
  2253. else if ((uPlayItemNumber >= 100) && (uPlayItemNumber <= 599)) {
  2254. // The Play-Item is an Entry from the Entries-Database: Extract the appropriate record
  2255. // and arrange for playback of the item, taking into consideration the value of the Playing-Time
  2256. // in the case of a PlayList.
  2257. BYTE aBuffer[4];
  2258. TrackInfo CurrTrack;
  2259. dbg_printf(("Entry #%u.n", (uPlayItemNumber - 99)));
  2260. // Extract the Entry from the Entries-Table
  2261. //sc_Read(g_uEntriesTableOffset + (SVCD_ENTRY_SIZE * (uPlayItemNumber - 100) / BYTE_PER_CONTAINER), 
  2262. // (SVCD_ENTRY_SIZE / BYTE_PER_CONTAINER), (Sc_cont*)aBuffer);
  2263. Array_getAt(g_hEntriesTable, (uPlayItemNumber - 100), (BYTE *)aBuffer);
  2264. dbg_printf(("Track %02x, %02x:%02x:%02xn", aBuffer[0], aBuffer[1], aBuffer[2], aBuffer[3]));
  2265. uCurrTrack= (WORD)drv_bcd2bin(aBuffer[0]);
  2266. // Check if the Entry is inside a CDDA Track
  2267. g_pSVCDNav->m_iCurrVideoType= MPEG_2;
  2268. if ( DEC_DISC_TYPE_SVCD != g_pSVCDNav->m_uDiscStandard )
  2269. g_pSVCDNav->m_uCurrAudioSID= MPEG_SID0;
  2270. else
  2271. g_pSVCDNav->m_uCurrAudioSID = (MPEG_SID0|SI_SVCD_AUDIO_NUM-1); //DM080205
  2272. //g_pSVCDNav->m_iCurrAudioType= (uCurrTrack >= g_pSVCDNav->m_uFirstCDDA_Track) ? CDDA_SID : MPEG_SID;
  2273. UpdateAudioInfo(uCurrTrack);
  2274. // Retrieve Track-Information, for future use
  2275. if (! PE_CD_GetTrackInfo((int)uCurrTrack, &CurrTrack)) {
  2276. dbg_printf(("Failed to extract Track information.n"));
  2277. return FALSE;
  2278. }
  2279. // Record the boundaries of the containing Track
  2280. g_pSVCDNav->m_aCurrTrack[0]= CurrTrack.dwStartAddress;
  2281. g_pSVCDNav->m_aCurrTrack[1]= (CurrTrack.dwStartAddress + CurrTrack.ulBlocksCnt);
  2282. g_pSVCDNav->m_aCurrTrack[2] = _getBlocksPerSecond(uCurrTrack, CurrTrack.ulBlocksCnt);
  2283. // Calculate the start address
  2284. dwSegmentStartAddress= drv_msf2lbn(drv_bcd2bin(aBuffer[1]), drv_bcd2bin(aBuffer[2]), drv_bcd2bin(aBuffer[3]));
  2285. dwActualItemStart= dwSegmentStartAddress;
  2286. // ulMaxBlocksCnt= CurrTrack.ulBlocksCnt;
  2287. ulMaxBlocksCnt = (CurrTrack.dwStartAddress + CurrTrack.ulBlocksCnt) - dwActualItemStart;
  2288. // Calculate the number of Blocks to play, according to the List Type and the
  2289. // Start-Address.
  2290. if (PlayList == (SHARED_INFO.m_CurrPosition).ListType) {
  2291. ULONG ulListPlaySectors;
  2292. ulListPlaySectors = (ULONG)( 5*(ULONG)gns.svcd.m_CurrList.PlayList.uPlayingTime);
  2293. // For a Play-List, play from the Start-Address, if one is supplied. The amount
  2294. // of Blocks to play is then determined by the Playing-Time for this Item.
  2295. if (-1 == dwStartPosition) {
  2296. dwPlaybackStartAddress= dwSegmentStartAddress;
  2297. if (0 == ((SHARED_INFO.m_CurrList).PlayList).uPlayingTime) 
  2298. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2299. else
  2300. ulBlocksCnt= ulListPlaySectors;
  2301. }
  2302. else {
  2303. dwPlaybackStartAddress= dwStartPosition;
  2304. if (0 == ((SHARED_INFO.m_CurrList).PlayList).uPlayingTime) {
  2305. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2306. }
  2307. else {
  2308. DWORD dwDestinationAddress= (dwSegmentStartAddress + ulListPlaySectors);
  2309. ulBlocksCnt= (dwDestinationAddress - dwPlaybackStartAddress);
  2310. }
  2311. }
  2312. }
  2313. else {
  2314. // For a Selection-List, play from the Start-Address, if one is supplied. Play
  2315. // until the End of the Item.
  2316. if (-1 == dwStartPosition)
  2317. dwPlaybackStartAddress= dwSegmentStartAddress;
  2318. else
  2319. dwPlaybackStartAddress= dwStartPosition;
  2320. ulBlocksCnt= (CurrTrack.ulBlocksCnt - (dwPlaybackStartAddress - CurrTrack.dwStartAddress));
  2321. }
  2322. #ifdef SVCD_USE_ABSOLUTE_TIME
  2323. if (!g_pSVCDNav->m_bIsUsingPSD)
  2324. //calculating the absolute time offset from the beginning of track #2
  2325. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset = (int)((dwPlaybackStartAddress - g_pSVCDNav->m_dwSecondTrackAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2326. else
  2327. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset= (int)((dwPlaybackStartAddress - CurrTrack.dwStartAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2328. #else
  2329. // Set the Time-Offset for Time Measurement
  2330. (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset= (int)((dwPlaybackStartAddress - CurrTrack.dwStartAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  2331. #endif //SVCD_USE_ABSOLUTE_TIME
  2332. }
  2333. else if ((uPlayItemNumber >= 1000) && (uPlayItemNumber <= 2979)) {
  2334. // The Play-Item is a Segment Play-Item: Search for the corresponding structure within
  2335. // the Items-List.
  2336. SVCD_SegmentPlayItem CurrItem;
  2337. BYTE uSegmentContents;
  2338. dbg_printf(("Segment #%u.n", (uPlayItemNumber - 999)));
  2339. #if 0
  2340. //DM080602 fix sometime menu got scrached
  2341. if (gps->tv_standard == TV_SYS_AUTO)
  2342. {
  2343. BOOL bVideoTypeIsPal = FALSE;
  2344. if (! AuxCache_GetBytes(SVCD_INFO_FILE_ADDRESS, SVCD_SEGMENT_OFFSET_IN_INFO+uPlayItemNumber-1000, 1, &uSegmentContents)) {
  2345. dbg_printf(("Failed to parse the Segments Play-Items Table!n"));
  2346. }
  2347. if ((uSegmentContents & 0x1C) > 0x10)
  2348. {
  2349. //PAL segment
  2350. bVideoTypeIsPal = TRUE;
  2351. }
  2352. else if ((uSegmentContents & 0x1C) > 0)
  2353. {
  2354. //NTSC segment
  2355. bVideoTypeIsPal = FALSE;
  2356. }
  2357. PE_CD_Set_OutputVideo_Fromat(bVideoTypeIsPal);
  2358. }
  2359. #endif
  2360. g_pSVCDNav->m_bIsSegment = TRUE;
  2361. // Invalidate the Elapsed-Time indication for Segments, and prohibit A-B Repeat inside
  2362. // a Segment.
  2363. SHARED_INFO.bIsElapsedTimeValid= FALSE;
  2364. SHARED_INFO.iCurrentTime= 0;
  2365. CLEAR_COP_MASK(COP_ABREPEAT);
  2366. SHARED_INFO.uCurrentTrackNumber = uCurrTrack= 1; // Segment Play-Items are always located in Track #1
  2367. g_pSVCDNav->m_aCurrTrack[0] = 0;
  2368. g_pSVCDNav->m_aCurrTrack[1] = -1;
  2369. g_pSVCDNav->m_aCurrTrack[2] = (DEC_DISC_TYPE_SVCD == g_pSVCDNav->m_uDiscStandard) ? 2*SVCD_BLOCKS_PER_SECOND : SVCD_BLOCKS_PER_SECOND;
  2370. CurrItem.uSegmentNumber = 0;
  2371. //Reading the segments and getting the PSD Table offset on the SDRAM
  2372. uIndex= 0;
  2373. while (CurrItem.uSegmentNumber != (uPlayItemNumber - 999)) {
  2374. Array_getAt(g_hSegmentsContentTable, uIndex++, (BYTE *)&CurrItem);
  2375. }
  2376. // Calculate the Start-Address of the Play-Item, assuming that each Segment has a constant
  2377. // size of 2 Seconds.
  2378. dwSegmentStartAddress= (((DWORD)uPlayItemNumber - 1000) * SVCD_BLOCKS_PER_SEGMENT) +
  2379. (DWORD)drv_msf2lbn(drv_bcd2bin((g_pSVCDNav->m_NavigationInfo).aFirstSegmentAddress[0]),
  2380.    drv_bcd2bin((g_pSVCDNav->m_NavigationInfo).aFirstSegmentAddress[1]),
  2381.    drv_bcd2bin((g_pSVCDNav->m_NavigationInfo).aFirstSegmentAddress[2]));
  2382. dwActualItemStart = dwSegmentStartAddress;
  2383. if (-1 == dwStartPosition) {
  2384. dwPlaybackStartAddress= dwSegmentStartAddress;
  2385. ulBlocksCnt = CurrItem.uSubSegmentCnt * SVCD_BLOCKS_PER_SEGMENT;
  2386. }
  2387. else {
  2388. dwPlaybackStartAddress= dwStartPosition;
  2389. ulBlocksCnt= ((CurrItem.uSubSegmentCnt * SVCD_BLOCKS_PER_SEGMENT) - (dwStartPosition - dwSegmentStartAddress));
  2390. }
  2391. ulMaxBlocksCnt = CurrItem.uSubSegmentCnt * SVCD_BLOCKS_PER_SEGMENT;
  2392. // Check if the Play-Item contains Audio
  2393. if (CurrItem.uContents & 0x3)
  2394. g_pSVCDNav->m_uCurrAudioSID= MPEG_SID0;
  2395. else //DM091702 means no audio
  2396. g_pSVCDNav->m_uCurrAudioSID= NoAudio;
  2397.       
  2398. // Check if the Play-Item has a Still Image or Motion video, and  check the Resolution 
  2399. // settings
  2400. switch ((CurrItem.uContents & 0xC) >> 2) 
  2401. {
  2402. case 0x1:
  2403. g_pSVCDNav->m_iCurrVideoType= STILL_LOWRES;
  2404. //slow motion and scan is prohibited during still images playback
  2405. CLEAR_COP_MASK(COP_SLOW | COP_SCAN | COP_SCAN_BACKWARD);
  2406. //clearing previous zoom operation
  2407. ie_send_ex(IE_CORE_ZOOM, (void*)NO_ZOOM);
  2408. #ifdef D_ENABLE_ELAPSEDTIME_FOR_SLIDESHOW
  2409. // In still picture, allow display of the Elapsed-Time
  2410. if ( PlayList == (SHARED_INFO.m_CurrPosition).ListType)
  2411. SHARED_INFO.bIsElapsedTimeValid= TRUE;
  2412. #endif
  2413. break;
  2414. case 0x2:
  2415. g_pSVCDNav->m_iCurrVideoType= STILL_HIRES;
  2416. //slow motion and scan is prohibited during still images playback
  2417. CLEAR_COP_MASK(COP_SLOW | COP_SCAN | COP_SCAN_BACKWARD);
  2418. //clearing previous zoom operation
  2419. ie_send_ex(IE_CORE_ZOOM, (void*)NO_ZOOM);
  2420. #ifdef D_ENABLE_ELAPSEDTIME_FOR_SLIDESHOW
  2421. // In still picture, allow display of the Elapsed-Time
  2422. if ( PlayList == (SHARED_INFO.m_CurrPosition).ListType)
  2423. SHARED_INFO.bIsElapsedTimeValid= TRUE;
  2424. #endif
  2425. break;
  2426. case 0x3:
  2427. g_pSVCDNav->m_iCurrVideoType= MPEG_2;
  2428. // In MPEG-2 streams, allow display of the Elapsed-Time
  2429. SHARED_INFO.bIsElapsedTimeValid= TRUE;
  2430. break;
  2431. }
  2432. //<<<LX091202
  2433. if ( ( g_pSVCDNav->m_iCurrVideoType == STILL_HIRES ) || ( g_pSVCDNav->m_iCurrVideoType == STILL_LOWRES ) )
  2434. g_pSVCDNav->ucStillPicturePlaybackFinishedGapCounter = SVCD_STILL_PICTURE_MISS_TIMEOUT;
  2435. else
  2436. g_pSVCDNav->ucStillPicturePlaybackFinishedGapCounter = 0x00;
  2437. //LX091202>>>
  2438. #ifdef _DEBUG
  2439. // Check the Encoding-System of the Play-Item
  2440. if (CurrItem.uContents & 0x10)
  2441. dbg_printf(("Encoding-System is NTSC.n"));
  2442. else
  2443. dbg_printf(("Encoding-System is PAL.n"));
  2444. #endif //_DEBUG
  2445. }
  2446. else
  2447. {
  2448. dbg_printf(("Invalid PIN: %u! skip to next play item.n",uPlayItemNumber));
  2449. ie_send(IE_CORE_CDNAV_FINISHED);
  2450. return TRUE;
  2451. }
  2452. // In case of Random-Access, call for Video-Settings detection, unless the item is a CDDA Track
  2453. if ((CDDA_SID != g_pSVCDNav->m_uCurrAudioSID)
  2454. #if defined(ENHANCED_SEQ_HDR_READING) || defined(EXINO2) // ZKR GL050104 : Eliminate unnecessary sequence header reads. 
  2455.   && (g_ucReadSeqHdr || g_pSVCDNav->m_bIsUsingPSD)
  2456. #endif 
  2457. && (PST_SCAN != gcs.pstate) 
  2458. &&((g_disc_type == DEC_DISC_TYPE_VCD) || (g_disc_type == DEC_DISC_TYPE_SVCD)) )
  2459. {
  2460. if(!(PM_GetRepeatAB()&PM_REPEAT_AB_B))
  2461. { if (! PE_CD_AutoDetectVideoSetting(g_pSVCDNav->m_iCurrVideoType, dwSegmentStartAddress, ulMaxBlocksCnt)) {
  2462. dbg_printf(("Failed to detect Video settings.n"));
  2463. }
  2464. }
  2465. }
  2466. #ifdef D_ENABLE_SVCD_SAMPLE_RATE_DETECTION
  2467. if ( ( g_disc_type == DEC_DISC_TYPE_SVCD ) && ( PST_SCAN != gcs.pstate ) && ( PST_SLOW != gcs.pstate ) )
  2468. gns.svcd.ulSVDSamplingRate = PE_CD_AutoDetectAudioSetting(g_pSVCDNav->m_uCurrAudioSID, dwSegmentStartAddress, ulMaxBlocksCnt);
  2469. #endif //D_ENABLE_SVCD_SAMPLE_RATE_DETECTION
  2470. // Update information for Scanning
  2471. g_pSVCDNav->m_aCurrSegment[0]= dwActualItemStart;
  2472. g_pSVCDNav->m_aCurrSegment[1]= (dwPlaybackStartAddress + ulBlocksCnt);
  2473. // When in Reverse-Scan, play from the End
  2474. if ((0 != SHARED_INFO.m_iScanSpeed) && (SHARED_INFO.m_iScanSpeed < 0)) {
  2475. dwPlaybackStartAddress= (dwPlaybackStartAddress + ulBlocksCnt) - 
  2476. (2 * abs(SHARED_INFO.m_iScanSpeed) * SVCD_BLOCKS_PER_SECOND);
  2477. if (uPlayItemNumber < g_pSVCDNav->m_uFirstCDDA_Track)
  2478. ulBlocksCnt= (2 * abs(SHARED_INFO.m_iScanSpeed) * SVCD_BLOCKS_PER_SECOND);
  2479. }
  2480. // Update the Global position variable
  2481. SHARED_INFO.uCurrentTrackNumber= uCurrTrack;
  2482. // Request for notifications of Trigger-Bit occurrence
  2483. if (g_pSVCDNav->m_bIsUsingPSD)
  2484. PE_CD_RequestNotification(TriggerBit);
  2485. //jeanz_0511_2005 Fix stuck problem during boundary scan.
  2486. // Request for notifications of IFrame occurrence
  2487. if ( (eScan == ePBType) ||(eSlowMotion == ePBType) )
  2488. PE_CD_RequestNotification(IFrame);
  2489. // Initiate the Error-Recovery Mechanism for Playback-Hangup, unless the item is a Segment
  2490. // that contains a Still image; in which case there is no criterion for detecting a
  2491. // playback-hangup (even if the Still image is accompanied by Audio).
  2492. #if defined (WATCHDOG_TRIGGERED_BY_FE) && !defined (EXINO2)
  2493. if ( g_pSVCDNav->m_bIsSegment && (NoVideo == g_pSVCDNav->m_iCurrVideoType) ) {
  2494. #else
  2495. if (g_pSVCDNav->m_bIsSegment && (MPEG_2 != g_pSVCDNav->m_iCurrVideoType)) {
  2496. #endif
  2497. (g_pSVCDNav->m_ErrorRecoveryInfo).eRecoveryType= eNoError;
  2498. }
  2499. else {
  2500. (g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout= (SVCD_PB_HANGUP_TIMEOUT * (1 + abs(SHARED_INFO.m_iSlowSpeed)));
  2501. (g_pSVCDNav->m_ErrorRecoveryInfo).eRecoveryType= ePlaybackHangup;
  2502. (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam= dwPlaybackStartAddress;
  2503. (g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter = 0;//LX051302
  2504. }
  2505. // Indicate that a Current-Location Change is about to take place
  2506. g_pSVCDNav->m_bLocationChanging= TRUE;
  2507. g_pSVCDNav->m_dwTargetLocation= dwPlaybackStartAddress;
  2508. // Display/Remove the Background, depending on whether or not the Item is a CDDA Track,
  2509. // and whether or not PBC is On.
  2510. if ((! g_pSVCDNav->m_bIsUsingPSD) && (CDDA_SID == g_pSVCDNav->m_uCurrAudioSID))
  2511. PE_CD_DisplayBackground(TRUE);
  2512. else
  2513. PE_CD_DisplayBackground(FALSE);
  2514. PE_CD_SetCurrentLocationLBN_Bakcup(dwPlaybackStartAddress);
  2515. // Invoke playback
  2516. return PE_CD_PlaySegment(g_pSVCDNav->m_iCurrVideoType, g_pSVCDNav->m_uCurrAudioSID, 
  2517.  dwPlaybackStartAddress, ulBlocksCnt,
  2518.  ePBType, ulPlaybackParam);
  2519. }
  2520. /////////////////////////////////////////////////////////////////////////////////////////////////
  2521. // BOOL InvokePlayback() -
  2522. // Invokes playback of the current List.
  2523. //
  2524. // Input:
  2525. // None
  2526. //
  2527. // Output:
  2528. // TRUE if the playback has been started successfully; FALSE otherwise.
  2529. //
  2530. // Remarks:
  2531. // The function uses the Current-Position in order to retrieve information regarding the
  2532. // next List to play. Once the current List is established, the function calls for
  2533. // playback of the appropriate Play-Item.
  2534. static BOOL InvokePlayback(void)
  2535. {
  2536. int iCurrSlowSpeed = 0;
  2537. // Terminate any pending Rendezvous events
  2538. g_pSVCDNav->m_dwWaitTime= SVCD_INFINITE;
  2539. g_pSVCDNav->m_dwTimeout= SVCD_INFINITE;
  2540. g_pSVCDNav->m_dwPausePeriod= SVCD_INFINITE;
  2541. // Cancel any ongoing playback, while maintaining the current Play-State
  2542. if (PST_STOP != gcs.pstate) {
  2543. PE_CD_AbortPlayback(TRUE); // Maintain Standby mode
  2544. }
  2545. // In the case of not using the PSD, just arrange for playback of the Track whose number is 
  2546. // stored in the Program-List Entry pointed by CurrPosition.uListItem.
  2547. if (! g_pSVCDNav->m_bIsUsingPSD) {
  2548. dbg_printf(("Invoking Playback without PSD.n"));
  2549. if ((PST_SCAN == gcs.pstate) && (0 != SHARED_INFO.m_iScanSpeed)) {
  2550. #ifdef SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2551. // Cancel the on-going Scanning
  2552. OnScan(0);
  2553. gcs.pstate= PST_PLAY;
  2554. #endif //SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2555. }
  2556. else if ((PST_SLOW == gcs.pstate) && (0 != SHARED_INFO.m_iSlowSpeed)) {
  2557. // First of all, cancel the current Slow-Motion
  2558. iCurrSlowSpeed= SHARED_INFO.m_iSlowSpeed;
  2559. OnSlow(0); // Cancel the ongoing Slow-Motion
  2560. gcs.pstate= PST_PLAY;
  2561. }
  2562. else if (PST_PAUSE == gcs.pstate) {
  2563. #ifdef SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2564. // Move to Play state
  2565. gcs.pstate= PST_PLAY;
  2566. #endif //SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2567. }
  2568. else {
  2569. // Move to Play state
  2570. gcs.pstate= PST_PLAY;
  2571. }
  2572. if (! PlayItem(PM_GetProgramListEntry((SHARED_INFO.m_CurrPosition).uListItem),
  2573.    (SHARED_INFO.m_CurrPosition).dwStartAddress)) 
  2574. {
  2575. dbg_printf(("Failed to play the required Track.n"));
  2576. gcs.pstate= PST_STOP;
  2577. return FALSE;
  2578. }
  2579. #ifndef SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2580. // Renew Slow-Motion
  2581. if (0 != iCurrSlowSpeed)
  2582. OnSlow(iCurrSlowSpeed);
  2583. #endif //SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2584. #ifndef SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2585. //waiting till the first frame of the next track is displayed
  2586. if (CDDA_SID != g_pSVCDNav->m_uCurrAudioSID)
  2587. {
  2588. int iRetryCount= 20;
  2589. while (!PE_CD_VideoIsActive() && iRetryCount)
  2590. {
  2591. usleep((DWORD)TIME_TILL_VIDEO_ACTIVE);
  2592. iRetryCount--;
  2593. }
  2594. }
  2595. // Renew Pause
  2596. if (PST_PAUSE == gcs.pstate)
  2597. OnStop(ePause);
  2598. #endif //SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2599. (SHARED_INFO.m_CurrPosition).dwStartAddress= -1;
  2600. //in case we are playing audio the step and slow options are prohibited
  2601. if (CDDA_SID == g_pSVCDNav->m_uCurrAudioSID)
  2602. {
  2603. SET_COP_MASK(COP_STOP | COP_PAUSE | COP_SCAN | COP_SCAN_BACKWARD | 
  2604.  COP_NEXT_CHAPTER | COP_PREVIOUS_CHAPTER);
  2605. CLEAR_COP_MASK(COP_SLOW | COP_STEP);
  2606. }
  2607. else
  2608. {
  2609. SET_COP_MASK(COP_STOP | COP_PAUSE | COP_SLOW | COP_SCAN | COP_SCAN_BACKWARD | 
  2610.  COP_STEP | COP_NEXT_CHAPTER | COP_PREVIOUS_CHAPTER);
  2611.      //If current track is the last one,clear next cop mask
  2612. if ((SHARED_INFO.m_CurrPosition).uListItem == (PM_GetProgramSize() - 1))
  2613.      CLEAR_COP_MASK(COP_NEXT_CHAPTER);
  2614. }
  2615. return TRUE;
  2616. }
  2617. // The PSD information is being used:
  2618. // Check if there's need to determine the type of the List
  2619. if (Undetermined == (SHARED_INFO.m_CurrPosition).ListType) {
  2620. BYTE aBuffer[SVCD_SELECTIONLIST_HDR_SIZE];
  2621. if (! _getPSDRecord((SHARED_INFO.m_CurrPosition).dwPSD_Offset, SVCD_SELECTIONLIST_HDR_SIZE, aBuffer)) {
  2622. dbg_printf(("Failed to parse a PSD List.n"));
  2623. return FALSE;
  2624. }
  2625. switch (aBuffer[0]) 
  2626. {
  2627. case 0x10: // This is a PlayList
  2628. dbg_printf(("Parsing a PlayListn"));
  2629. (SHARED_INFO.m_CurrPosition).ListType= PlayList;
  2630. ((SHARED_INFO.m_CurrList).PlayList).uItemsCnt= (WORD)aBuffer[1];
  2631. ((SHARED_INFO.m_CurrList).PlayList).uPrevOffset= ((aBuffer[4] << 8) | aBuffer[5]);
  2632. ((SHARED_INFO.m_CurrList).PlayList).uNextOffset= ((aBuffer[6] << 8) | aBuffer[7]);
  2633. ((SHARED_INFO.m_CurrList).PlayList).uReturnOffset= ((aBuffer[8] << 8) | aBuffer[9]);
  2634. ((SHARED_INFO.m_CurrList).PlayList).uPlayingTime= ((aBuffer[10] << 8) | aBuffer[11]);
  2635. ((SHARED_INFO.m_CurrList).PlayList).wWaitTime= aBuffer[12];
  2636. ((SHARED_INFO.m_CurrList).PlayList).wAutoPausePeriod= aBuffer[13];
  2637. break;
  2638. case 0x18: // This is a SelectionList
  2639. dbg_printf(("Parsing a SelectionListn"));
  2640. (SHARED_INFO.m_CurrPosition).ListType= SelectionList;
  2641. ((SHARED_INFO.m_CurrList).SelectionList).uSelectionsCnt= (WORD)aBuffer[2];
  2642. ((SHARED_INFO.m_CurrList).SelectionList).uSelectionBase= (WORD)aBuffer[3];
  2643. ((SHARED_INFO.m_CurrList).SelectionList).uPrevOffset= ((aBuffer[6] << 8) | aBuffer[7]);
  2644. ((SHARED_INFO.m_CurrList).SelectionList).uNextOffset= ((aBuffer[8] << 8) | aBuffer[9]);
  2645. ((SHARED_INFO.m_CurrList).SelectionList).uReturnOffset= ((aBuffer[10] << 8) | aBuffer[11]);
  2646. ((SHARED_INFO.m_CurrList).SelectionList).uDefaultOffset= ((aBuffer[12] << 8) | aBuffer[13]);
  2647. ((SHARED_INFO.m_CurrList).SelectionList).uTimeoutOffset= ((aBuffer[14] << 8) | aBuffer[15]);
  2648. ((SHARED_INFO.m_CurrList).SelectionList).wTimeoutWaitTime= aBuffer[16];
  2649. ((SHARED_INFO.m_CurrList).SelectionList).uRepeatCnt= (WORD)(aBuffer[17] & 0x7F);
  2650. ((SHARED_INFO.m_CurrList).SelectionList).bPostponeEventsDuringPlay= (aBuffer[17] & 0x80) ? TRUE : FALSE;
  2651. ((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber= ((aBuffer[18] << 8) | aBuffer[19]);
  2652. break;
  2653. case 0x1F: // This is an EndList
  2654. dbg_printf(("Parsing an EndListn"));
  2655. (SHARED_INFO.m_CurrPosition).ListType= EndList;
  2656. break;
  2657. // <<< SEC CH.KO041204: for illegal VCD
  2658. #ifdef EXINO2
  2659. default:
  2660. (SHARED_INFO.m_CurrPosition).ListType= Undetermined;
  2661. PM_SetPBC(FALSE);
  2662. OnModeChange();
  2663. g_ui_misc_flags.m_bIllegalVCD = TRUE;
  2664. break;
  2665. #endif 
  2666. // SEC CH.KO041204 >>>
  2667. }
  2668. } // endof if
  2669. // Invoke the Playback using the information in the current PSD List:
  2670. switch ((SHARED_INFO.m_CurrPosition).ListType) 
  2671. {
  2672. case PlayList:
  2673. {
  2674. BYTE aBuffer[2];
  2675. DWORD dwPSD_Offset= ((SHARED_INFO.m_CurrPosition).dwPSD_Offset + SVCD_PLAYLIST_HDR_SIZE 
  2676. + (2 * ((SHARED_INFO.m_CurrPosition).uListItem - 1)));
  2677. if (! _getPSDRecord(dwPSD_Offset, 2, aBuffer)) {
  2678. dbg_printf(("Failed to retrieve PSD information.n"));
  2679. return FALSE;
  2680. }
  2681. if ((PST_SCAN == gcs.pstate) && (0 != SHARED_INFO.m_iScanSpeed)) {
  2682. #ifdef SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2683. // Cancel the on-going Scanning
  2684. OnScan(0);
  2685. gcs.pstate= PST_PLAY;
  2686. #endif //SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2687. }
  2688. else if ((PST_SLOW == gcs.pstate) && (0 != SHARED_INFO.m_iSlowSpeed)) {
  2689. #ifdef SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2690. // Cancel the on-going Slow-Motion
  2691. OnSlow(0);
  2692. gcs.pstate= PST_PLAY;
  2693. #endif //SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2694. }
  2695. else {
  2696. // Move to Play state
  2697. gcs.pstate= PST_PLAY;
  2698. }
  2699. // Update the Previous, Next, and Return Core-Operations according to the appropriate Offsets
  2700. #ifdef SVCD_FORCE_PERVIOUS_ITEM
  2701. #ifndef SKIP_TO_THE_BEGINING//angieh_0324_2004:For Alco,support previous func when play the first track.
  2702. if ((0xFFFF == ((SHARED_INFO.m_CurrList).PlayList).uPrevOffset) &&
  2703. (1 == (SHARED_INFO.m_CurrPosition).uListItem))
  2704. CLEAR_COP_MASK(COP_PREVIOUS_CHAPTER);
  2705.          else
  2706. #endif
  2707. #else
  2708. if (0xFFFF == ((SHARED_INFO.m_CurrList).PlayList).uPrevOffset)
  2709. CLEAR_COP_MASK(COP_PREVIOUS_CHAPTER);
  2710.          else
  2711. #endif
  2712. SET_COP_MASK(COP_PREVIOUS_CHAPTER);
  2713. if (0xFFFF == ((SHARED_INFO.m_CurrList).PlayList).uNextOffset)
  2714. CLEAR_COP_MASK(COP_NEXT_CHAPTER);
  2715. else
  2716. SET_COP_MASK(COP_NEXT_CHAPTER);
  2717. if (0xFFFF == ((SHARED_INFO.m_CurrList).PlayList).uReturnOffset)
  2718. CLEAR_COP_MASK(COP_RETURN);
  2719. else
  2720. SET_COP_MASK(COP_RETURN);
  2721. if (! PlayItem(((aBuffer[0] << 8) | aBuffer[1]), (SHARED_INFO.m_CurrPosition).dwStartAddress)) {
  2722. dbg_printf(("Failed to invoke playback of Play-Item Number %02x.n", ((aBuffer[0] << 8) | aBuffer[1])));
  2723. gcs.pstate= PST_STOP;
  2724. }
  2725. (SHARED_INFO.m_CurrPosition).dwStartAddress= -1;
  2726. if ( (SHARED_INFO.m_CurrPosition).dwStartAddress <= 0 )
  2727. ((SHARED_INFO.m_CurrList).SelectionList).bPostponeEventsDuringPlay = FALSE;
  2728. if (((SHARED_INFO.m_CurrList).PlayList).uItemsCnt == 0x0) //ML 061903 nothing being palyed so jump to next list
  2729. ie_send_ex(IE_CORE_CDNAV_RENDEZVOUS, (void *)eWaitTimeExpired);
  2730. }
  2731. break;
  2732. case SelectionList:
  2733. // If Scanning is in progress, eliminate it
  2734. if (PST_SCAN == gcs.pstate)
  2735. OnScan(0);
  2736. else if (PST_SLOW == gcs.pstate)
  2737. OnSlow(0);
  2738. gcs.pstate= PST_PLAY;
  2739. // Update the Previous, Next, Return, and Play Core-Operations according to the appropriate Offsets
  2740. #ifndef SKIP_TO_THE_BEGINING//angieh_0324_2004:For Alco,support previous func when play the first track.
  2741. if (0xFFFF == ((SHARED_INFO.m_CurrList).SelectionList).uPrevOffset)
  2742. CLEAR_COP_MASK(COP_PREVIOUS_CHAPTER);
  2743. else
  2744. #endif
  2745. SET_COP_MASK(COP_PREVIOUS_CHAPTER);
  2746. if (0xFFFF == ((SHARED_INFO.m_CurrList).SelectionList).uNextOffset)
  2747. CLEAR_COP_MASK(COP_NEXT_CHAPTER);
  2748. else
  2749. SET_COP_MASK(COP_NEXT_CHAPTER);
  2750. if (0xFFFF == ((SHARED_INFO.m_CurrList).SelectionList).uReturnOffset)
  2751. CLEAR_COP_MASK(COP_RETURN);
  2752. else
  2753. SET_COP_MASK(COP_RETURN);
  2754. if (0xFFFF == ((SHARED_INFO.m_CurrList).SelectionList).uDefaultOffset)
  2755. CLEAR_COP_MASK(COP_PLAY);
  2756. else
  2757. SET_COP_MASK(COP_PLAY);
  2758. if (! PlayItem(((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber, (SHARED_INFO.m_CurrPosition).dwStartAddress)) {
  2759. dbg_printf(("Failed to invoke playback of Play-Item Number %02x.n", ((SHARED_INFO.m_CurrList).SelectionList).uPlayItemNumber));
  2760. return FALSE;
  2761. }
  2762. (SHARED_INFO.m_CurrPosition).dwStartAddress= -1;
  2763. // Mark that a single iteration has been executed
  2764. ((SHARED_INFO.m_CurrList).SelectionList).uRepeatCnt--;
  2765. break;
  2766. case EndList:
  2767. // Perform Full-Stop (End of Playback)
  2768. OnStop(eFullStop);
  2769. return TRUE;
  2770. // <<< SEC shKang041804 : some specific disc has a illegal List type. must work like VCD 1.0
  2771. #ifdef EXINO2
  2772. case Undetermined:
  2773. {
  2774. dbg_printf(("Invoking Playback without PSD.n"));
  2775. if ((PST_SCAN == gcs.pstate) && (0 != SHARED_INFO.m_iScanSpeed)) {
  2776. #ifdef SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2777. // Cancel the on-going Scanning
  2778. OnScan(0);
  2779. gcs.pstate= PST_PLAY;
  2780. #endif //SVCD_PROHIBIT_SCAN_ACROSS_ITEM_BOUNDARIES
  2781. }
  2782. else if ((PST_SLOW == gcs.pstate) && (0 != SHARED_INFO.m_iSlowSpeed)) {
  2783. // First of all, cancel the current Slow-Motion
  2784. iCurrSlowSpeed= SHARED_INFO.m_iSlowSpeed;
  2785. OnSlow(0); // Cancel the ongoing Slow-Motion
  2786. gcs.pstate= PST_PLAY;
  2787. }
  2788. else if (PST_PAUSE == gcs.pstate) {
  2789. #ifdef SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2790. // Move to Play state
  2791. gcs.pstate= PST_PLAY;
  2792. #endif //SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2793. }
  2794. else {
  2795. // Move to Play state
  2796. gcs.pstate= PST_PLAY;
  2797. }
  2798. if (! PlayItem(PM_GetProgramListEntry((SHARED_INFO.m_CurrPosition).uListItem),
  2799.    (SHARED_INFO.m_CurrPosition).dwStartAddress)) 
  2800. {
  2801. dbg_printf(("Failed to play the required Track.n"));
  2802. gcs.pstate= PST_STOP;
  2803. return FALSE;
  2804. }
  2805. #ifndef SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2806. // Renew Slow-Motion
  2807. if (0 != iCurrSlowSpeed)
  2808. OnSlow(iCurrSlowSpeed);
  2809. #endif //SVCD_PROHIBIT_SLOW_ACROSS_ITEM_BOUNDARIES
  2810. #ifndef SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2811. //waiting till the first frame of the next track is displayed
  2812. if (CDDA_SID != g_pSVCDNav->m_uCurrAudioSID)
  2813. {
  2814. int iRetryCount= 20;
  2815. while (!PE_CD_VideoIsActive() && iRetryCount)
  2816. {
  2817. usleep((DWORD)TIME_TILL_VIDEO_ACTIVE);
  2818. iRetryCount--;
  2819. }
  2820. }
  2821. // Renew Pause
  2822. if (PST_PAUSE == gcs.pstate)
  2823. OnStop(ePause);
  2824. #endif //SVCD_PROHIBIT_PAUSE_ACROSS_ITEM_BOUNDARIES
  2825. (SHARED_INFO.m_CurrPosition).dwStartAddress= -1;
  2826. //in case we are playing audio the step and slow options are prohibited
  2827. if (CDDA_SID == g_pSVCDNav->m_uCurrAudioSID)
  2828. {
  2829. SET_COP_MASK(COP_STOP | COP_PAUSE | COP_SCAN | COP_SCAN_BACKWARD | 
  2830.  COP_NEXT_CHAPTER | COP_PREVIOUS_CHAPTER);
  2831. CLEAR_COP_MASK(COP_SLOW | COP_STEP);
  2832. }
  2833. else
  2834. {
  2835. SET_COP_MASK(COP_STOP | COP_PAUSE | COP_SLOW | COP_SCAN | COP_SCAN_BACKWARD | 
  2836.  COP_STEP | COP_NEXT_CHAPTER | COP_PREVIOUS_CHAPTER);
  2837.      //If current track is the last one,clear next cop mask
  2838. if ((SHARED_INFO.m_CurrPosition).uListItem == (PM_GetProgramSize() - 1))
  2839.      CLEAR_COP_MASK(COP_NEXT_CHAPTER);
  2840. }
  2841. return TRUE;
  2842. }
  2843. #endif // EXINO2
  2844. // SEC shKang041804 >>>
  2845. }
  2846. return TRUE;
  2847. }
  2848. /////////////////////////////////////////////////////////////////////////////////////////////////
  2849. // void CalculateRecoveryAddress() -
  2850. // Calculates a destination address for attempting Error-Recovery.
  2851. //
  2852. // Input:
  2853. // dwErrorAddress - Holds the LBN where the Error occurred.
  2854. //
  2855. // Output:
  2856. // None.
  2857. //
  2858. // Remarks:
  2859. // If the Error Address is met for the first time, Recovery will be attempted from the
  2860. // exact same place.
  2861. // For successive occurrences of the Error, a Linear offset is used to advance through
  2862. // the Segment.
  2863. // Note: This function is only meant to be used in conjunction with a forward playback.
  2864. //   Since Reverse-Playback is unsupported, and Reverse-Scan is handled by a different
  2865. //   Error-Recovery mechanism, this poses no limitation over Error-Recovery.
  2866. #define LINEAR_ERROR_RECOVERY_OFFSET 10
  2867. static DWORD CalculateRecoveryAddress(DWORD dwErrorAddress)
  2868. {
  2869. #ifndef WATCHDOG_TRIGGERED_BY_FE
  2870. static DWORD dwLastError= 0;
  2871. static UINT8 uOccurrences= 0;
  2872. // Check if this is the first time that we've seen this Address
  2873. if (dwErrorAddress != dwLastError) {
  2874. uOccurrences= 0; // Restart the mechanism for this Address
  2875. dwLastError= dwErrorAddress;
  2876. }
  2877. // Begin Calculation of the Recovery Address
  2878. if (1 == ++uOccurrences) {
  2879. // At the first attempt, always try to replay the original segment
  2880. return dwErrorAddress;
  2881. }
  2882. // Use a fixed linear offset for Recovery
  2883. return (dwErrorAddress + LINEAR_ERROR_RECOVERY_OFFSET + (75 * uOccurrences));
  2884. #else
  2885. //<<<LX051302: New error recovery
  2886. if ( (g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter < SVCD_ERROR_RETRY_NUM )
  2887. return( dwErrorAddress +
  2888. g_miSVCDNSPBErrorJumpTbl[(g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter]*NUM_OF_SECTORS_PER_SECOND);
  2889. else
  2890. return ( dwErrorAddress + (DWORD)( 4*NUM_OF_SECTORS_PER_SECOND*((g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter+1) ) );
  2891. #endif//WATCHDOG_TRIGGERED_BY_FE
  2892. //LX051302>>>
  2893. }
  2894. /////////////////////////////////////////////////////////////////////////////////////////////////
  2895. // void PerformErrorRecovery() -
  2896. // Performs Error-Recovery, if needed.
  2897. //
  2898. // Input:
  2899. // None.
  2900. //
  2901. // Output:
  2902. // None.
  2903. //
  2904. // Remarks:
  2905. // The function uses the Error-Recovery Information in order to determine which kind of
  2906. // Error-Recovery mechanism to engage, if any.
  2907. // This function is expected to be called periodically in order to detecet an Error situation.
  2908. // The Error-Recovery Mechanism is selected by the Navigator according to the appropriate
  2909. // situation.
  2910. // In response, this function will attempt to return the system to natural flow, if possible.
  2911. static void PerformErrorRecovery(void)
  2912. {
  2913. DWORD dwCurrentLocation;
  2914. dwCurrentLocation= PE_CD_GetCurrentLocation();
  2915. // Check if there's need to activate Error-Recovery, by checking if the Timeout has expired.
  2916. if (((g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout <= 0) ||
  2917. (0 != --(g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout))
  2918. return; 
  2919. switch ((g_pSVCDNav->m_ErrorRecoveryInfo).eRecoveryType)
  2920. {
  2921. case eNoError:
  2922. //<<<mikex_0827_2003_a: add the recovery error mechanism in digest mode
  2923. #ifdef SVCD_DIGEST_SUPPORT
  2924. if(gcs.pstate == PST_STILL && g_pSVCDNav->m_bDigestMode != FALSE)
  2925. g_DigestReadDiscError++;
  2926. #endif
  2927. //mikex_0827_2003_a>>>
  2928. break;
  2929. case eIFrameDisplayMiss:
  2930. // Take care of I-Frame Display Miss
  2931. dbg_printf(("I-Frame Display Missed -- Recovering...n"));
  2932. ie_send(IE_CORE_I_FRAME); // Emulate the display of an I-Frame
  2933. break;
  2934. case ePlaybackHangup:
  2935. #ifndef WATCHDOG_TRIGGERED_BY_FE
  2936. // Take care of Playback-Hangup
  2937. if ((PST_PLAY == gcs.pstate) || (PST_SLOW == gcs.pstate)) {
  2938. if (dwCurrentLocation <= (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam) {
  2939. DWORD dwRecoveryAddress= CalculateRecoveryAddress((g_pSVCDNav->m_ErrorRecoveryInfo).dwParam);
  2940. tr_printf(("Possible Playback-Hangup -- Recovering...n"));
  2941. // Abort the current Playback, without changing the Decoder's mode
  2942. PE_CD_AbortPlayback(TRUE);
  2943. // Attempt recovery
  2944. if (dwRecoveryAddress < g_pSVCDNav->m_aCurrSegment[1]) {
  2945. // The Recovery Address is within the legal range: try to recover
  2946. (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam= dwRecoveryAddress;
  2947. PE_CD_SetCurrentLocationLBN_Bakcup(dwRecoveryAddress);
  2948. PE_CD_PlaySegment(g_pSVCDNav->m_iCurrVideoType, g_pSVCDNav->m_uCurrAudioSID,
  2949.   dwRecoveryAddress, (g_pSVCDNav->m_aCurrSegment[1] - dwRecoveryAddress),
  2950.   eNormalSpeed, 0);
  2951. // Renew Slow-Motion, if necessary
  2952. if (PST_SLOW == gcs.pstate)
  2953. OnSlow(SHARED_INFO.m_iSlowSpeed);
  2954. }
  2955. else {
  2956. // The Recovery-Address breaches the legal range: emulate a Playback-Finished
  2957. // Event, so that navigation can carry on as if no error occurred.
  2958. //CL, clear it, for we also send this message in tick
  2959. //ie_send(IE_CORE_CDNAV_FINISHED);
  2960. }
  2961. }
  2962. else {
  2963. // So far so good - there's progress. Register the Current Loaction.
  2964. (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam= dwCurrentLocation;
  2965. }
  2966. // Setup the Timeout parameter for the next time, according to the Playback mode
  2967. (g_pSVCDNav->m_ErrorRecoveryInfo).uTimeout= (SVCD_PB_HANGUP_TIMEOUT * (1 + abs(SHARED_INFO.m_iSlowSpeed)));
  2968. }
  2969. #else
  2970. //<<<LX051302: New Error Recovery process
  2971. // Take care of Playback-Hangup
  2972. if ((PST_PLAY == gcs.pstate) || (PST_SLOW == gcs.pstate)) {
  2973. DWORD dwRecoveryAddress= CalculateRecoveryAddress((g_pSVCDNav->m_ErrorRecoveryInfo).dwParam);
  2974. dbg_printf(("Watchdog startedn"));
  2975. //LX051302: Current segment playback finished if retry times is more than MAX_WATCHDOG_RETRY_TIMES
  2976. if (  (g_pSVCDNav->m_ErrorRecoveryInfo).ucRetryCounter++ > MAX_WATCHDOG_RETRY_TIMES ){
  2977. dbg_printf(("Too many retrys, skip to next playitemn"));
  2978. ie_send(IE_CORE_CDNAV_FINISHED);
  2979. }
  2980. // Abort the current Playback, without changing the Decoder's mode
  2981. PE_CD_AbortPlayback(TRUE);
  2982. // Attempt recovery
  2983. if (dwRecoveryAddress < g_pSVCDNav->m_aCurrSegment[1]) {
  2984. // The Recovery Address is within the legal range: try to recover
  2985. (g_pSVCDNav->m_ErrorRecoveryInfo).dwParam= dwRecoveryAddress;
  2986. PE_CD_SetCurrentLocationLBN_Bakcup(dwRecoveryAddress);
  2987. PE_CD_PlaySegment(g_pSVCDNav->m_iCurrVideoType, g_pSVCDNav->m_uCurrAudioSID,
  2988.   dwRecoveryAddress, (g_pSVCDNav->m_aCurrSegment[1] - dwRecoveryAddress),
  2989.   eNormalSpeed, 0);
  2990. // Renew Slow-Motion, if necessary
  2991. if (PST_SLOW == gcs.pstate)
  2992. OnSlow(SHARED_INFO.m_iSlowSpeed);
  2993. if (g_pSVCDNav->m_bIsSegment && (MPEG_2 != g_pSVCDNav->m_iCurrVideoType)) 
  2994. {
  2995. PE_CD_RequestNotification(IFrame);
  2996. PE_CD_RequestNotification(StuckTrigger);
  2997. }
  2998. }
  2999. else {
  3000. // The Recovery-Address breaches the legal range: emulate a Playback-Finished
  3001. // Event, so that navigation can carry on as if no error occurred.
  3002. //CL, clear it, for we also send this message in tick
  3003. tr_printf(("Watch dog started, end of current segment, skip to next playitemn"));
  3004. ie_send(IE_CORE_CDNAV_FINISHED);
  3005. }
  3006. }
  3007. #endif//WATCHDOG_TRIGGERED_BY_FE
  3008. //LX051302>>>
  3009. break;
  3010. default:
  3011. dbg_printf(("Unknown Error-Recovery Mechanism Type: %xn", (g_pSVCDNav->m_ErrorRecoveryInfo).eRecoveryType));
  3012. break;
  3013. }
  3014. return;
  3015. }
  3016. /////////////////////////////////////////////////////////////////////////////////////////////////
  3017. // void CancelRepeatModes(BYTE ucModesMask) -
  3018. // Cancels one or more Repeat-Modes.
  3019. //
  3020. // Input:
  3021. // ucModesMask - A bit-mask indicating which Repeat Mode(s) needs to be cancelled
  3022. //
  3023. // Output:
  3024. // None. The requested Repeat-Modes are eliminated, if they were active.
  3025. static void CancelRepeatModes(BYTE ucModesMask)
  3026. {
  3027. BOOL bRepeatModeChanged= FALSE;
  3028. // Cancel "Repeat Single" if it is in effect
  3029. if ((ucModesMask & PM_REPEAT_SINGLE) && PM_IsRepeatSingle()) {
  3030. PM_SetRepeatSingle(FALSE);
  3031. bRepeatModeChanged= TRUE;
  3032. }
  3033. // Cancel "Repeat All" if it is in effect
  3034. if ((ucModesMask & PM_REPEAT_ALL) && PM_IsRepeatAll()) {
  3035. PM_SetRepeatAll(FALSE);
  3036. bRepeatModeChanged= TRUE;
  3037. }
  3038. // Cancel "Repeat A-B" if it is in effect
  3039. if ((ucModesMask & PM_REPEAT_AB_MASK) && (0 != PM_GetRepeatAB())) {
  3040. PM_SetRepeatAB(0);
  3041. OnCancelABRepeat();
  3042. bRepeatModeChanged= TRUE;
  3043. }
  3044. if (bRepeatModeChanged)
  3045. ie_send(IE_UI_STATE_CHANGE);
  3046. return;
  3047. }
  3048. /////////////////////////////////////////////////////////////////////////////////////////////////
  3049. // void OnTimeout() -
  3050. // Handels a Timeout Event, identified by the OnTick() service.
  3051. //
  3052. // Input:
  3053. // None
  3054. //
  3055. // Output:
  3056. // The next suitable List is selected for playback and invoked.
  3057. //
  3058. // Remarks:
  3059. // A Timeout Event occurrs when a Play-Item finishes playback, and a Timeout period
  3060. // has been defined for it. As long as there is no user-intervention, the Timeout counter 
  3061. // starts measuring the Timeout-period. When this period expires, this handler is called.
  3062. //
  3063. // The handler will examine the current List to establish the Timeout-List Offset.
  3064. // This offset is used as the next List to play. If no such offset has been defined,
  3065. // the current List is repeated.
  3066. static void OnTimeout(void)
  3067. {
  3068. dbg_printf(("OnTimeout()n"));
  3069. g_pSVCDNav->m_dwTimeout= SVCD_INFINITE;
  3070. // Reset the current Position
  3071. (SHARED_INFO.m_CurrPosition).ListType= Undetermined;
  3072. (SHARED_INFO.m_CurrPosition).uListItem= 1; // Start playback from the first Item
  3073. // The Timeout Event is relevant only for Selection-Lists, therefore the current List
  3074. // must be of type SelectionList. Examine the TimeoutOffset Field to find out which 
  3075. // List needs to be played next. If there is no valid Timeout-Offset, select the first
  3076. // suitable SelectionList Item.
  3077. if (0xFFFF != ((SHARED_INFO.m_CurrList).SelectionList).uTimeoutOffset) {
  3078. dbg_printf(("The Timeout-List is at offset: %04xn", ((SHARED_INFO.m_CurrList).SelectionList).uTimeoutOffset));
  3079. (SHARED_INFO.m_CurrPosition).dwPSD_Offset= (g_pSVCDNav->m_NavigationInfo).uOffsetMultiplier * 
  3080.     (UINT32)((SHARED_INFO.m_CurrList).SelectionList).uTimeoutOffset;
  3081. }
  3082. else {
  3083. WORD uDefaultOffset= FindDefaultSelectionOffset(-1);
  3084. dbg_printf(("No Timeout-List was defined.n"));
  3085. if ((WORD)-1 == uDefaultOffset) {
  3086. gcs.pstate= PST_STILL;
  3087. return;
  3088. }
  3089. (SHARED_INFO.m_CurrPosition).dwPSD_Offset= (g_pSVCDNav->m_NavigationInfo).uOffsetMultiplier * 
  3090.     (UINT32)uDefaultOffset;
  3091. }
  3092. // Cancel any current Repeat-Modes
  3093. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  3094. // Now actually invoke playback of the List
  3095. gcs.pstate= PST_PLAY;
  3096. if (! InvokePlayback()) {
  3097. dbg_printf(("Failed to play-back the current List.n"));
  3098. gcs.pstate= PST_STOP;
  3099. }
  3100. return;
  3101. }
  3102. /////////////////////////////////////////////////////////////////////////////////////////////////
  3103. // void OnWaitTimeExpired() -
  3104. // Handels a Wait-Expired Event, identified by the OnTick() service.
  3105. //
  3106. // Input:
  3107. // None
  3108. //
  3109. // Output:
  3110. // The next suitable List is selected for playback and invoked.
  3111. //
  3112. // Remarks:
  3113. // A Wait-Expired Event occurs when a Play-Item within a Play-List finishes playback, and
  3114. // a Waiting-Time is defined for that Play-List.
  3115. // If the entire Play-List has been exhausted, then the next List is selected for playback.
  3116. // Otherwise, the next Item on the Play-List is selected for playback.
  3117. static void OnWaitTimeExpired(void)
  3118. {
  3119. dbg_printf(("OnWaitTimeExpired()n"));
  3120. g_pSVCDNav->m_dwWaitTime= SVCD_INFINITE;
  3121. // The WaitTimeExpired Event is relevant only for Play-Lists, therefore the current List
  3122. // must be of type PlayList. Continue to play the next Play-Item on the List, or continue 
  3123. // to the next List if the last Item has been played.
  3124. if (((SHARED_INFO.m_CurrList).PlayList).uItemsCnt <= (SHARED_INFO.m_CurrPosition).uListItem++) 
  3125. {
  3126. dbg_printf(("PlayList playback is done. Switching to the next list.n"));
  3127. if (0xFFFF == ((SHARED_INFO.m_CurrList).PlayList).uNextOffset) {
  3128. dbg_printf(("Invalid Next List Offset for a Play-List. Ignored.n"));
  3129. //Emulating an EndList to overcome authoring errors.
  3130. (SHARED_INFO.m_CurrPosition).ListType= EndList;
  3131. //return;
  3132. }
  3133. else
  3134. {
  3135. (SHARED_INFO.m_CurrPosition).ListType= Undetermined;
  3136. (SHARED_INFO.m_CurrPosition).dwPSD_Offset= (g_pSVCDNav->m_NavigationInfo).uOffsetMultiplier * 
  3137. (UINT32)((SHARED_INFO.m_CurrList).PlayList).uNextOffset;
  3138. (SHARED_INFO.m_CurrPosition).uListItem= 1; // Start playback from the first Item
  3139. }
  3140. // Cancel any current Repeat-Modes
  3141. CancelRepeatModes(PM_REPEAT_SINGLE | PM_REPEAT_ALL | PM_REPEAT_AB_MASK);
  3142. }
  3143. // Continue playback of the current PlayList or the next SelectionList
  3144. gcs.pstate= PST_PLAY;
  3145. if (! InvokePlayback()) {
  3146. dbg_printf(("Failed to invoke the next Play-Item.n"));
  3147. gcs.pstate= PST_STOP;
  3148. }
  3149. return;
  3150. }
  3151. /////////////////////////////////////////////////////////////////////////////////////////////////
  3152. // void OnPausePeriodExpired() -
  3153. // Handels a Pause-Expired Event, identified by the OnTick() service;
  3154. // or a Resume-Playback Event.
  3155. //
  3156. // Input:
  3157. // None
  3158. //
  3159. // Output:
  3160. // Normal playback is resumed.
  3161. //
  3162. // Remarks:
  3163. // A Pause-Expired event occurrs when a stream uses the Trigger-Bit to trigger an
  3164. // automatic-pause. When this happens, the playback pauses for the amount of time
  3165. // defined and measured by the Auto-Pause-Period. When that period expires, this handler is
  3166. // called.
  3167. // This handler also gets called in response to a Resume-Playback event (to resume playback
  3168. // that was previously paused by the user).
  3169. static void OnPausePeriodExpired(void)
  3170. {
  3171. dbg_printf(("OnPausePeriodExpired()n"));
  3172. g_pSVCDNav->m_dwPausePeriod= SVCD_INFINITE;
  3173. PE_CD_PausePlayback(FALSE, g_pSVCDNav->m_uCurrAudioSID);
  3174. gcs.pstate= PST_PLAY;
  3175. // Re-install the notification request for Trigger-Bit occurrence, only
  3176. // if the PSD information is being used (otherwise, nothing to do with 
  3177. // the Trigger-Bit).
  3178. if (g_pSVCDNav->m_bIsUsingPSD)
  3179. PE_CD_RequestNotification(TriggerBit);
  3180. return;
  3181. }
  3182. /////////////////////////////////////////////////////////////////////////////////////////////////
  3183. // void OnTick() -
  3184. // Handles an IE_CORE_TICK200 Event.
  3185. //
  3186. // Input:
  3187. // None
  3188. //
  3189. // Output:
  3190. // Various internal timers are managed.
  3191. //
  3192. // Remarks:
  3193. // The handler manages the different internal-timers, associated with temporal events
  3194. // (Auto-Pause-Period, Waiting-Period, Timeout-Period).
  3195. // In addition, the handler checks the Current-Location against the PositionB marker,
  3196. // provided that REPEAT_AB is active. If a match is found, an appropriate Rendezvous
  3197. // event is issued.
  3198. //
  3199. // In addition, when any of the different internal-timers expires, the handler will issue
  3200. // an appropriate Rendezvous event.
  3201. //
  3202. // Apart from the Navigational-events related to timing, this handler also manages the 
  3203. // Error-Recovery mechanisms.
  3204. static void OnTick(void)
  3205. {
  3206. int  j;
  3207. int   iElapsedTime= SHARED_INFO.iCurrentTime;
  3208. DWORD dwCurrentLocation;
  3209. static int iRetryCount = SVCD_PTS_MONOTONITY_GRACE_RETRIES;
  3210. // Gard for Zero Divided
  3211. if (PST_STOP == gcs.pstate) {
  3212. return;
  3213. }
  3214. dwCurrentLocation = PE_CD_GetCurrentLocation();
  3215. //Leon.He_1003_05: Fix the bug can't play in VCD 2.0 selection list. It is not correct to just prevent PLAY EVENT when the state is PST_PLAY.
  3216. /* if (PST_PLAY == gcs.pstate)
  3217. if ((SHARED_INFO.uCurrentTrackNumber >1) && (SHARED_INFO.uCurrentTrackNumber <100))
  3218. CLEAR_COP_MASK(COP_PLAY);
  3219. else
  3220. SET_COP_MASK(COP_PLAY);*/
  3221. // Calculate the Elapsed Time
  3222. if ((g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS
  3223. #ifdef D_ENABLE_ELAPSEDTIME_FOR_SLIDESHOW
  3224. && !((g_pSVCDNav->m_iCurrVideoType == STILL_HIRES)||(g_pSVCDNav->m_iCurrVideoType == STILL_LOWRES))
  3225. #endif
  3226. ) {
  3227. DWORD dwCurrPTS;
  3228. // Attempt to calculate the Elapsed-Time based on the current PTS:
  3229. // Acquire the Current-PTS
  3230. if (PE_CD_GetDecoderCurrentLocationSCR(&dwCurrPTS)) 
  3231. {
  3232. //<<<ML0704 added
  3233. //for using pts to measure,also need to update current entry number
  3234. #ifdef PARSE_ENTRY_INFO
  3235. if ( ( NULL != g_hEntriesTable ) && ( 0 != g_pSVCDNav->m_wEntriesUsedCnt ) 
  3236. && ( PST_STOP != gcs.pstate ) && ( SHARED_INFO.uCurrentTrackNumber > 1 ) )
  3237. {
  3238. WORD i;
  3239. BYTE aucBuffer[4];
  3240. DWORD dwEntriesStartAddress;
  3241. if ( 1 == g_pSVCDNav->m_wEntriesUsedCnt )
  3242. {
  3243. gns.svcd.wCurrentEntryNumber = 1;
  3244. // tr_printf(("Current Entry Number is %04xn", gns.svcd.wCurrentEntryNumber));
  3245. }
  3246. else
  3247. {
  3248. for ( i = 0; i < g_pSVCDNav->m_wEntriesUsedCnt; i++)
  3249. {
  3250. Array_getAt(g_hEntriesTable, (UINT16)i, aucBuffer);
  3251. dwEntriesStartAddress= drv_msf2lbn(drv_bcd2bin(aucBuffer[1]), drv_bcd2bin(aucBuffer[2]), drv_bcd2bin(aucBuffer[3]));
  3252. if ( dwCurrentLocation < dwEntriesStartAddress  )
  3253. {
  3254. for(j=0;j<=g_pSVCDNav->m_wEntriesUsedCnt;j++)
  3255. {
  3256. Array_getAt(g_hEntriesTable, (UINT16)j, aucBuffer);
  3257. dwEntriesStartAddress = drv_msf2lbn(drv_bcd2bin(aucBuffer[1]), drv_bcd2bin(aucBuffer[2]), drv_bcd2bin(aucBuffer[3]));
  3258. if(dwEntriesStartAddress>=g_pSVCDNav->m_aCurrTrack[0])
  3259.      break;
  3260. }
  3261. i=i-j;
  3262. gns.svcd.wCurrentEntryNumber = i;
  3263. // tr_printf(("Current Entry Number is %04xn", gns.svcd.wCurrentEntryNumber));
  3264. break;
  3265. }
  3266. }
  3267. }
  3268. }
  3269. else
  3270. gns.svcd.wCurrentEntryNumber = 0xFFFF;
  3271. #endif
  3272. //>>>ML0704
  3273. // Check if the Start-PTS must be acquired
  3274. if ((g_pSVCDNav->m_TimeMeasurementInfo).bAcquireStartPTS) 
  3275. {
  3276. (g_pSVCDNav->m_TimeMeasurementInfo).dwStartPTS= dwCurrPTS;
  3277. (g_pSVCDNav->m_TimeMeasurementInfo).dwLastPTS= dwCurrPTS;
  3278. (g_pSVCDNav->m_TimeMeasurementInfo).bAcquireStartPTS= FALSE;
  3279. }
  3280. // Check that the PTS has monotonically increased since last time
  3281. if (dwCurrPTS >= (g_pSVCDNav->m_TimeMeasurementInfo).dwLastPTS) {
  3282. // The Elapsed-Time is the difference between the Current-PTS and the Start-PTS,
  3283. // divided by the PTS-Clock Frequency (90 KHz).
  3284. if (dwCurrPTS>=(g_pSVCDNav->m_TimeMeasurementInfo).dwStartPTS)
  3285. iElapsedTime= (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset + 
  3286. (int)((dwCurrPTS - (g_pSVCDNav->m_TimeMeasurementInfo).dwStartPTS) / SCR_RATE);
  3287. else {
  3288. iElapsedTime= (g_pSVCDNav->m_TimeMeasurementInfo).iTimeOffset -
  3289.   (int)(((g_pSVCDNav->m_TimeMeasurementInfo).dwStartPTS - dwCurrPTS ) / SCR_RATE);
  3290.                                    if (iElapsedTime<0)
  3291.                                       tr_printf(("nCurrent PTS error ! n"));
  3292. }
  3293. gns.svcd.wTotalElpasedTime = iElapsedTime + ((g_pSVCDNav->m_aCurrTrack[0] - g_pSVCDNav->m_dwSecondTrackAddress) / g_pSVCDNav->m_aCurrTrack[2]);
  3294. (g_pSVCDNav->m_TimeMeasurementInfo).dwLastPTS= dwCurrPTS;
  3295. iRetryCount = SVCD_PTS_MONOTONITY_GRACE_RETRIES;
  3296. }
  3297. else {
  3298. // The PTS hasn't increased monotonically - try again before abandoning
  3299. // the PTS-based measurement
  3300. if (iRetryCount > 0) {
  3301. iRetryCount--;
  3302. (g_pSVCDNav->m_TimeMeasurementInfo).dwLastPTS= dwCurrPTS;
  3303. }
  3304. else {
  3305. (g_pSVCDNav->m_TimeMeasurementInfo).bUsePTS= FALSE;
  3306. iRetryCount = SVCD_PTS_MONOTONITY_GRACE_RETRIES;
  3307. }
  3308. }
  3309. }
  3310. else {
  3311. // Failed to acquire the current PTS: don't update the Elapsed-Time
  3312. }
  3313. }