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

DVD

开发平台:

Others

  1. /****************************************************************************************
  2.  *  Copyright (c) 2003 ZORAN Corporation, All Rights Reserved
  3.  *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ZORAN CORPORATION
  4.  *
  5.  *  File: $Workfile: AVI.c $             
  6.  *
  7.  * Description: 
  8.  * ============
  9.  * 
  10.  * 
  11.  * Log:
  12.  * ====
  13.  * $Revision: #12 $
  14.  * $Change: 57739 $ 
  15.  * Last Modified by $Author: callie.cai $ at $DateTime: 2005/09/29 15:10:23 $ 
  16.  ****************************************************************************************
  17.  * Updates:
  18.  ****************************************************************************************
  19.  * $Log: /I76/I76_Common/I76_Reference/Playcore/Nav_Clips/AVI.c $
  20.  * 
  21.  * 79    4/03/04 1:58p Robinj
  22.  * avoid calculation overflow
  23.  * 
  24.  * 78    04-04-02 15:01 Fwang
  25.  * Fix green screen by MPP.
  26.  * 
  27.  * 77    04-04-01 19:19 Fwang
  28.  * Fix AVI AB repeat goes to start of clip.
  29.  * 
  30.  * 76    3/30/04 10:04p Robinj
  31.  * support special 3ivx clip, "fccHandler" is "mp4v"/"rmp4" and
  32.  * "biCompression" is "rmp4", it's same as "XVID"
  33.  * 
  34.  * 75    04-03-30 15:51 Fwang
  35.  * Fix pause after scan.
  36.  * 
  37.  * 74    04-03-29 11:09 Leonh
  38.  * keep the zoom when scan
  39.  * 
  40.  * 73    3/25/04 7:52p Robinj
  41.  * fix wrong number display when change subtitle/audio stream 
  42.  * 
  43.  * 72    3/25/04 7:28p Rond
  44.  * added watchdog for divx 3.11
  45.  * 
  46.  * 71    3/24/04 5:35p Robinj
  47.  * support special divx clip, "fccHandler" is "DX50" and  "biCompression"
  48.  * is "DX50", it's same as "Divx 5"
  49.  * playback without audio output when DIVX audio is PCM/ADPCM/WMA
  50.  * 
  51.  * 70    3/22/04 10:20a Robinj
  52.  * special divx clip, "fccHandler" is "MSVC" and  "biCompression" is
  53.  * "DIVX", it's same as "Divx 4.12"
  54.  * 
  55.  * 69    3/21/04 8:49p Lotan
  56.  * merge 4 with certification DB
  57.  * 
  58.  * 68    3/21/04 8:00p Hamadk
  59.  * Removed DRV_SET_BIT_RATE macro
  60.  * 
  61.  * 67    3/10/04 4:21p Lotan
  62.  * Merge with Divx Certification DB 3
  63.  * 
  64.  * 66    04-03-09 21:50 Leslie
  65.  * Mem reduction for DRM 
  66.  * 
  67.  * 65    3/08/04 4:14p Hamadk
  68.  * Merging with DivX certification DB - Optimized AVI file info memory
  69.  * 
  70.  * 64    3/04/04 10:22p Lotan
  71.  * Second merge with Divx Certification DB,
  72.  * including 2x16 SDram
  73.  * 
  74.  * 63    3/01/04 6:29p Lotan
  75.  * merge with Divx certification DB
  76.  * 
  77.  
  78.  * From Divx Certification DB
  79.  * DRM - add casting - just to make sure it is done correctly
  80.  * chage DRM indication, according to Divx's request
  81.  * Corrected calculation of time in idx proccessing for VBR
  82.  * Removed looking for Nandub - treat all clips with audio scale of 1152
  83.  * as VBR
  84.  * update Divx DRM rental screen parameters
  85.  * - Added support for different I spaces in the IDX for different clips
  86.  * - Code cleanup.
  87.  * Added error handling for DivX (Drive & Demux)
  88.  * Corrected getStatus() when IP FF is not supported
  89.  * Corrected saving/reading idx entries
  90.  * Replaced the autoplay patch
  91.  * patch to prevent index proccessing on auto play
  92.  * remove UI temp screen
  93.  * add DRM rental check and screen
  94.  * - Corrected Idx calculation for CBR to be more accurate.
  95.  * - Replaced printfs with dbg_printfs.
  96.  * No IP support
  97.  * Removed FIFO_destruct()
  98.  * add Reading Index message
  99.  * - Corrected bug in FB.
  100.  * - Code cleanup.
  101.  * fixed bug of more than one audio stream
  102.  * add DRM trick mode support
  103.  * divX Version for Certification
  104.  * drive speed up is ON
  105.  
  106. ====================
  107. * 62    2/27/04 7:06p Robinj
  108.  * Prohibit "FF/FB" when "idx1" not found
  109.  * 
  110.  * 61    2/19/04 10:47p Robinj
  111.  * fix the problem of chunk size is zero
  112.  * 
  113.  * 60    2/17/04 3:09p Lotan
  114.  * 
  115.  * 58    2/15/04 7:40p Lotan
  116.  * update DRM process. Add registration check, etc.
  117.  * 
  118.  * 57    2/13/04 12:09a Rond
  119.  * moved speed for High bit rate clips 
  120.  * 
  121.  * 56    04-02-11 17:33 Fwang
  122.  * Enable CPU scaling for DVD/VCD/SVCD.
  123.  * 
  124.  * 55    2/11/04 12:41a Lotan
  125.  * new Divx DRM handling method.
  126.  * 
  127.  * 54    2/10/04 8:44p Rond
  128.  * mpeg layer 2
  129.  * 
  130.  * 53    3/02/04 10:36 Lotan
  131.  * rollback, due to bug in VBR processing
  132.  * 
  133.  * 51    20/01/04 12:12 Lotan
  134.  * change DRM flag for DVP from false to true - for DRM support
  135.  * 
  136.  * 50    1/13/04 12:11 Hamadk
  137.  * Merged with CES DB
  138.  * 
  139.  * 49    12/26/03 14:08 Hamadk
  140.  * 
  141.  * 48    12/26/03 13:45 Hamadk
  142.  * - Added support for changing the start of the idx processing.
  143.  * - Fixed bug in idx processing not to regard audio for non-audio clips.
  144.  * - Fixed bug in resuming from FF I only to FF IP.
  145.  * 
  146.  * 47    12/25/03 15:50 Hamadk
  147.  * - Fixed bug in processing time to address.
  148.  * - Changed idx processing not to hangup in case of there's many audio
  149.  * chunks before key frames.
  150.  * 
  151.  * 46    12/25/03 11:15 Hamadk
  152.  * - Corrected updating of the time.
  153.  * - Corrected resuming from FF I only.
  154.  * - Corrected clearing DVPGen2 in resuming from FF IP.
  155.  * 
  156.  * 45    12/24/03 19:27 Hamadk
  157.  * 
  158.  * 44    12/24/03 17:41 Hamadk
  159.  * FF & GoTo time basically work
  160.  * 
  161.  * 43    12/24/03 9:38 Eyalr
  162.  * removed 512 width of Aharon temp slot machine
  163.  * 
  164.  * 42    12/23/03 12:31p Chaol
  165.  * for compilation pass
  166.  * 
  167.  * 41    12/23/03 12:12p Chaol
  168.  * modify MPP implement
  169.  * 
  170.  * 40    03-12-23 11:07 Fwang
  171.  * Workaround for video garbage when skip between clips.
  172.  * 
  173.  * 39    12/22/03 5:35p Chaol
  174.  * add MPP support for Divx
  175.  * 
  176.  * 38    22/12/03 14:53 Lotan
  177.  * solve special clip14 problem --> supports "mp43" (divx3.11) encoder
  178.  * 
  179.  * 37    12/18/03 19:14 Hamadk
  180.  * - Corrected FF operation.
  181.  * - Corrected GoTo time operation.
  182.  * - Removed code orginization
  183.  * 
  184.  * 36    03-12-18 13:22 Fwang
  185.  * Implement CC-RAM scaling.
  186.  * 
  187.  * 35    12/18/03 12:41 Hamadk
  188.  * Changed getTime function not to check the SCLK in case the DVP is still
  189.  * not in NSPB
  190.  * 
  191.  * 34    12/18/03 11:15 Hamadk
  192.  * - Replaced sending the demux fixed video/audio stream numbers to the
  193.  * actual played ones.
  194.  * - Code cleanup.
  195.  * 
  196.  * 33    12/18/03 9:46 Nmaurer
  197.  * Adjust the Drive speed according to the clip bitrate
  198.  * 
  199.  * 32    12/17/03 18:08 Eyalr
  200.  * fixed 512 width Divx problem
  201.  * 
  202.  * 31    16/12/03 14:37 Lotan
  203.  * fix subtitle bug (picture of clips with subtitle was wrong)
  204.  * 
  205.  * 30    12/14/03 19:27 Eyalr
  206.  * added two parameters to set files
  207.  * 
  208.  * 29    12/14/03 18:31 Eyalr
  209.  * 
  210.  * 28    12/12/03 16:33 Eyalr
  211.  * 
  212.  * 27    12/12/03 14:02 Eyalr
  213.  * 
  214.  * 26    12/11/03 10:06 Eyalr
  215.  * 
  216.  * 25    12/09/03 17:20 Eyalr
  217.  * changed SEt file param
  218.  * 
  219.  * 24    12/08/03 3:49p Fwang
  220.  * To avoid uninitialized scaling parameter.
  221.  * 
  222.  * 23    12/07/03 8:51p Fwang
  223.  * Scaling by CPU
  224.  * 
  225.  * 22    12/04/03 1:11p Leslie
  226.  * Abort drive each time after we finish parse AVI File Header information
  227.  * 
  228.  * 21    11/30/03 10:05 Eyalr
  229.  * 
  230.  * 20    11/27/03 18:40 Eyalr
  231.  * 
  232.  * 19    11/27/03 18:19 Eyalr
  233.  * 
  234.  * 18    11/26/03 17:24 Eyalr
  235.  * Zooming & Scalling on CPU
  236.  * 
  237.  * 17    11/26/03 15:55 Eyalr
  238.  * 
  239.  * 16    11/26/03 11:59 Eyalr
  240.  * playing XVID
  241.  * 
  242.  * 15    25/11/03 18:07 Lotan
  243.  * fix playback range calculation bug
  244.  * 
  245.  * 14    11/24/03 18:59 Eyalr
  246.  * display logo on stop
  247.  * 
  248.  * 13    11/18/03 9:29 Eyalr
  249.  * added SID for Decoder & UI
  250.  * 
  251.  * 12    11/17/03 14:10 Eyalr
  252.  * 
  253.  * 11    11/06/03 15:16 Eyalr
  254.  * added new features for Divx
  255.  * 
  256.  * 10    10/29/03 17:46 Eyalr
  257.  * 
  258.  * 9     10/22/03 19:04 Hamadk
  259.  * - Moved AVI Clip navigator info in the global navigation union.
  260.  * - Changed the clip's get status function to be like generic clip.
  261.  * - Updated function names.
  262.  * - Added support for XVID.
  263.  * - Code cleanup.
  264.  * 
  265.  * 8     10/20/03 14:34 Eyalr
  266.  * 
  267.  * 7     10/12/03 15:12 Hamadk
  268.  * - Fixed idx processing.
  269.  * - Added documentation.
  270.  * - Code cleanup.
  271.  * 
  272.  * 6     10/12/03 9:06 Hamadk
  273.  * Corrected processing of the Idx
  274.  * 
  275.  * 5     10/02/03 18:47 Hamadk
  276.  * Corrected calculating the requested entry from the IDX
  277.  * 
  278.  * 4     10/02/03 17:46 Hamadk
  279.  * Corrected reaching the end of the idx table while scanning
  280.  * 
  281.  * 3     10/02/03 10:35 Hamadk
  282.  *  - Corrected calculation of end address and end offset
  283.  *  - Added support for FF/FB
  284.  * 
  285.  * 2     9/29/03 8:18 Hamadk
  286.  * 
  287.  ****************************************************************************************/
  288. #include "Config.h" // Global Configuration - do not remove!
  289. #ifdef _DEBUG
  290. #undef IFTRACE
  291. #define IFTRACE if (gTraceNavigator)
  292. #include "Debugdbgmain.h"
  293. #endif
  294. #include "Decoderadp_api.h"
  295. #include "Decoderlow_levelDEC_LL_API.h"
  296. #include "Decoderlow_levelDEC_LL_Def.h"
  297. #include "Drivedrv_api.h"
  298. #include "Includestring_ex.h"
  299. #include "KernelEventDef.H"
  300. #include "KernelKer_API.h"
  301. #include "LogoLogo.h"
  302. #include "PlaycoreCoremainCoreDefs.h"
  303. #include "PlaycoreCoremainCoreGDef.h"
  304. #include "PlaycoreAuxCacheAuxCache.h"
  305. #include "PlaycoreNav_CDDAPE_CD.h"
  306. #include "PlaycoreNav_ClipsAVI.h"
  307. #include "PlaycoreNav_ClipsAVI_private.h"
  308. #include "PlaycoreNav_ClipsClip_Impl.h"
  309. #include "PlaycoreNav_ClipsGenericClip.h"
  310. #include "PlaycoreNav_ClipsPE_Clips.h"
  311. #include "PlaycorePlayModePlayMode.h"
  312. #include "PlaycorePSPS.h"
  313. #include "DecoderDec_Avi_Drm.h"
  314. #include "Decoderlow_levelDEC_LL_Reg.h"
  315. #include "PlaycoreNav_ClipsAviDrmLibDrmCommonDrmErrors.h"
  316. #include "PlaycoreNav_ClipsMpeg4ClipsCommon.h"
  317. #ifdef USE_AUX_SUBTITLES
  318. #include "PlaycoreNav_ClipsAuxSubtitles.h"
  319. #endif
  320. #ifdef AVI_DRM_SUPPORT
  321. #include "Playcore/Nav_Clips/AviDrm/libDrmDecrypt/DrmAdpApi.h"
  322. #endif
  323. #ifdef _DEBUG
  324. #include "CPUTimefunc.h"
  325. #endif
  326. #ifdef SUPPORT_FLASH_CARD
  327. #include "drivefe_manager.h"
  328. #include "mediacardsincluderegister.h"
  329. #endif
  330. /////////////////////////////////////////////////////////////////////////////
  331. // Globals and Singletions
  332. #define CALC_IDX_ENTRY_ADDRESS(address, offset) (address - (offset >> 1) - sizeof(IndexEntry)/2)
  333. static AVIIndexEntry*  _idxEntries = NULL;
  334. static UINT16   _aviIdxIDiff;
  335. /* DRM info */
  336. #ifdef AVI_DRM_SUPPORT
  337. extern UINT16 uiAviDrmFrameKeyIndex;
  338. extern keyInstance* pMasterKeyInstance;
  339. WORD g_ScAviDrm_KeysOffset = SC_AVI_DRM_KEYS_ADDR;
  340. BOOL g_bDivxRentanSelection;
  341. BOOL g_bUserAck;
  342. UINT16 g_DivxRentalsLeft=0;
  343. UINT16 g_DivxRentalsTotal=0;
  344. #endif //AVI_DRM_SUPPORT
  345. // RB_TBD
  346. // Robin_1003_2004_D
  347. //static BOOL bVideoBeforeAudio = FALSE;
  348. // Robin_1003_2004_C
  349. static BOOL bVideoAudioInterleave = TRUE;
  350. #ifdef NO_AUTO_PLAY_FOR_CLIPS
  351. BOOL g_patch_4_auto_play;
  352. #endif
  353. extern CURRENT_STATES gcst; /* Global current status */
  354. extern BOOL change_pallet;
  355. // Robin_1119_2004, display AVI audio/subtitle language
  356. static CONST LanguageCode DIVX_LANGUAGE_CODE_LUT[]  =
  357. {
  358. {""}, // 0 None
  359. {"Ara"}, // 1 Arabic   
  360. {"Bul"}, // 2 Bulgarian   
  361. {"Cat"}, // 3 Catalan    
  362. {"Chi"}, // 4 Chinese    
  363. {"Cze"}, // 5 Czech   
  364. {"Dan"}, // 6 Danish   
  365. {"Ger"}, // 7 German   
  366. {"Gre"}, // 8 Greek   
  367. {"Eng"}, // 9 English    
  368. {"Spa"}, // 10 Spanish    
  369. {"Fin"}, // 11 Finnish    
  370. {"Fre"}, // 12 French   
  371. {"Heb"}, // 13 Hebrew   
  372. {"Hun"}, // 14 Hungarian   
  373. {"Ice"}, // 15 Icelandic   
  374. {"Ita"}, // 16 Italian    
  375. {"Jap"}, // 17 Japanese   
  376. {"Kor"}, // 18 Korean   
  377. {"Dut"}, // 19 Dutch   
  378. {"Nor"}, // 20 Norwegian   
  379. {"Pol"}, // 21 Polish   
  380. {"Por"}, // 22 Portuguese   
  381. {"Rha"}, // 23 Rhaeto-Romanic
  382. {"Rom"}, // 24 Romanian   
  383. {"Rus"}, // 25 Russian    
  384. {"Cro"}, // 26 Croatian   
  385. {"Slo"}, // 27 Slovak   
  386. {"Alb"}, // 28 Albanian   
  387. {"Swe"}, // 29 Swedish    
  388. {"Tha"}, // 30 Thai   
  389. {"Tur"}, // 31 Turkish    
  390. {"Urd"}, // 32 Urdu   
  391. {"Bah"}, // 33 Bahasa
  392. };
  393. /////////////////////////////////////////////////////////////////////////////
  394. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE_MODE0
  395. extern WORD Get_SubFile_Select(void);
  396. #endif
  397. #ifdef MPP_SUPPORT
  398. extern void DEC_SetMPP(BOOL enable);
  399. #endif
  400. static BOOL _aviDetectBVOP(void);
  401. /////////////////////////////////////////////////////////////////////////////
  402. // Forward Declarations of Virtual Methods
  403. BOOL AVIClip_getExtendedInfo(const struct Clip_TAG *i_pThis, WORD i_pExtInfo_sc_handle);
  404. BOOL AVIClip_play(Clip *i_pThis, const ClipMarker *i_pResumeMarker, BOOL bCacheOnly);
  405. void AVIClip_pause(Clip *i_pThis, BOOL bEnable);
  406. void AVIClip_refresh(Clip *i_pThis);
  407. UINT16 AVIClip_getTime(const Clip *i_pThis);
  408. enClipStatus AVIClip_getStatus(const Clip *i_pThis);
  409. void AVIClip_scan(Clip *i_pThis, int iScanSpeed);
  410. void AVIClip_recordMarker(const Clip *i_pThis, ClipMarker *o_pMarker);
  411. void AVIClip_abort(Clip *i_pThis, BOOL bMaintainStandby);
  412. /////////////////////////////////////////////////////////////////////////////
  413. // Const Factory
  414. /* Valid Extenions List */
  415. BEGIN_CLIP_VALID_EXTENSIONS_MAP(AVI)
  416. CLIP_VALID_EXTENSIONS_ENTRY(L"AVI")
  417. CLIP_VALID_EXTENSIONS_ENTRY(L"DIVX")
  418. CLIP_VALID_EXTENSIONS_ENTRY(L"DIV")
  419. CLIP_VALID_EXTENSIONS_ENTRY(L"XVID")
  420. END_CLIP_VALID_EXTENSIONS_MAP()
  421. /* Constant Attributes */
  422. DECLARE_CLIP_CONST_ATTR(AVI, 
  423. DECLARE_CLIP_VTABLE(AVIClip_getExtendedInfo,
  424. AVIClip_play,
  425. AVIClip_pause,
  426. AVIClip_getStatus,
  427. AVIClip_abort,
  428. AVIClip_recordMarker,
  429. AVIClip_refresh,
  430. AVIClip_getTime,
  431. GenericClip_digest,
  432. AVIClip_scan
  433. ),
  434. eClipType_AVI,
  435. 0xFF, 0xE0, DEC_DISC_TYPE_AVI, //FW0408_2005C Set 0xE0 as video SID
  436. (eCA_Scanable | eCA_Zoomable | eCA_Slowable | eCA_Markable/* | eCA_Digestable*/),
  437. NULL
  438. )
  439. /////////////////////////////////////////////////////////////////////////////
  440. // Private Services
  441. // <<< Robin_1003_2004_A, check the chunk offset in the Index is from the "movi"
  442. ///////////////////////////////////////////////////////////////////////////
  443. // Function name : _checkAVIClipOffset
  444. // Purpose : Check the offset in Index is from MOVI 
  445. // Input Parameters : dwClipStartAddr - the clip start add
  446. // : dwMovieListOffset - the offset of Movi
  447. // Output Parameters : 
  448. // Return type : BOOL
  449. ///////////////////////////////////////////////////////////////////////////
  450. static BOOL _checkAVIClipOffset(DWORD dwClipStartAddr, DWORD dwMovieListOffset)
  451. {
  452. IndexEntry indexEntry;
  453. DWORD dwOffset;
  454. DWORD dwFourCC;
  455. DWORD dwVideoStreamID1, dwVideoStreamID2;
  456. UINT16 uiCount;
  457. if (FALSE == _bMPEG4TrickModeOn)
  458. return FALSE;
  459. dwVideoStreamID1 = ((DWORD)('c') << 24) + ((DWORD)('d')<<16) + ((DWORD)(_mpeg4VideoStreamID+ '0') << 8) + '0';
  460. dwVideoStreamID2 = ((DWORD)('b') << 24) + ((DWORD)('d')<<16) + ((DWORD)(_mpeg4VideoStreamID + '0') << 8) + '0';
  461. for(uiCount=0;uiCount<2;uiCount++)
  462. {
  463. wai_sem(SEM_DRAM_ID);
  464. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,(uiCount*sizeof(IndexEntry))),
  465.  (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  466. sig_sem( SEM_DRAM_ID );
  467. dwOffset = indexEntry.ulVideoChunkOffset + dwMovieListOffset - FOURCC_FIELD_LENGTH;
  468. AuxCache_GetBytes(dwClipStartAddr, dwOffset, FOURCC_FIELD_LENGTH, &dwFourCC);
  469. if ((dwFourCC != dwVideoStreamID1) && (dwFourCC != dwVideoStreamID2) )
  470. return FALSE;
  471. }
  472. return TRUE;
  473. }
  474. // >>> Robin_1003_2004_A
  475. ///////////////////////////////////////////////////////////////////////////
  476. // Function name : StringToFourCC
  477. // Purpose : Returns the FOURCC string type.
  478. // Input Parameters : fourCCstring - The FourCC string.
  479. // Output Parameters: none
  480. // Return type : The FourCC type.
  481. ///////////////////////////////////////////////////////////////////////////
  482. static EFourCCType StringToFourCC(char* fourCCstring)
  483. {
  484.    if (0 == strnicmp(fourCCstring, VIDEO_STREAM_TYPE_ID, FOURCC_FIELD_LENGTH))
  485.    {
  486.       return EVids;
  487.    }
  488.    else if (0 == strnicmp(fourCCstring, AUDIO_STREAM_TYPE_ID, FOURCC_FIELD_LENGTH))
  489.    {
  490.       return EAuds;
  491.    }
  492.    else if (0 == strnicmp(fourCCstring, TEXT_STREAM_TYPE_ID, FOURCC_FIELD_LENGTH))
  493.    {
  494.       return ETxts;
  495.    }
  496.    else if (0 == strnicmp(fourCCstring, AVI_STREAM_HEADER_START_ID, FOURCC_FIELD_LENGTH))
  497.    {
  498.       return EStrl;
  499.    }
  500.    else if (0 == strnicmp(fourCCstring, AVI_STREAM_HEADER_ID, FOURCC_FIELD_LENGTH))
  501.    {
  502.       return EStrh;
  503.    }
  504.    else if (0 == strnicmp(fourCCstring, AVI_STREAM_FORMAT_ID, FOURCC_FIELD_LENGTH))
  505.    {
  506.       return EStrf;
  507.    }
  508.    else if (0 == strnicmp(fourCCstring, AVI_STREAM_HEADER_DATA_ID, FOURCC_FIELD_LENGTH))
  509.    {
  510.       return EStrd;
  511.    }
  512.    /* else */
  513.    return EInvalid;
  514. }
  515. ///////////////////////////////////////////////////////////////////////////
  516. // Function name : _getAdjacentIFrames
  517. // Purpose : Returns the nearby I frames of the given time, with 
  518. //   their times.
  519. // Input Parameters : dwClipStartAddr - The start address of the clip.
  520. //   wCurrTime       - The current time.
  521. // Return type : TRUE - if succeeded, FALSE otherwise.
  522. // Output Parameters: The tow I frames numbers with their times.
  523. // Description : 
  524. ///////////////////////////////////////////////////////////////////////////
  525. static BOOL _getAdjacentIFrames(DWORD dwClipStartAddr, WORD wCurrTime, 
  526.            UINT32* ulFirstIFrame, UINT32* ulSecondIFrame,
  527.         WORD* wFirstITime, WORD* wSecondITime,
  528. UINT32* ulFirstIIdx, UINT32* ulSecondIIdx)
  529. {
  530. UINT32 ulIndex;
  531. UINT32 ulRequestedFrameNumber;
  532. IndexEntry currIndexEntry;
  533. IndexEntry previousIndexEntry;
  534. DWORD dwFirstChunkOffset;
  535. /* Read the index if it is not read yet */
  536. if (FALSE == _aquireAndProcessIdx(dwClipStartAddr, _mpeg4VideoStreamID, _mpeg4AudioStreamID,&dwFirstChunkOffset))
  537. {
  538. dbg_printf(("WARNING: _getAdjacentIFrames() FAILEDn"));
  539. return FALSE;
  540. }
  541. /* Calculate the frame number corresponding to the given time */
  542. // Robin_1003_2004_B
  543. ulRequestedFrameNumber = caclFrameOfTime(wCurrTime, 
  544. _mpeg4VideoRate, 
  545. _mpeg4VideoScale);
  546. /* Seek the index table to find the nearby I frames */
  547. for (ulIndex=0; ulIndex<_uiMPEG4NextIndexEntry; ulIndex++)
  548. {
  549. wai_sem(SEM_DRAM_ID);
  550. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (ulIndex*sizeof(currIndexEntry))),
  551.  (UINT16*)&currIndexEntry, sizeof(currIndexEntry)/2);
  552. sig_sem(SEM_DRAM_ID);
  553. if (currIndexEntry.ulVideoFrameNumber < ulRequestedFrameNumber)
  554. {
  555. /* Checking if this is the last entry */
  556. if ( (_uiMPEG4NextIndexEntry-1) == ulIndex )
  557. {
  558. /* Get the previous entry in the index table */
  559. wai_sem(SEM_DRAM_ID);
  560. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,((ulIndex-1)*sizeof(IndexEntry))),
  561.  (UINT16*)&previousIndexEntry, sizeof(IndexEntry)/2);
  562. sig_sem(SEM_DRAM_ID);
  563. *ulFirstIIdx = ulIndex - 1;
  564. *ulSecondIIdx = ulIndex;
  565. break;
  566. }
  567. }
  568. else
  569. {
  570. /* Check if this is the first entry */
  571. if (0UL == ulIndex)
  572. {
  573. previousIndexEntry = currIndexEntry;
  574. /* Get the previous entry in the index table */
  575. wai_sem(SEM_DRAM_ID);
  576. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,((ulIndex+1)*sizeof(IndexEntry))),
  577.  (UINT16*)&currIndexEntry, sizeof(IndexEntry)/2);
  578. sig_sem(SEM_DRAM_ID);
  579. *ulFirstIIdx = ulIndex;
  580. *ulSecondIIdx = ulIndex + 1;
  581. }
  582. else
  583. {
  584. /* Get the previous entry in the index table */
  585. wai_sem(SEM_DRAM_ID);
  586. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, ((ulIndex-1)*sizeof(IndexEntry))),
  587.  (UINT16*)&previousIndexEntry, sizeof(IndexEntry)/2);
  588. sig_sem(SEM_DRAM_ID);
  589. *ulFirstIIdx = ulIndex - 1;
  590. *ulSecondIIdx = ulIndex;
  591. }
  592. break;
  593. }
  594. }
  595. // Robin_1003_2004_B
  596. *wFirstITime = caclTimeOfFrame(previousIndexEntry.ulVideoFrameNumber,
  597.          _mpeg4VideoRate,
  598.   _mpeg4VideoScale);
  599. // Robin_1003_2004_B
  600. *wSecondITime = caclTimeOfFrame(currIndexEntry.ulVideoFrameNumber,
  601.           _mpeg4VideoRate,
  602.    _mpeg4VideoScale);
  603. *ulFirstIFrame = previousIndexEntry.ulVideoFrameNumber;
  604. *ulSecondIFrame = currIndexEntry.ulVideoFrameNumber;
  605. return TRUE;
  606. }
  607. ///////////////////////////////////////////////////////////////////////////
  608. // Function name : _getNextIFrames
  609. // Purpose : Returns the next I frames of the given frame number, with 
  610. //   their indexs.
  611. // Input Parameters : dwClipStartAddr - The start address of the clip.
  612. //  ulRequestedFrameNumber       - The current frame number.
  613. // Return type : TRUE - if succeeded, FALSE otherwise.
  614. // Output Parameters: The next Iframe index.
  615. // Description : 
  616. ///////////////////////////////////////////////////////////////////////////
  617. static BOOL _getNextIFrames(DWORD dwClipStartAddr, UINT32 ulRequestedFrameNumber, 
  618. UINT32* ulNextIIdx, UINT16* wNextITime)
  619. {
  620. UINT32 ulIndex;
  621. IndexEntry currIndexEntry;
  622. DWORD dwFirstChunkOffset;
  623. // Read the index if it is not read yet 
  624. if (FALSE == _aquireAndProcessIdx(dwClipStartAddr, _mpeg4VideoStreamID, _mpeg4AudioStreamID,&dwFirstChunkOffset))
  625. {
  626. dbg_printf(("WARNING: _getNextIFrames() FAILEDn"));
  627. return FALSE;
  628. }
  629. // Seek the index table to find the nearby I frames 
  630. for (ulIndex=0; ulIndex<=_uiMPEG4NextIndexEntry; ulIndex++)
  631. {
  632. if(ulIndex == _uiMPEG4NextIndexEntry)
  633. {
  634. dbg_printf(("ulIndex == _uiMPEG4NextIndexEntryn"));
  635. break;
  636. }
  637. wai_sem(SEM_DRAM_ID);
  638. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (ulIndex*sizeof(currIndexEntry))),
  639.  (UINT16*)&currIndexEntry, sizeof(currIndexEntry)/2);
  640. sig_sem( SEM_DRAM_ID );
  641. if (currIndexEntry.ulVideoFrameNumber > ulRequestedFrameNumber)
  642. {
  643. break;
  644. }
  645. }
  646. *ulNextIIdx = ulIndex;
  647. // Robin_1003_2004_B
  648. *wNextITime = caclTimeOfFrame(currIndexEntry.ulVideoFrameNumber,
  649.          _mpeg4VideoRate,
  650.   _mpeg4VideoScale);
  651. return TRUE;
  652. }
  653. ///////////////////////////////////////////////////////////////////////////
  654. // Function name : _getNextFOURCC
  655. // Purpose : Returns the next FOURCC in the file.
  656. // Input Parameters : dwClipStartAddr - The start address to get the FOURCC.
  657. //   dwOffset        - The offset to read the FOURCC.
  658. // Return type : TRUE - if succeeded, FALSE otherwise.
  659. // Output Parameters: pForccInfo - The FOURCC info which was read.
  660. // Description : The function reads the first 32 bits from the 
  661. //   specified location, if it a 'LIST' FOURCC it returns
  662. //   the list's type FOURCC (among the other things), 
  663. //   otherwise, it is assumed this is a chunk FOURCC.
  664. ///////////////////////////////////////////////////////////////////////////
  665. static BOOL _getNextFOURCC(DWORD dwClipStartAddr, DWORD dwOffset, FOURCCInfo* pForccInfo)
  666. {
  667. BYTE aCurrSize[4];
  668. if (!AuxCache_GetBytes(dwClipStartAddr, dwOffset, (WORD)FOURCC_FIELD_LENGTH, pForccInfo->aFOURCCBuff))
  669. {
  670. dbg_printf(("FATAL: _getNextList() Failed [1]n"));
  671. return FALSE;
  672. }
  673. pForccInfo->bIsList = FALSE;
  674. dwOffset += FOURCC_FIELD_LENGTH; /* Skipping the FOURCC field */
  675. /* Check whether the FOURCC is 'LIST' */
  676. if (0 == strnicmp((LPSTR)(pForccInfo->aFOURCCBuff), AVI_LIST_FOURCC_ID, FOURCC_FIELD_LENGTH)) 
  677. {
  678. /* List is detected */
  679. pForccInfo->bIsList = TRUE;
  680. dwOffset += SIZE_FIELD_LENGTH; /* Skipping the size field */
  681. /* Reading the list type FOURCC */
  682. if (!AuxCache_GetBytes(dwClipStartAddr, dwOffset, (WORD)FOURCC_FIELD_LENGTH, pForccInfo->aFOURCCBuff))
  683. {
  684. dbg_printf(("FATAL: _getNextList() Failed [2]n"));
  685. return FALSE;
  686. }
  687. dwOffset -= SIZE_FIELD_LENGTH; /* Updating the offset for the list size field */
  688. }
  689. /* Getting the list/chunk size */
  690. if (!AuxCache_GetBytes(dwClipStartAddr, dwOffset, (WORD)sizeof(aCurrSize), aCurrSize))
  691. {
  692. dbg_printf(("FATAL: _getNextList() Failed [3]n"));
  693. return FALSE;
  694. }
  695. pForccInfo->ulSize = ((*((UINT32*)aCurrSize) + 1) /2) * 2;// padding to word boundary 
  696. return TRUE;
  697. }
  698. ///////////////////////////////////////////////////////////////////////////
  699. // Function name : _searchForFOURCC
  700. // Purpose : Searches for a specific FOURCC according to the 
  701. //   requested one.
  702. // Input Parameters : dwClipStartAddr - The start address to get the FOURCC.
  703. //   pdwOffset       - Pointer to the offset to read the FOURCC.
  704. //   fourccName      - The FOURCC to search for.
  705. //   bReadFOURCCData - Indicates whether the FOURCC data 
  706. // should be read.
  707. // Output Parameters: pForccInfo - The requested FOURCC info.
  708. //   pdwOffset  - Update the offset to the next chunk/list.
  709. // Return type : TRUE - if succeeded, FALSE otherwise.
  710. // Description : 
  711. ///////////////////////////////////////////////////////////////////////////
  712. static BOOL _searchForFOURCC(DWORD dwClipStartAddr, DWORD* pdwOffset, 
  713.    LPSTR fourccName, FOURCCInfo* pFourccInfo, BOOL bReadFOURCCData, WORD wDataSize)
  714. {
  715. /* Keep checking the next available FOURCC till reaching the required one */
  716. while (TRUE)
  717. {
  718. /* Get the next FOURCC */
  719. if (FALSE == _getNextFOURCC(dwClipStartAddr, *pdwOffset, pFourccInfo))
  720. {
  721. dbg_printf(("FATAL: _searchForFOURCC() Failed [1]n"));
  722. return FALSE;
  723. }
  724. /* Check whether this is the FOURCC we are looking for */
  725. if (0 == strnicmp((LPSTR)pFourccInfo->aFOURCCBuff, fourccName, FOURCC_FIELD_LENGTH))
  726. {
  727. /* Reach the chunk/list data area */
  728. (*pdwOffset) += FOURCC_FIELD_LENGTH;
  729. (*pdwOffset) += SIZE_FIELD_LENGTH; 
  730. if (TRUE == pFourccInfo->bIsList)
  731. {
  732. (*pdwOffset) += LIST_TYPE_FIELD_LENGTH; 
  733. }
  734. /* Read the chunk/list data if required */
  735. if (TRUE == bReadFOURCCData)
  736. {
  737. if (!AuxCache_GetBytes(dwClipStartAddr, *pdwOffset, wDataSize, pFourccInfo->pData))
  738. {
  739. dbg_printf(("FATAL: _searchForFOURCC() Failed [2]n"));
  740. return FALSE;
  741. }
  742. }
  743. /* Update the offset to reach the next list/chunk */
  744. if (TRUE == pFourccInfo->bIsList)
  745. {
  746. (*pdwOffset) -= LIST_TYPE_FIELD_LENGTH; 
  747. }
  748. (*pdwOffset) += (DWORD)pFourccInfo->ulSize;
  749. return TRUE;
  750. }
  751. /* Skip to the next list/chunk */
  752. (*pdwOffset) += FOURCC_FIELD_LENGTH;
  753. (*pdwOffset) += SIZE_FIELD_LENGTH; 
  754. (*pdwOffset) += (DWORD)pFourccInfo->ulSize;
  755. // get the wrong data because bad disc
  756. if (4 > strlen((LPSTR)pFourccInfo->aFOURCCBuff))
  757. {
  758. tr_printf(("Failed: Wrong Fourcc, %s", (LPSTR)pFourccInfo->aFOURCCBuff));
  759. return FALSE;
  760. }
  761. }
  762. }
  763. ///////////////////////////////////////////////////////////////////////////
  764. // Function name : _searchForDrmFOURCC
  765. // Purpose : Searches for a DRM FOURCC, if found, all of the necessary
  766. //                  DRM data will be saved in the scratch pad.
  767. //
  768. // Input Parameters : DWORD dwClipStartAddr,  - The start address to get the FOURCC
  769. //                     DWORD* pdwOffset,       - Pointer to the offset to read the FOURCC.
  770. //                     FOURCCInfo* pFourccInfo - The FOURCC to search for (DRM)
  771. //
  772. // Output Parameters: None.
  773. // Return type      : TRUE - if the stream should be played (DRM not found, or DRM found,
  774. //                           and its legal to play.
  775. //                    FALSE - if the steram should not be played (registration expired, etc.)
  776. ///////////////////////////////////////////////////////////////////////////
  777. static BOOL _searchForDrmFOURCC(DWORD dwClipStartAddr, DWORD* pdwOffset, FOURCCInfo* pFourccInfo)
  778. {
  779. #ifdef AVI_DRM_SUPPORT
  780.     
  781.     BYTE* drmInfoHeader;
  782.     BYTE* drmPlayContext; 
  783.     uint8_t useLimit;
  784.     uint8_t useCount;
  785.     uint8_t result = DRM_ERROR_NONE;
  786.     WORD wDataSize;
  787. UINT32 drm_length;
  788.     
  789.     dbg_printf(("Reset DRM globals.n"));
  790.     uiAviDrmFrameKeyIndex = -1;
  791.     if (NULL != pMasterKeyInstance)
  792.     {
  793.         free (pMasterKeyInstance);
  794.         dbg_printf(("key instance was set in the beggining!n"));
  795.         pMasterKeyInstance = NULL;
  796.     }
  797.     
  798.     /* Get the next FOURCC */
  799.     if (FALSE == _getNextFOURCC(dwClipStartAddr, *pdwOffset, pFourccInfo))
  800.     {
  801.         dbg_printf(("no DRMn"));
  802.         _bAVIDrmOn = FALSE;
  803.         return TRUE;
  804.     }
  805.     
  806.     /* Check if this fourCC is DRM (assuming the strl was video */
  807.     if (0 == strnicmp((LPSTR)pFourccInfo->aFOURCCBuff, AVI_STREAM_HEADER_DATA_ID, FOURCC_FIELD_LENGTH))
  808.     {
  809.         /* Reach the chunk/list data area */
  810.         (*pdwOffset) += FOURCC_FIELD_LENGTH;
  811.         (*pdwOffset) += SIZE_FIELD_LENGTH; 
  812.         
  813. // Robin_2004_0525_A, patch for the "strd" chunk, no DRM information
  814.         (*pdwOffset) += 4; 
  815.         if (!AuxCache_GetBytes(dwClipStartAddr, *pdwOffset, 4, &drm_length))
  816.         {
  817.             dbg_printf(("FATAL: _searchForFOURCC() Failed [3]n"));
  818.             return TRUE;
  819.         }
  820. (*pdwOffset) += 4; 
  821. // The condition is not accurate, Robin_2004_0525_A
  822. if ((drm_length >= 2224) && (pFourccInfo->ulSize >= 2232))
  823. {
  824.         dbg_printf(("DRM onn"));
  825.         _bAVIDrmOn = TRUE;
  826. #ifdef SUPPORT_FLASH_CARD //DIVX with DRM is not supported on card.
  827.   if(IS_PLAYING_CARD)
  828.   return FALSE;
  829. #endif
  830. }
  831. else
  832. {
  833. dbg_printf(("no DRMn"));
  834.          _bAVIDrmOn = FALSE;
  835. return TRUE;
  836. }
  837. // <<< Robin_2004_0525_A
  838.         /* prase DRM data */
  839.         
  840.         /* Read the chunk/list data if required */
  841.         wDataSize = (FALSE == pFourccInfo->bIsList) ? 
  842.             ((WORD)pFourccInfo->ulSize ) :
  843.         ((WORD)pFourccInfo->ulSize - LIST_TYPE_FIELD_LENGTH);
  844.         
  845. #ifdef AVI_MALLOC_SIZE_DOWN 
  846. // wDataSize -= DRM_FRAME_KEY_COUNT * KEY_SIZE_BYTES;
  847. wDataSize = sizeof (DrmHeader);
  848. #endif
  849.         drmPlayContext = (BYTE*)malloc (wDataSize+1);
  850.         drmInfoHeader = drmPlayContext ; // pointer assignment!
  851.         //drmInfoHeader = (BYTE*)malloc (wDataSize);
  852.         
  853.         if ( NULL == drmInfoHeader)
  854.         {
  855.             dbg_printf(("malloc drm info header size: %d failed!!n",wDataSize));
  856.             return FALSE;
  857.             
  858.         }
  859.         else
  860.         {
  861.             dbg_printf(("malloc drm info header size: %d successfulln",wDataSize));
  862.         }
  863.         
  864.         if (!AuxCache_GetBytes(dwClipStartAddr, *pdwOffset, wDataSize, drmInfoHeader))
  865.         {
  866.             dbg_printf(("FATAL: _searchForFOURCC() Failed [2]n"));
  867.             free (drmInfoHeader);
  868.             return TRUE;
  869.         }
  870.         
  871.         result = drmInitPlaybackContext( drmPlayContext );
  872.         if (DRM_ERROR_NONE != result)
  873.         {
  874.             ie_send(IE_UI_DIVX_MSG_AUTHORIZATION_ERROR);
  875.             dbg_printf(("1 DRM Message 1 (generic), code %d - Screen 2n", result));
  876. free (drmInfoHeader);
  877. gcs.pstate= PST_STOP;
  878.             return FALSE;
  879.         }      
  880.         
  881.         result = drmQueryRentalStatus(drmPlayContext, &useLimit, &useCount);
  882.         if (DRM_ERROR_RENTAL_EXPIRED == result)
  883.         {
  884.             ie_send(IE_UI_DIVX_MSG_RENTAL_EXPIRED);
  885.             dbg_printf(("2 DRM Message 2 (expired), code %d - Screen 3n", result));
  886.             free (drmInfoHeader);
  887. gcs.pstate= PST_STOP;
  888.             return FALSE;
  889.         }
  890.         if (DRM_ERROR_NOT_AUTH_USER == result)
  891.         {
  892.             ie_send(IE_UI_DIVX_MSG_AUTHORIZATION_ERROR);
  893.             dbg_printf(("3 DRM Message 3 (not auth user), code %d - Screen 2n", result));
  894.             free (drmInfoHeader);
  895. gcs.pstate= PST_STOP;
  896.             return FALSE;
  897.         }
  898.         if (DRM_ERROR_NOT_LIMITED_RENTAL_TYPE != result &&
  899.             DRM_ERROR_NONE != result)
  900.         {
  901.             ie_send(IE_UI_DIVX_MSG_AUTHORIZATION_ERROR);
  902.             dbg_printf(("4 DRM Message 1 (generic), code %d - Screen 2n", result));
  903.             free (drmInfoHeader);
  904. gcs.pstate= PST_STOP;
  905.             return FALSE;
  906.         }
  907.            if (useLimit > 0)
  908.            {
  909. // char buffer[10];
  910. UINT16 watchdog=0;
  911. dbg_printf(("You have %d out of %d views.  Ok to continue (y or n)? - Screen 4n", useCount, useLimit));
  912. g_DivxRentalsLeft = (UINT16)(useLimit - useCount);
  913. g_DivxRentalsTotal = useLimit;
  914. g_bUserAck = FALSE;
  915. g_bDivxRentanSelection =  FALSE;
  916. dbg_printf(("g_bUserAck: %sn", (g_bUserAck)? "TRUE":"FALSE"));
  917. ie_send(IE_UI_DIVX_RENTAL_CONFIRM);
  918. // here we should wait for UI response
  919. // Robin_0715_2004, merge changelist #24356
  920. while( !g_bUserAck && watchdog++ < 1000 )
  921. {
  922. usleep(100000UL); // wait
  923. }
  924. if(!g_bUserAck)
  925. ie_send(IE_UI_CLOSE_MENU); //inform UI close DRM menu
  926.            
  927. if ( g_bDivxRentanSelection == FALSE)
  928. {
  929. dbg_printf(("g_bDivxRentanSelection DONT PLAYn"));
  930. dbg_printf(("Playback canceled.n"));
  931. free (drmInfoHeader);
  932. return FALSE;
  933. }
  934. /* LOTAN               */
  935. dbg_printf(("g_bDivxRentanSelection PLAYn"));
  936. }           
  937. #ifdef AVI_MALLOC_SIZE_DOWN  
  938.            result = drmCommitPlayback( drmInfoHeader, dwClipStartAddr, *pdwOffset );
  939. #else
  940.            result = drmCommitPlayback( drmInfoHeader );
  941. #endif 
  942.            if (result != DRM_ERROR_NONE)
  943.            {
  944.                if (DRM_ERROR_NOT_AUTH_USER == result)
  945.                {
  946.                    ie_send(IE_UI_DIVX_MSG_AUTHORIZATION_ERROR);
  947.                    dbg_printf(("5 DRM Message 3 (not auth user), code %d - Screen 2n", result));
  948.                    free(drmInfoHeader);
  949.    gcs.pstate= PST_STOP;
  950.                    return FALSE;
  951.                }
  952.                
  953.                if (DRM_ERROR_RENTAL_EXPIRED == result)
  954.                {
  955.                    ie_send(IE_UI_DIVX_MSG_RENTAL_EXPIRED);
  956.                    dbg_printf(("6 DRM Message 2 (expired), code %d - Screen 3n", result));
  957.                    free (drmInfoHeader);
  958.    gcs.pstate= PST_STOP;
  959.                    return FALSE;
  960.                }
  961.                
  962.                ie_send(IE_UI_DIVX_MSG_AUTHORIZATION_ERROR);
  963.                dbg_printf(("7 DRM Message 1 (generic), code %d - Screen 2n", result));
  964.                free (drmInfoHeader);
  965.    gcs.pstate= PST_STOP;
  966.                return FALSE;
  967.            }
  968.            
  969.            sc_SetBytes(g_ScAviDrm_KeysOffset, 0, wDataSize, (BYTE *)drmInfoHeader);
  970.            
  971.            free (drmInfoHeader);
  972.            
  973.            /* Update the offset to reach the next list/chunk */
  974.            if (TRUE == pFourccInfo->bIsList)
  975.            {
  976.                (*pdwOffset) -= LIST_TYPE_FIELD_LENGTH; 
  977.            }
  978.            (*pdwOffset) += (DWORD)pFourccInfo->ulSize;
  979.            return TRUE;
  980.     }
  981.     else
  982. #endif // AVI_DRM_SUPPORT
  983.     {
  984.         dbg_printf(("no DRMn"));
  985.         _bAVIDrmOn = FALSE;
  986.     }
  987.     
  988.     return TRUE;
  989.     
  990.     
  991. }
  992. ///////////////////////////////////////////////////////////////////////////
  993. // Function name : _aquireAVIStreamsInfo
  994. // Purpose : Reads the 'strl' lists from the AVI file header.
  995. // Input Parameters : dwClipStartAddr - The start address to get the lists.
  996. //   dwOffset        - The offset to read the lists.
  997. // Return type : TRUE - if succeeded, FALSE otherwise.
  998. // Description : The function aquires the streams info by reading the
  999. //   'strl' lists from the AVI file header up to the 
  1000. //   maximum number of streams.
  1001. //   Currently, the function reads the first Video and Audio
  1002. //   streams only.
  1003. ///////////////////////////////////////////////////////////////////////////
  1004. static BOOL _aquireAVIStreamsInfo(DWORD dwClipStartAddr, DWORD dwOffset, DWORD *dwStrdOffset)
  1005. {
  1006. FOURCCInfo currFourcc;
  1007. DWORD dwOrginalOffset = dwOffset;
  1008. DWORD dwNextStrlOffset = 0UL;
  1009. BOOL  bVideoStreamFound = FALSE;
  1010. BOOL  bLookForDRM = FALSE;
  1011. UINT8 uiCounter = 0, uiAudioCnt = 0, uiSubtitleCnt = 0;
  1012. EFourCCType eFourCcType;
  1013. AVIStreamHeader aviStreamheader;
  1014. BitMapInfoHeader* pBitmapInfoHeader;
  1015. WaveFormat* pWaveFormatInfo;
  1016. LanguageCode *languageCode;
  1017. _mpeg4VideoStreamID = NO_STREAM;
  1018. _mpeg4AudioStreamID = NO_STREAM;
  1019. _mpeg4SubtitleStreamID = NO_STREAM;
  1020. // clear the audio stream info
  1021. memset((BYTE*)&_mpeg4AudioStreamInfo, 0, SIZE_OF_AUDIO_STREAM_INFO);
  1022. sc_SetBytes(SC_MPEG4_AUDIO_STREAM_INFO_ADDR,
  1023. 0,
  1024. SIZE_OF_AUDIO_STREAM_INFO,
  1025. (BYTE*)&_mpeg4AudioStreamInfo
  1026. );
  1027. uiCounter = 0;
  1028. _mpeg4SubtitleAvailableNum =0;
  1029. _mpeg4SubtitleInternalAvailableNum = 0;
  1030. _mpeg4AudioAvailableNum =0;
  1031. _mpeg4ChapterAvailableNum =0;
  1032. _mpeg4VideoScale = 1;
  1033. _mpeg4VideoRate = 30;// supposed
  1034. /* Reach the first video and audio streams */
  1035. while (TRUE)
  1036. {
  1037. /* Get the next FOURCC */
  1038. if (FALSE == _getNextFOURCC(dwClipStartAddr, dwOffset, &currFourcc))
  1039. {
  1040. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [1]n"));
  1041. return FALSE;
  1042. }
  1043. /* Reach the data zone of the list/chunk */
  1044. dwNextStrlOffset += (DWORD)currFourcc.ulSize;
  1045. dwNextStrlOffset += FOURCC_FIELD_LENGTH;
  1046. dwNextStrlOffset += SIZE_FIELD_LENGTH;
  1047. /* Checking for 'strl' chunk */
  1048. if (0 == strnicmp((LPSTR)currFourcc.aFOURCCBuff, AVI_STREAM_HEADER_START_ID, FOURCC_FIELD_LENGTH))
  1049. {
  1050. CHAR streamType[FOURCC_FIELD_LENGTH] = {0};
  1051. /* Reach the internal chunks */
  1052. dwOffset += FOURCC_FIELD_LENGTH;
  1053. dwOffset += SIZE_FIELD_LENGTH;
  1054. dwOffset += LIST_TYPE_FIELD_LENGTH;
  1055. /* Read 'strh' and 'strf' couple */
  1056. currFourcc.pData = (BYTE*)(&aviStreamheader);
  1057. if ( FALSE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_STREAM_HEADER_ID, &currFourcc, TRUE, sizeof(AVIStreamHeader)) )
  1058. {
  1059. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [2]n"));
  1060. return FALSE;
  1061. }
  1062. // Robin_1119_2004, display AVI audio/subtitle language
  1063. languageCode = &DIVX_LANGUAGE_CODE_LUT[aviStreamheader.wLanguage]; 
  1064. /* Determie what data 'strf' chunk contains */
  1065. convertFOURCCToString(aviStreamheader.fccType, streamType);
  1066. eFourCcType = StringToFourCC(streamType);
  1067. switch (eFourCcType)
  1068. {
  1069.             case (EVids):
  1070. if (FALSE == bVideoStreamFound)
  1071. {
  1072. /* Video Stream */
  1073. while (aviStreamheader.dwRate>1000000UL)
  1074. {
  1075. aviStreamheader.dwRate = aviStreamheader.dwRate / 10;
  1076. aviStreamheader.dwScale = (aviStreamheader.dwScale+5) / 10;
  1077. }
  1078. _mpeg4VideoScale = aviStreamheader.dwScale;
  1079. _mpeg4VideoRate = aviStreamheader.dwRate;
  1080. _mpeg4VideoLength = aviStreamheader.dwLength;
  1081. // _aviVideoStreamInfo._aviStreamType = AVI_VIDEO_STREAM;
  1082. bVideoStreamFound = TRUE;
  1083. bLookForDRM = TRUE;
  1084. // _mpeg4VideoStreamID = uiCounter; // Robin_0527_2004_B, fix the first stream not video stream
  1085. pBitmapInfoHeader = malloc(sizeof(BitMapInfoHeader));
  1086. if( NULL == pBitmapInfoHeader)
  1087. {
  1088. tr_printf(("FATAL: _aquireAVIStreamsInfo() Failed [3]: Malloc failed. Low system resource.n"));
  1089. return FALSE;
  1090. }
  1091. currFourcc.pData = (BYTE*)(pBitmapInfoHeader);
  1092. /* Read the 'strf' chunk according to the stream type */
  1093. if ( FALSE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_STREAM_FORMAT_ID, &currFourcc, TRUE, sizeof(BitMapInfoHeader)) )
  1094. {
  1095. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [4]n"));
  1096. free(pBitmapInfoHeader);
  1097. return FALSE;
  1098. }
  1099. // Robin_0809_2004, store the video header data
  1100. _mpeg4VideoHeight = (WORD)(pBitmapInfoHeader->lHeight & 0xFFFF);
  1101. _mpeg4VideoWidth = (WORD)(pBitmapInfoHeader->lWidth & 0xFFFF);
  1102. _mpeg4VideoCodec = determineDivXVersion(aviStreamheader.fccHandler,pBitmapInfoHeader->dwCompression);
  1103. free(pBitmapInfoHeader);
  1104. if (DIVX_UNKNOWN == _mpeg4VideoCodec)
  1105. {
  1106. continue;
  1107. }
  1108. if (currFourcc.ulSize > 0x28)
  1109. {
  1110. WORD wVideoHeaderSize;
  1111. WORD wOffset;
  1112. BOOL bFirst = TRUE;
  1113. BOOL bFoundStartCode = FALSE;
  1114. WORD wVideoHeaderCacheSize;
  1115. BYTE videoHeaderBuff[MPEG4_VIDEO_HEADER_CACHE_SIZE];
  1116. dbg_printf(("The video strf size more than 0x28 n"));
  1117. wVideoHeaderSize = (WORD)(currFourcc.ulSize - 0x28);
  1118. wOffset = 0;
  1119. _mpeg4VideoHeaderDataLength = 0;
  1120. while(wVideoHeaderSize > 0)
  1121. {
  1122. wVideoHeaderCacheSize = min(wVideoHeaderSize,MPEG4_VIDEO_HEADER_CACHE_SIZE); 
  1123. if (!AuxCache_GetBytes(dwClipStartAddr, (dwOffset - wVideoHeaderSize), (WORD)wVideoHeaderCacheSize, videoHeaderBuff))
  1124. {
  1125. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [5]n"));
  1126. return FALSE;
  1127. }
  1128. if(TRUE == (wVideoHeaderCacheSize & 0x1))
  1129. videoHeaderBuff[wVideoHeaderCacheSize] = 0;
  1130. wVideoHeaderCacheSize += (wVideoHeaderCacheSize & 0x1);
  1131. if (TRUE == bFirst)
  1132. {
  1133. int i;
  1134. for (i=0; i<(MPEG4_VIDEO_HEADER_CACHE_SIZE -4);i++)
  1135. {
  1136. if(videoHeaderBuff[i] != 0)
  1137. break;
  1138. if(videoHeaderBuff[i+1] != 0)
  1139. break;
  1140. if((videoHeaderBuff[i+2] != 0) && (videoHeaderBuff[i+2] != 1) )
  1141. break;
  1142. if(videoHeaderBuff[i+2] == 1)
  1143.                                     {
  1144. bFoundStartCode = TRUE;
  1145.                                      break;
  1146.                                  }
  1147. }
  1148. bFirst = FALSE;
  1149. }
  1150. if(FALSE ==bFoundStartCode)
  1151. {
  1152. dbg_printf(("Not found video start code n"));
  1153. break;
  1154. }
  1155. sc_SetBytes(SC_MPEG4_VIDEO_HEADER_DATA_ADDR,
  1156.        wOffset,
  1157.        wVideoHeaderCacheSize,
  1158.        (BYTE*)&videoHeaderBuff
  1159.        );
  1160. wVideoHeaderSize -= wVideoHeaderCacheSize;
  1161. wOffset += wVideoHeaderCacheSize;
  1162. if ((videoHeaderBuff[wVideoHeaderCacheSize-1] == 0) && 
  1163. (videoHeaderBuff[wVideoHeaderCacheSize-2] == 0) && 
  1164. (videoHeaderBuff[wVideoHeaderCacheSize-3] == 0) &&
  1165. (videoHeaderBuff[wVideoHeaderCacheSize-4] == 0))
  1166. break;
  1167. }
  1168. if (wOffset > MPEG4_VIDEO_HEADER_BUFFER_SIZE)
  1169. dbg_printf(("Video header data length more than 1024bytes! n"));
  1170. _mpeg4VideoHeaderDataLength = wOffset;
  1171. }
  1172. _mpeg4VideoStreamID = uiCounter; // Robin_0527_2004_B, fix the first stream not video stream
  1173. // Robin_0705_2004, restrict DivX image size not exceed 720x576
  1174. {
  1175. WORD wNumOfMB = ((_mpeg4VideoWidth + 15) / 16) * ((_mpeg4VideoHeight + 15) / 16);
  1176. if(wNumOfMB > 1620) // 720x576/256
  1177. {
  1178. dbg_printf(("Too large image size! Width: %d, Height: %dn",_mpeg4VideoWidth,_mpeg4VideoHeight));
  1179. return FALSE;
  1180. }
  1181. if(_mpeg4VideoWidth > 720)
  1182. {
  1183. dbg_printf(("Too large image width! Playback with artifacts! Width: %d, Height: %dn",_mpeg4VideoWidth,_mpeg4VideoHeight));
  1184. }
  1185. }
  1186. }
  1187. else
  1188. {
  1189. /* Subtitle Stream */
  1190. if (uiSubtitleCnt >= MAX_SUB_PER_CLIP)
  1191. {
  1192. tr_printf(("TOO MUCH SUBTITLE STREAMSn"));
  1193. }
  1194. else
  1195. {
  1196. _mpeg4SubtitleStreamID = uiCounter;
  1197. _mpeg4SubtitleType = INTERNAL_SUBP; // RB_TBD
  1198. memcpy(_mpeg4SubtitleLanguageCode,languageCode,3);
  1199. sc_SetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  1200.        (uiSubtitleCnt * SIZE_OF_SUBTITLE_STREAM_INFO),
  1201.        SIZE_OF_SUBTITLE_STREAM_INFO,
  1202.        (BYTE*)&_mpeg4SubtitleStreamInfo
  1203.        );
  1204.       
  1205. uiSubtitleCnt++;
  1206. _mpeg4SubtitleAvailableNum = uiSubtitleCnt;
  1207. _mpeg4SubtitleInternalAvailableNum = uiSubtitleCnt;
  1208. }
  1209. }
  1210. break;
  1211.             case (EAuds):
  1212. if (uiAudioCnt >= MAX_AUDS_PER_CLIP)
  1213. {
  1214. tr_printf(("TOO MUCH AUDIO STREAMSn"));
  1215. }
  1216. else
  1217. {
  1218. _mpeg4AudioScale = aviStreamheader.dwScale;
  1219. _mpeg4AudioRate = aviStreamheader.dwRate;
  1220. _mpeg4AudioLength = aviStreamheader.dwLength;
  1221.  // _aviAudioStreamInfo._aviStreamType = AVI_AUDIO_STREAM;
  1222. pWaveFormatInfo = (WaveFormat*)malloc(sizeof(WaveFormat));
  1223. if( NULL == pWaveFormatInfo)
  1224. {
  1225. tr_printf(("FATAL: _aquireAVIStreamsInfo() Failed [6]: Malloc failed. Low system resource.n"));
  1226. return FALSE;
  1227. }
  1228. currFourcc.pData = (BYTE*)pWaveFormatInfo;
  1229. /* Read the 'strf' chunk according to the stream type */
  1230. if ( FALSE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_STREAM_FORMAT_ID, &currFourcc, TRUE, sizeof(WaveFormat)) )
  1231. {
  1232. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [7]n"));
  1233. free(pWaveFormatInfo);
  1234. return FALSE;
  1235. }
  1236. _mpeg4AudioSamplesPerSec = pWaveFormatInfo->wave.dwSamplesPerSec;
  1237. _mpeg4AudioCodec = determineAudioCodec(0UL, pWaveFormatInfo->wave.wFormatTag, FALSE);
  1238. if (AUDIO_UNKNOWN == _mpeg4AudioCodec)
  1239. {
  1240. free(pWaveFormatInfo);
  1241. break;
  1242. }
  1243. #ifdef D_ENABLE_ADPCM_SUPPORT
  1244. if ((ADPCM == _mpeg4AudioCodec) ||(PCM == _mpeg4AudioCodec))
  1245. {
  1246. // _mpeg4AudioChannels_ADPCM  = pWaveFormatInfo->wave.wChannels;
  1247. _mpeg4AudioSamplesPerBlock_ADPCM = pWaveFormatInfo->adpcm.wSamplesPerBlock;
  1248. _mpeg4AudioBlockAlign_ADPCM  = pWaveFormatInfo->wave.wBlockAlign;
  1249. }
  1250. if (PCM == _mpeg4AudioCodec)
  1251. _mpeg4AudioBitsPerSample_ADPCM  = (8 * pWaveFormatInfo->wave.wBlockAlign) / pWaveFormatInfo->wave.wChannels;
  1252. else if (ADPCM == _mpeg4AudioCodec)
  1253. _mpeg4AudioBitsPerSample_ADPCM = pWaveFormatInfo->wave.wBitsPerSample;
  1254. #endif
  1255. #ifdef D_ENABLE_DIVX_WMA_SUPPORT
  1256. if (WMA == _mpeg4AudioCodec)
  1257. {
  1258. // _mpeg4AudioChannels_WMA = pWaveFormatInfo->wave.wChannels;
  1259. _mpeg4AudioBlockAlign_WMA = pWaveFormatInfo->wave.wBlockAlign;
  1260. _mpeg4AudioEncoderOptions_WMA = pWaveFormatInfo->wma.wEncoderOptions;
  1261. }
  1262. #endif
  1263. _mpeg4AudioChannels  = pWaveFormatInfo->wave.wChannels;
  1264. _mpeg4AudioAvgBytesPerSec = pWaveFormatInfo->wave.dwAvgBytesPerSec;
  1265. _mpeg4AudioStreamID = uiCounter;
  1266. memcpy(_mpeg4AudioLanguageCode,languageCode,3);
  1267. sc_SetBytes(SC_MPEG4_AUDIO_STREAM_INFO_ADDR,
  1268.        (uiAudioCnt * SIZE_OF_AUDIO_STREAM_INFO),
  1269.        SIZE_OF_AUDIO_STREAM_INFO,
  1270.        (BYTE*)&_mpeg4AudioStreamInfo
  1271.        );
  1272. uiAudioCnt++;
  1273. _mpeg4AudioAvailableNum = uiAudioCnt;
  1274. free(pWaveFormatInfo);
  1275. }
  1276. break;
  1277. // Robin_0117_2005, support AVI internal text subtitle
  1278. #if 0
  1279. case(ETxts):
  1280. /* Subtitle Stream (Text) */
  1281. if (uiSubtitleCnt >= MAX_SUB_PER_CLIP)
  1282. {
  1283. tr_printf(("TOO MUCH SUBTITLE STREAMSn"));
  1284. }
  1285. else
  1286. {
  1287. _mpeg4SubtitleStreamID = uiCounter;
  1288. _mpeg4SubtitleType = AVI_INTERNAL_TEXT; // RB_TBD
  1289. memcpy(_mpeg4SubtitleLanguageCode,languageCode,3);
  1290. sc_SetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  1291.        (uiSubtitleCnt * SIZE_OF_SUBTITLE_STREAM_INFO),
  1292.        SIZE_OF_SUBTITLE_STREAM_INFO,
  1293.        (BYTE*)&_mpeg4SubtitleStreamInfo
  1294.        );
  1295.       
  1296. uiSubtitleCnt++;
  1297. _mpeg4SubtitleAvailableNum = uiSubtitleCnt;
  1298. }
  1299. break;
  1300. #endif
  1301.                     
  1302. }
  1303. while (dwOffset < (dwNextStrlOffset + dwOrginalOffset))
  1304. {
  1305. // Get the next FOURCC 
  1306. if (FALSE == _getNextFOURCC(dwClipStartAddr, dwOffset, &currFourcc))
  1307. {
  1308. dbg_printf(("FATAL: _aquireAVIStreamsInfo() Failed [6]n"));
  1309. return FALSE;
  1310. }
  1311. if (0 == strnicmp((LPSTR)currFourcc.aFOURCCBuff, AVI_STREAM_HEADER_DATA_ID, FOURCC_FIELD_LENGTH)) // "strd"
  1312. {
  1313. // DRM data
  1314. if ( bLookForDRM )
  1315. {
  1316. *dwStrdOffset = dwOffset;
  1317. bLookForDRM = FALSE;
  1318. }
  1319. }
  1320. dwOffset += FOURCC_FIELD_LENGTH;
  1321. dwOffset += SIZE_FIELD_LENGTH; 
  1322. dwOffset += currFourcc.ulSize;
  1323. }
  1324. uiCounter++;
  1325. }
  1326. else
  1327. {
  1328. /* No more 'strl' chunks exist, finish */
  1329. break;
  1330. }
  1331. /* Skip to the next 'strl' chunk */
  1332. dwOffset = dwNextStrlOffset + dwOrginalOffset;
  1333. }
  1334. return TRUE;
  1335. }
  1336. ///////////////////////////////////////////////////////////////////////////
  1337. // Function name : _aquireAVIInfo
  1338. // Purpose : Reads all the needed data from the AVI file header.
  1339. // Input Parameters : dwClipStartAddr - The start address of the AVI file.
  1340. // Return type : TRUE - if succeeded, FALSE otherwise.
  1341. // Description : The function reads all the data needed for managing
  1342. //   of the playback including parameters needed by the
  1343. //   DVP.
  1344. ///////////////////////////////////////////////////////////////////////////
  1345. static BOOL _acquireAVIInfo(DWORD dwClipStartAddr)
  1346. {
  1347. FOURCCInfo currFourcc;
  1348. DWORD dwOffset = AVI_HEADER_OFFSET;
  1349. AVIMainHeader* pAviMainHeader;
  1350. DWORD dwStrdOffset  = 0;
  1351. dbg_printf(("Aquiring AVI file info...n"));
  1352. /* Verifying that the RIFF file is an AVI one */
  1353. if (!AuxCache_GetBytes(dwClipStartAddr, AVI_ID_OFFSET, (WORD)FOURCC_FIELD_LENGTH, currFourcc.aFOURCCBuff))
  1354. {
  1355. dbg_printf(("FATAL: _acquireAVIInfo() Failed [1]n"));
  1356. return FALSE;
  1357. }
  1358. if (0 == strnicmp((LPSTR)(currFourcc.aFOURCCBuff), AVI_FILE_ID, FOURCC_FIELD_LENGTH)) 
  1359. {
  1360. dbg_printf(("AVI FOURCC detected...n"));
  1361. }
  1362. else
  1363. {
  1364. tr_printf(("FATAL: AVI FOURCC was not detectedn"));
  1365. return FALSE;
  1366. }
  1367. /* Reading the AVI file header */
  1368. while (TRUE)
  1369. {
  1370. if (FALSE == _getNextFOURCC(dwClipStartAddr, dwOffset, &currFourcc))
  1371. {
  1372. dbg_printf(("FATAL: _acquireAVIInfo() Failed [2]n"));
  1373. return FALSE;
  1374. }
  1375. /* Checking if we reached the start of the header */
  1376. else if (0 == strnicmp((LPSTR)currFourcc.aFOURCCBuff, AVI_HEADER_START_ID, FOURCC_FIELD_LENGTH))
  1377. {
  1378. /* Updating offset to reach the next chunks */
  1379. dwOffset += FOURCC_FIELD_LENGTH;
  1380. dwOffset += SIZE_FIELD_LENGTH; 
  1381. dwOffset += LIST_TYPE_FIELD_LENGTH; 
  1382. break;
  1383. }
  1384. /* Skipping the list/chunk */
  1385. dwOffset += FOURCC_FIELD_LENGTH;
  1386. dwOffset += SIZE_FIELD_LENGTH;
  1387. dwOffset += (DWORD)currFourcc.ulSize;
  1388. }
  1389. /* Read the 'avih' chunk */
  1390. pAviMainHeader = malloc(sizeof(AVIMainHeader));
  1391. if( NULL == pAviMainHeader)
  1392. {
  1393. tr_printf(("FATAL: _acquireAVIInfo() Failed [3]: Malloc failed. Low system resource.n"));
  1394. return FALSE;
  1395. }
  1396. currFourcc.pData = (BYTE*)(pAviMainHeader);
  1397. if ( FALSE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_MAIN_HEADER_ID, &currFourcc, TRUE, sizeof(AVIMainHeader)) )
  1398. {
  1399. dbg_printf(("FATAL: _acquireAVIInfo() Failed [4]n"));
  1400. free(pAviMainHeader);
  1401. return FALSE;
  1402. }
  1403. _bAVIHasIndex = (pAviMainHeader->dwFlags & AVI_HAS_INDEX) ? TRUE : FALSE;
  1404. free(pAviMainHeader);
  1405. /* Read the streams info */
  1406. if (FALSE == _aquireAVIStreamsInfo(dwClipStartAddr, dwOffset, &dwStrdOffset))
  1407. {
  1408. dbg_printf(("FATAL: _acquireAVIInfo() Failed [5]n"));
  1409. return FALSE;
  1410. }
  1411. if (dwStrdOffset != 0)
  1412. {
  1413. if ( FALSE == _searchForDrmFOURCC(dwClipStartAddr, &dwStrdOffset, &currFourcc ))
  1414. {
  1415. dbg_printf(("clip fail becuase of DRMn"));
  1416. return FALSE;
  1417. }
  1418. }
  1419. /* Check if the 'INFO' list is avaiable */
  1420. /* dwOffset = AVI_HEADER_OFFSET;
  1421. if ( TRUE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_INFO_LIST_ID, &currFourcc, FALSE, 0) )
  1422. {
  1423. /* Read ISFT chunk from INFO list */
  1424. /* Update the offset to reach the info list data */
  1425. /* dwOffset -= (DWORD)currFourcc.ulSize;
  1426. dwOffset += FOURCC_FIELD_LENGTH;
  1427. if ( TRUE == _searchForFOURCC(dwClipStartAddr, &dwOffset, AVI_ISET_CHUNK_ID, &currFourcc, FALSE, 0) )
  1428. {
  1429. BYTE aISFTBuff[VIRTUALDUB_ID_LENGTH];
  1430. /* update the offset to reach "ISFT" chunk data*/
  1431. /* dwOffset -= (DWORD)currFourcc.ulSize;
  1432. if (discGetBytes(dwClipStartAddr, dwOffset, (WORD)VIRTUALDUB_ID_LENGTH, aISFTBuff))
  1433. {
  1434. if ( (0 == strnicmp((LPSTR)aISFTBuff, AVI_NANDUB_ID, NANDUB_ID_LENGTH)) ||
  1435.  (0 == strnicmp((LPSTR)aISFTBuff, AVI_VIRTUALDUB_ID, VIRTUALDUB_ID_LENGTH)) )
  1436. {
  1437. dbg_printf(("Nandub is detected....n"));
  1438. _aviFileInfo.bIsNandub = TRUE;
  1439. }
  1440. }
  1441. }
  1442. }*/
  1443. return TRUE;
  1444. }
  1445. ///////////////////////////////////////////////////////////////////////////
  1446. // Function name : _getIdxEntry
  1447. // Purpose : Retuns the next entry in the index table.
  1448. // Input Parameters : dwClipStartAddr - The start address to get the entries.
  1449. //   dwOffset        - The offset to read the entries.
  1450. // Return type : TRUE if the operation succeeded, FALSE otherwise.
  1451. // Description : The function reads several idx entries and returns the
  1452. //   first one. Upon calling of the function, if the
  1453. //   entry already exists from previous reading then it is
  1454. //   returned, otherwise, another segment of entries is read.
  1455. //   The caching of the entries is used for speeding up 
  1456. //   idx processing.
  1457. ///////////////////////////////////////////////////////////////////////////
  1458. static BOOL _getIdxEntry(DWORD dwClipStartAddr, DWORD dwOffset, DWORD ulIdxSize, 
  1459.  AVIIndexEntry* pCurrEntry, BOOL bFirstTime, UINT32 ulLeftIdxSize)
  1460. {
  1461. if (NULL == _idxEntries)
  1462. return FALSE;
  1463. /* Check whether the entry already exist in the cache */
  1464. if (NUM_OF_IDX_ENTRIES_CACHE == _uiAVICurrCachedIdxEntry)
  1465. {
  1466. /* Read the next segment of idx entries */
  1467. /* Check if the left size is lower than the entries cache size */
  1468. if (ulLeftIdxSize < (WORD)(NUM_OF_IDX_ENTRIES_CACHE*sizeof(AVIIndexEntry)))
  1469. {
  1470. if (!AuxCache_GetFile(dwClipStartAddr, dwOffset, (WORD)ulLeftIdxSize,
  1471.   ulIdxSize, bFirstTime, (BYTE*)_idxEntries))
  1472. {
  1473. dbg_printf(("FATAL: _cacheIdxEntries() Failed[1]n"));
  1474. return FALSE;
  1475. }
  1476. }
  1477. else 
  1478. {
  1479. if (!AuxCache_GetFile(dwClipStartAddr, dwOffset, (WORD)(NUM_OF_IDX_ENTRIES_CACHE*sizeof(AVIIndexEntry)), 
  1480.   ulIdxSize, bFirstTime, (BYTE*)_idxEntries))
  1481. {
  1482. dbg_printf(("FATAL: _cacheIdxEntries() Failed[2]n"));
  1483. return FALSE;
  1484. }
  1485. }
  1486. _uiAVICurrCachedIdxEntry = 0;
  1487. }
  1488. *pCurrEntry = _idxEntries[_uiAVICurrCachedIdxEntry++];
  1489. return TRUE;
  1490. }
  1491. ///////////////////////////////////////////////////////////////////////////
  1492. // Function name : _saveIdxEntry
  1493. // Purpose : Saving an idx entry in the memory.
  1494. // Input Parameters : ulVidFrameNumber   - Video frame number to save.
  1495. //   dwVidChunkOffset   - Video chunk offset.
  1496. //   dwVidChunkSize     - Video chunk size.
  1497. //   dwAudioChunkOffset - Corresponding audio chunk offset.
  1498. //   dwAudioChunkDelta  - Offset within the audio chunk.
  1499. //   uiSkipVideoChunks     - Video frames between the audio
  1500. //    chunk and the appropiate video one.
  1501. //   uiSkipAudioChunks - Audio chunks to skip
  1502. // Return type : TRUE if the operation succeeded, FALSE otherwise.
  1503. ///////////////////////////////////////////////////////////////////////////
  1504. // <<< Robin_1003_2004_D
  1505. static BOOL _saveIdxEntry(UINT32 ulVidFrameNumber, DWORD dwVidChunkOffset, DWORD dwVidChunkSize,
  1506.   DWORD dwAudioChunkOffset, DWORD dwAudioChunkDelta, UINT16 uiSkipVideoChunks, UINT16 uiSkipAudioChunks)
  1507. {
  1508. IndexEntry indexEntry;
  1509. /* Check whether we are out of memory */
  1510. if (_uiMPEG4NextIndexEntry >= MAX_NUMBER_OF_IDX_ENTRIES)
  1511. {
  1512. dbg_printf(("FATAL: _saveIdxEntry() Failedn"));
  1513. return FALSE;
  1514. }
  1515. if ( (_lAVIPreviousFrameNumber == -1) || 
  1516.  (1000*(ulVidFrameNumber - _lAVIPreviousFrameNumber) >= _aviIdxIDiff) )
  1517. {
  1518. indexEntry.ulVideoFrameNumber = ulVidFrameNumber;
  1519. indexEntry.ulVideoChunkOffset = dwVidChunkOffset;
  1520. indexEntry.ulVideoChunkSize = dwVidChunkSize;
  1521. indexEntry.ulAudioChunkOffset = dwAudioChunkOffset;
  1522. indexEntry.ulAudioChunkDelta = dwAudioChunkDelta;
  1523. indexEntry.uiSkipVideoChunks = uiSkipVideoChunks;
  1524. indexEntry.uiSkipAudioChunks = uiSkipAudioChunks;
  1525. wai_sem(SEM_DRAM_ID);
  1526. I49_WriteDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (((DWORD)(_uiMPEG4NextIndexEntry))*sizeof(IndexEntry))), // Robin_1119_2004_B, avoid the overflow
  1527.     (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  1528. sig_sem(SEM_DRAM_ID);
  1529. _lAVIPreviousFrameNumber = ulVidFrameNumber;
  1530. _uiMPEG4NextIndexEntry++;
  1531. }
  1532. return TRUE;
  1533. }
  1534. ///////////////////////////////////////////////////////////////////////////
  1535. // Function name : _aquireAndProcessIdx
  1536. // Purpose : Reading and processing the index table.
  1537. // Input Parameters : dwClipStartAddr  - The start address to get the entries.
  1538. //   uiVideoStreamNum - The video stream number to process.
  1539. //   uiAudioStreamNum - The audio stream number to process.
  1540. // Return type : TRUE if the operation succeeded, FALSE otherwise.
  1541. // Description : The function reads the idx entries, process them and 
  1542. //   saves them in the memory to be used for trick modes.
  1543. //   The function aquires the idx only once.
  1544. ///////////////////////////////////////////////////////////////////////////
  1545. #ifdef V882_FLASH_CARD
  1546. #define USE_HEAP //todo: change to USE_SC
  1547. #endif//V882_FLASH_CARD
  1548. static BOOL _aquireAndProcessIdx(DWORD dwClipStartAddr,
  1549.  UINT8 uiVideoStreamNum, UINT8 uiAudioStreamNum, DWORD* dwFirstChunkOffset)
  1550. {
  1551. int iAudioReminderCounter100 = 100;
  1552. int iAudioReminderCounter10000 = 100;
  1553. int iVideoReminderCounter100 = 100;
  1554. int iVideoReminderCounter10000 = 100;
  1555. DWORD  dwIdxOffset = AVI_HEADER_OFFSET;
  1556. FOURCCInfo idxList;
  1557. UINT32 ulLeftSize;
  1558. AVIIndexEntry currEntry;
  1559. UINT32 ulCurrFrameNumber = 0;
  1560. UINT32 ulFramesBeforeAudioCh = 0;
  1561. BOOL bIsFirstAudioChunk = TRUE;
  1562. DWORD dwCurrAudioChunkDelta = 0;
  1563. DWORD dwCurrAudioChunkOffset = 0;
  1564. DWORD dwCurrAudioChunkSize = 0;
  1565. DWORD dwAudioSkip;
  1566. DWORD dwAudioSkipRemider100;
  1567. DWORD dwAudioSkipRemider10000;
  1568. DWORD dwVideoSkip;
  1569. DWORD dwVideoSkipRemider100;
  1570. DWORD dwVideoSkipRemider10000;
  1571. UINT32 ulCurrVideoTime = 0;
  1572. UINT32 ulCurrAudioTime =0;
  1573. BOOL  bFirstEntry;
  1574. DWORD dwIdxClipStartAddr;
  1575. DWORD ulLeftSizeSave;
  1576. BOOL  bDrmFound = FALSE;
  1577. #ifndef USE_HEAP
  1578. IdxFIFOElement idxFIFO[FIFO_LEN];
  1579. #else
  1580. // WORD idxFIFO;
  1581. IdxFIFOElement* idxFIFO;
  1582. #endif
  1583. UINT16 fifoHead, fifoTail;
  1584. // <<< Robin_0907_2004_B
  1585. BOOL bIdxFifoOverFlow = FALSE;
  1586. DWORD dwIdxOffsetStore;
  1587. UINT32 ulLeftSizeStore;
  1588. // >>> Robin_0907_2004_B
  1589. DWORD dwTotalAudioLength;
  1590. DWORD dwTotalAudioCount = 0UL;
  1591. #if defined(_DEBUG) || defined(D_RELEASE_TRACE_ENABLED) // ZKR GL051004
  1592. UINT32 ulStartTime = gen_timer()/1000UL;
  1593. #endif
  1594. #ifdef USE_HEAP
  1595. _freeStorageInterfaceAndIndex();
  1596. #endif
  1597. /* Check if the idx processing already has failed */
  1598. if ((FALSE == _bMPEG4TrickModeOn) && (_uiMPEG4NextIndexEntry == 0))
  1599. {
  1600. return FALSE;
  1601. }
  1602. /* Check if the index exists */
  1603. if (FALSE == _bAVIHasIndex) 
  1604. {
  1605. tr_printf(("WARNING: _aquireAndProcessIdx() Failed - Index does not existn"));
  1606. _bMPEG4TrickModeOn = FALSE;
  1607. _dwMPEG4ProcessingEndAddr = MPEG4_PROCESSING_BUFF_ADDR;
  1608. return FALSE;
  1609. }
  1610. /* Check if the index was already processed */
  1611. if (TRUE == _bMPEG4IsIndexProcessed)
  1612. {
  1613. return TRUE;
  1614. }
  1615. _uiMPEG4ProcessedFileAddr = dwClipStartAddr;
  1616. dbg_printf(("AVI Clip: Aquiring Index Table Infon"));
  1617. _dwMPEG4ProcessingEndAddr = MPEG4_PROCESSING_BUFF_ADDR;
  1618. _uiMPEG4NextIndexEntry = 0;
  1619. _uiAVICurrCachedIdxEntry = NUM_OF_IDX_ENTRIES_CACHE;
  1620. /* Reaching the 'idx1' FOURCC */
  1621. if (FALSE == _searchForFOURCC(dwClipStartAddr, &dwIdxOffset, AVI_IDX_CHUNK_ID, &idxList, FALSE, 0))
  1622. {
  1623. dbg_printf(("FATAL: _aquireAndProcessIdx() Failed [1]n"));
  1624. _bMPEG4TrickModeOn = FALSE;
  1625. return FALSE;
  1626. }
  1627. dwIdxOffset -= (DWORD)idxList.ulSize;
  1628. ulLeftSize = idxList.ulSize;
  1629. dwIdxClipStartAddr = dwClipStartAddr + (dwIdxOffset/2048UL);
  1630. dwIdxOffset = dwIdxOffset % 2048UL;
  1631. /* Check if the file doesn't contain audio stream */
  1632. if (NO_STREAM == _mpeg4AudioStreamID)
  1633. {
  1634. /* Signal to the idx processing not to wait for audio chunk at the beginning */
  1635. bIsFirstAudioChunk = FALSE;
  1636. }
  1637. if (NO_STREAM != _mpeg4AudioStreamID)
  1638. {
  1639. if ( (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE) /*&&
  1640.  (TRUE == _aviFileInfo.bIsNandub)*/ )
  1641. {
  1642. /* VBR audio stream */
  1643. UINT32 ulDelta;
  1644. tr_printf(("Detected VBR audio stream...n"));
  1645. // <<< Robin_2004_0519_A, change the index processing when VBR audio
  1646. // dwVideoSkip mean the time of one video frame, in unit of 0.1ms
  1647. dwVideoSkip = (10000UL * _mpeg4VideoScale) /
  1648. _mpeg4VideoRate;
  1649. ulDelta = (10000UL * _mpeg4VideoScale) -
  1650.  (dwVideoSkip * _mpeg4VideoRate);
  1651. // Robin_0201_2005, avoid the calculate overflow
  1652. if (((10000UL*ulDelta)/10000UL) == ulDelta)
  1653. {
  1654. ulDelta = (10000UL*ulDelta) / _mpeg4VideoRate;
  1655. }
  1656. else if (((5000UL*ulDelta)/5000UL) == ulDelta)
  1657. {
  1658. ulDelta = ((5000UL*ulDelta) / _mpeg4VideoRate) * 2;
  1659. }
  1660. else if (((1000UL*ulDelta)/1000UL) == ulDelta)
  1661. {
  1662. ulDelta = ((1000UL*ulDelta) / _mpeg4VideoRate) * 10;
  1663. }
  1664. else if (((100UL*ulDelta)/100UL) == ulDelta)
  1665. {
  1666. ulDelta = ((100UL*ulDelta) / _mpeg4VideoRate) * 100;
  1667. }
  1668. dwVideoSkipRemider100 = ulDelta / 100;
  1669. dwVideoSkipRemider10000 = ulDelta % 100;
  1670. dwAudioSkip = (10000UL * AVI_VBR_AUD_STREAM_SCALE) / _mpeg4AudioRate;
  1671. ulDelta = (10000UL * AVI_VBR_AUD_STREAM_SCALE) -
  1672. (dwAudioSkip * _mpeg4AudioRate);
  1673. // Robin_0201_2005, avoid the calculate overflow
  1674. if (((10000UL*ulDelta)/10000UL) == ulDelta)
  1675. {
  1676. ulDelta = (10000UL*ulDelta) / _mpeg4AudioRate;
  1677. }
  1678. else if (((5000UL*ulDelta)/5000UL) == ulDelta)
  1679. {
  1680. ulDelta = ((5000UL*ulDelta) / _mpeg4AudioRate) * 2;
  1681. }
  1682. else if (((1000UL*ulDelta)/1000UL) == ulDelta)
  1683. {
  1684. ulDelta = ((1000UL*ulDelta) / _mpeg4AudioRate) * 10;
  1685. }
  1686. else if (((100UL*ulDelta)/100UL) == ulDelta)
  1687. {
  1688. ulDelta = ((100UL*ulDelta) / _mpeg4AudioRate) * 100;
  1689. }
  1690. dwAudioSkipRemider100 = ulDelta / 100;
  1691. dwAudioSkipRemider10000 = ulDelta % 100;
  1692. dbg_printf(("IDX: audio skip: %ld, reminder100: %ld, reminder10000: %ldn", 
  1693.         dwAudioSkip, dwAudioSkipRemider100, dwAudioSkipRemider10000));
  1694. dbg_printf(("IDX: video skip: %ld, reminder100: %ld, reminder10000: %ldn", 
  1695.         dwVideoSkip, dwVideoSkipRemider100, dwVideoSkipRemider10000));
  1696. // >>> Robin_2004_0519_A
  1697. }
  1698. else
  1699. {
  1700. UINT32 ulDelta;
  1701. UINT16 uVideoTotalPlaybackTime;
  1702. UINT16 uAudioTotalPlaybackTime;
  1703. /* CBR audio stream
  1704.  * Warning: The ahead order of computation is very important to prevent overflow and
  1705.  * for the computation's accurecy.
  1706.  */
  1707. if (0 == _mpeg4AudioLength)
  1708. {
  1709. DWORD dwAudRate = _mpeg4AudioRate;
  1710. DWORD dwFileLength = (10*_mpeg4VideoLength *
  1711.    _mpeg4VideoScale) /
  1712.    _mpeg4VideoRate;
  1713. _mpeg4AudioLength = dwAudRate * dwFileLength/10;
  1714. }
  1715. // Robin_0607_2004_A, handle some special divx with video/audio total playback time not equal (absdiff > 1) 
  1716. uVideoTotalPlaybackTime = caclTimeOfFrame(_mpeg4VideoLength, _mpeg4VideoRate, _mpeg4VideoScale);
  1717. if (0 != _mpeg4AudioAvgBytesPerSec)
  1718. uAudioTotalPlaybackTime =  (UINT16)((_mpeg4AudioLength * _mpeg4AudioScale) / _mpeg4AudioAvgBytesPerSec);
  1719. // <<< Robin_0930_2004, avoid the calculation overflow
  1720. if(((ABS_DIFF(uVideoTotalPlaybackTime, uAudioTotalPlaybackTime) > 1) && 0 != _mpeg4AudioAvgBytesPerSec) 
  1721. || (0UL == (_mpeg4AudioAvgBytesPerSec * _mpeg4VideoScale) % _mpeg4VideoRate)) // for some special divx clips
  1722. {
  1723. dwAudioSkip = (_mpeg4AudioAvgBytesPerSec * _mpeg4VideoScale) / _mpeg4VideoRate;
  1724. ulDelta = (_mpeg4AudioAvgBytesPerSec * _mpeg4VideoScale) - (_mpeg4VideoRate * dwAudioSkip);
  1725. if (((10000UL*ulDelta)/10000UL) == ulDelta)
  1726. ulDelta = (10000UL*ulDelta) / _mpeg4VideoRate;
  1727. else if (((5000UL*ulDelta)/5000UL) == ulDelta)
  1728. ulDelta = ((5000UL*ulDelta) / _mpeg4VideoRate) * 2;
  1729. else if (((1000UL*ulDelta)/1000UL) == ulDelta)
  1730. ulDelta = ((1000UL*ulDelta) / _mpeg4VideoRate) * 10;
  1731. else
  1732. ulDelta = ((100UL*ulDelta) / _mpeg4VideoRate) * 100;
  1733. }
  1734. else
  1735. {
  1736. dwAudioSkip = (_mpeg4AudioLength * _mpeg4AudioScale) / _mpeg4VideoLength;
  1737. ulDelta =  (_mpeg4AudioLength * _mpeg4AudioScale) - (_mpeg4VideoLength * dwAudioSkip);
  1738. if (((10000UL*ulDelta)/10000UL) == ulDelta)
  1739. ulDelta = (10000UL*ulDelta) / _mpeg4VideoLength;
  1740. else if (((5000UL*ulDelta)/5000UL) == ulDelta)
  1741. ulDelta = ((5000UL*ulDelta) / _mpeg4VideoLength) * 2;
  1742. else if (((1000UL*ulDelta)/1000UL) == ulDelta)
  1743. ulDelta = ((1000UL*ulDelta) / _mpeg4VideoLength) * 10;
  1744. else
  1745. ulDelta = ((100UL*ulDelta) /_mpeg4VideoLength) * 100;
  1746. }
  1747. dwAudioSkipRemider100 = ulDelta / 100;
  1748. dwAudioSkipRemider10000 = ulDelta % 100;
  1749. dbg_printf(("IDX: audio skip: %ld, reminder100: %ld, reminder10000: %ldn", 
  1750.         dwAudioSkip, dwAudioSkipRemider100, dwAudioSkipRemider10000));
  1751. }
  1752. }
  1753. bFirstEntry = TRUE;
  1754. ulLeftSizeSave = ulLeftSize;
  1755. fifoHead = fifoTail = 0;
  1756. /* Determine the difference between the saved I-frames according to the AVI file */
  1757. #ifdef SDRAM_2X16MBITS
  1758. if (_mpeg4VideoLength >= IDX_LONG_I_DIFF_THRESHOLD)
  1759. {
  1760. _aviIdxIDiff = IDX_TABLE_LONG_TIME_DIFFERANCE * 
  1761.    (_mpeg4VideoRate /
  1762. _mpeg4VideoScale);
  1763. dbg_printf(("IDX: Diff between I frames is: %d msecn", IDX_TABLE_LONG_TIME_DIFFERANCE));
  1764. }
  1765. else
  1766. {
  1767. _aviIdxIDiff = IDX_TABLE_SHORT_TIME_DIFFERANCE * 
  1768.    (_mpeg4VideoRate /
  1769. _mpeg4VideoScale);
  1770. dbg_printf(("IDX: Diff between I frames is: %d msecn", IDX_TABLE_SHORT_TIME_DIFFERANCE));
  1771. }
  1772. #else
  1773. _aviIdxIDiff = IDX_TABLE_SHORT_TIME_DIFFERANCE * (UINT16)(_mpeg4VideoRate / _mpeg4VideoScale);
  1774. dbg_printf(("IDX: Diff between I frames is: %d msecn", IDX_TABLE_SHORT_TIME_DIFFERANCE));
  1775. #endif // SDRAM_2X16MBITS
  1776. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  1777. if(IS_PLAYING_CARD)
  1778. _idxEntries = FCU_IDX_ENTRIES_START;
  1779. else
  1780. #endif    
  1781. _idxEntries = (BYTE*) malloc(NUM_OF_IDX_ENTRIES_CACHE*sizeof(AVIIndexEntry));
  1782. if (NULL == _idxEntries)
  1783. {
  1784. tr_printf(("FATAL: couldn't allocate memory for idx caching...n"));
  1785. _bMPEG4TrickModeOn = FALSE;
  1786. return FALSE;
  1787. }
  1788. // Robin_1003_2004_D
  1789. _bAVIVideoBeforeAudio = FALSE;
  1790. // Robin_1003_2004_C
  1791. bVideoAudioInterleave = TRUE;
  1792. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  1793. dwTotalAudioLength = _mpeg4AudioLength;
  1794. else
  1795. dwTotalAudioLength = _mpeg4AudioLength * _mpeg4AudioScale;
  1796. /* Reading the index entries and saving the I frames only */
  1797. ulLeftSize = ((ulLeftSize+15) >> 4) << 4; // ensure "ulLeftSize" in unit of 16 bytes // Robin_0809_2004
  1798. // <<< Robin_0907_2004_B
  1799. dwIdxOffsetStore = dwIdxOffset;
  1800. ulLeftSizeStore = ulLeftSize;
  1801. #ifdef USE_HEAP
  1802. // idxFIFO = sc_Malloc((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4);
  1803.   idxFIFO = malloc(FIFO_LEN*sizeof(IdxFIFOElement));
  1804.    if(NULL_HANDLE == idxFIFO){
  1805.     printf("AVI.c, Fatal: low system resource, idxFIFO.n");
  1806.       return FALSE;
  1807.    }
  1808. #endif
  1809. // >>> Robin_0907_2004_B
  1810. while (ulLeftSize > 0UL)
  1811. {
  1812. DWORD dwSizeOfCurrEntry;
  1813. UINT8 uiStreamNumber;
  1814. if (FALSE == _getIdxEntry(dwIdxClipStartAddr, dwIdxOffset, ulLeftSizeSave, 
  1815.   &currEntry, bFirstEntry, ulLeftSize))
  1816. {
  1817. dbg_printf(("FATAL: _aquireAndProcessIdx() Failed [2]n"));
  1818. if (ulLeftSize < 4096UL) // can't get last two sectors
  1819. break;
  1820. AuxCache_GetFileTerminate();
  1821. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  1822. if (!IS_PLAYING_CARD)
  1823. #endif
  1824. free(_idxEntries);
  1825. _idxEntries = NULL;
  1826. _bMPEG4TrickModeOn = FALSE;
  1827. #ifdef USE_HEAP
  1828. //    sc_Free(idxFIFO, ((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4));
  1829.         free(idxFIFO);
  1830. #endif
  1831. return FALSE;
  1832. }
  1833. if (TRUE == bFirstEntry)
  1834. {
  1835. *dwFirstChunkOffset = currEntry.dwChunkOffset;
  1836. bFirstEntry = FALSE;
  1837. }
  1838. dwSizeOfCurrEntry = (DWORD)sizeof(currEntry);
  1839. ulLeftSize -= (UINT32)dwSizeOfCurrEntry;
  1840. dwIdxOffset += dwSizeOfCurrEntry;
  1841. if (0 == currEntry.dwChunkOffset) // index corrupted
  1842. continue;
  1843. /* Calculating the stream number of the entry */
  1844. uiStreamNumber = (currEntry.ucChunkID[0] - '0')*10 + currEntry.ucChunkID[1] - '0';
  1845. /* Check whether the current entry does not belong to the current played AV streams */
  1846. if ( (('d' == currEntry.ucChunkID[2]) && (uiStreamNumber != uiVideoStreamNum)) ||
  1847.  (('w' == currEntry.ucChunkID[2]) && (uiStreamNumber != uiAudioStreamNum)) )
  1848.   {
  1849. /* Not the current played stream - ignore it */
  1850.   continue;
  1851.    }
  1852.    if ( 'w' == currEntry.ucChunkID[2] )
  1853. {
  1854. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  1855. dwTotalAudioCount ++;
  1856. else
  1857. dwTotalAudioCount += currEntry.dwChunkLength;
  1858. }
  1859. /* Check the entry type (video/audio/DRM) */
  1860. if ( 'd' == currEntry.ucChunkID[2] )
  1861. {
  1862. if ( 'd' == currEntry.ucChunkID[3] )
  1863. {
  1864. /* DRM entry */
  1865. /* mark DRM chunk found, so it's value can be added to the following video */
  1866. bDrmFound = TRUE;
  1867. }
  1868. else if ( ('c' == currEntry.ucChunkID[3]) || ('b' == currEntry.ucChunkID[3])  )
  1869. {
  1870. /* Video Entry */
  1871. if (TRUE == bDrmFound)
  1872. {
  1873. currEntry.dwChunkOffset -= 0x12;
  1874. currEntry.dwChunkLength += 0x12;
  1875. bDrmFound = FALSE;
  1876. }
  1877. /* Check if this is a video chunk in which no audio is preceding it */
  1878. if (TRUE == bIsFirstAudioChunk)
  1879. {
  1880. /* If this is the first video frame - drop it */
  1881. if (FALSE == _bAVIVideoBeforeAudio)
  1882. {
  1883. _bAVIVideoBeforeAudio = TRUE;
  1884. // Robin_1003_2004_D
  1885. tr_printf(("WARNING: The video chunk is before the audio chunk!n"));
  1886. }
  1887. }