| Setting 
                    up the project Three simple steps: 
                    Include vidj.h somewhere in your source codeAdd vidj.lib to your projectEnsure that vidj.dll is "visible" to 
                      the executable (same folder, PATH env. variable, etc).  You are now ready to use VIDJ at its full extent. Important: You must call CoInitialize(NULL) 
                    at the very beginning of your application, from the main thread. 
                    Also call CoUninitialize() at the very end, after the 
                    message loop is completed. Common guidelines Functions return TRUE on success or FALSE on failure. Use 
                    VIDJ_ErrorGetCode to retrieve the error code for 
                    the last function called. Error codes are stored for each 
                    thread. So if you happen to call 2 or more VIDJ functions 
                    at the same time, they will not interfere with eachother's 
                    error codes. Initializing 
                    the library VIDJ_Init The first thing to do is to call the VIDJ_Init function: VIDJ_Init (HInstance, hMainWindow, hMasterPreview, lFullScreenDevice, dwOptions); 
                    hMainWindow is the handle of the main application 
                      window. hMasterPreview is the handle of the window that 
                      will be used for preview the mixed video output. Typically 
                      this will be the handle of a panel inside the main window. 
                      The master preview window cannot be changed later, but the 
                      panel itself can be moved or hidden if required.lFullScreenDevice is the device that will be used 
                      for full-screen output.dwOptions are additional initialization options. Possible values for lFullScreenDevice are: 
                    VIDJ_DEVICE_DEFAULT: Same as VIDJ_DEVICE_SECONDARY.VIDJ_DEVICE_DISABLEFULLSCREEN: Don't intialize 
                      any full-screen. Only previews will be available.VIDJ_DEVICE_PRIMARY: Use the primary display 
                      as full-screen. The full-screen mode can be enabled or disabled 
                      with VIDJ_ShowFullScreen.VIDJ_DEVICE_SECONDARY: Use the first secondary 
                      display available. If there's no secodary display, then 
                      the primary display will be used.number N: use the N-th secondary display. The primary 
                      screen is 0, the first secondary is 1, the second secondary 
                      is 2 and so on. If the specified display does not exists, 
                      then the behavior will be the same as VID_DEVICE_SECONDARY. Possible values for dwOptions are: 
                    VIDJ_INIT_ENABLEDEBUGLOG: log messages and errors 
                      to a log file (vidj.log in the same folder as the main exe)VIDJ_INIT_TRIPLEBUFFER: Enables triple-buffer 
                      for video rendering. This may improve the playback smoothness, 
                      but will also use more display memory.VIDJ_INIT_SINGLEDEVICEMODE: Forces the 3D engine 
                      to initialize both screens as a single device, as in previous 
                      VIDJ versions (1.x.x). This option should be used for compatibility 
                      tests only, as it will greatly increment the CPU usage.(new) VIDJ_INIT_PAUSED: 
                      Initialize the engine but doesn't start the video output 
                      yet. This allows the application to continue its initialization 
                      without the video using CPU. Use the function VIDJ_StartVideoOutput 
                      when you're ready to roll. If VIDJ_Init call is successfull then you can use 
                    the functions VIDJ_IsFullScreenAvailable, VIDJ_IsFullScreenVisible 
                    and VIDJ_IsSecondaryScreenInUse to gather information 
                    of the resulting screen scenario. When full screen is available 
                    you can show and hide it with the function VIDJ_ShowFullScreen. Preview panels Next step (optional), set the window handles that will be 
                    used for video preview on each deck: VIDJ_DeckSetPreviewWindow (VIDJ_DECKA, hPreviewA);
VIDJ_DeckSetPreviewWindow (VIDJ_DECKB, hPreviewB);
VIDJ_DeckSetPreviewWindow (VIDJ_DECKC, hPreviewC); As with the master preview, hPreviewA, 
                    hPreviewB and hPreviewC will be the handles 
                    of panels inside the main window. Preview windows can be changed 
                    or removed at any time (set to NULL for removing) but is more 
                    efficient to just hide or move the panels. TIP: Performance can be greatly improved when using dual 
                    screens by increasing the VID_SConfig.dwPreviewFrameSkip 
                    setting (see below). Configuration Now, before opening files, you may want to adjust the configuration 
                    parameters. Use the functions VIDJ_SetConfig and 
                    VIDJ_GetConfig. They are pretty self-explained. See 
                    the struct VIDJ_SConfig in vidj.h file for details. Important: you must set the VIDJ_SConfig.dwBufferLength 
                    value to at least the total ammount of audio data that your 
                    audio engine will read before actually starting playback. 
                    A safe value is 200 ms over your audio buffer lenght, and 
                    a minimum of 300 ms. The default value is 300 ms. Note: bigger buffer length require more main memory 
                    to allocate the video buffers. The required memory depends 
                    on the clip's properties, but a good estimation is 64 Mb per 
                    each 500 ms of buffer. Preparing for open files Before opening any file you should call these two functions: VIDJ_DeckSetOpenCallback (VIDJ_DECKA, OpenProcedure, dwUserDataA)
VIDJ_DeckSetPositionCallback (VIDJ_DECKA, PositionProcedure, dwUserDataA) Same for deck B and C: VIDJ_DeckSetOpenCallback (VIDJ_DECKB, OpenProcedure, dwUserDataB)
VIDJ_DeckSetPositionCallback (VIDJ_DECKB, PositionProcedure, dwUserDataB)
VIDJ_DeckSetOpenCallback (VIDJ_DECKC, OpenProcedure, dwUserDataC)
VIDJ_DeckSetPositionCallback (VIDJ_DECKC, PositionProcedure, dwUserDataC) OpenProcedure will be called 
                    during the opening process, keeping you informed on the progress. 
                    This also allows you to abort the opening process: typedef BOOL (CALLBACK VIDJ_OPENPROC)(float fProgress, DWORD dwProcUser);
 fProgress tells you the completion percentage 
                    (from 0.0 to 1.0), so you can show the user a progress bar 
                    or something like. dwProcUser is the user data you 
                    passed to the function VIDJ_DeckSetOpenCallback. 
                    Finally, from this procedure you can return TRUE for letting 
                    the process go or FALSE to abort. OpenProcedure is called only from inside a VIDJ_DeckOpen 
                    call.  PositionProcedure is very important as it 
                    will allow you to keep the video synchronized with the audio 
                    as you play it throught your audio engine. This callback will 
                    be called very frequently for requesting the current audio 
                    playback state. You must return the position of the song that 
                    is being heard at each time. The video output will then be 
                    played at the same exact rate as the audio. typedef void (CALLBACK VIDJ_PLAYPROC)(DWORD* pdwPlaybackPosition,
                                      DWORD* pdwPlaybackState,
                                      float* pfPlaybackRate,DWORD dwProcUser);
All pointers are guaranteed to be non-NULL. 
                    You must store the appropiate values at the targets: 
                    Set *pdwPlaybackPosition to the current song's 
                      position in bytes of audio stream.Set *pdwPlaybackState to zero if your player is 
                      stopped or paused; set it to non-zero if your player is 
                      running.Set *pfPlaybackRate to the current rate at which 
                      you're playing the audio. 1.0 is the original rate. The last two values are intended to let the decoder know 
                    the rate at which the video frames will be requested, so it 
                    could optimize the decoding (i.e. lower priority when the 
                    player is paused). The PlaybackRate value doesn't need to 
                    be exact.  PositionProcedure is called since VIDJ_DeckOpen 
                    to VIDJ_DeckClose. The call is generated from its 
                    own thread, so no graphic nor other thread-sensitive operations 
                    should be performed inside this procedure. The VIDJ_TimerUpdate function This function should be called regularly, always from the 
                    main thread. It handles the internal engine situations that 
                    require an action via the application's main thread. A good 
                    call rate is 5 - 10 times per second. 
                    Handles all internal automated operations such as background 
                      / logo changes, layer effects, etc...Checks for a "video lost" situation, and restores 
                      all video display surfaces when required. For instance, 
                      a typical "video lost" situation is when the user 
                      presses WINDOWS-L on Windows XP to bring the login window. 
                      When the user returns, VIDJ_TimerUpdate will restore 
                      all video resources and continue video playback normally. The VIDJ_UPDATEPROC callback This callback can be set or cleared with the function VIDJ_SetUpdateProc. 
                    When set, the engine calls the callback function once before 
                    each screen's refresh, regardless there are videos opened 
                    or not. This allows to adjust layers, positions, or any other 
                    parameter in a per-frame basis. The call rate will be the 
                    screen's refresh rate. NOTE: This callback is called from the engine's update 
                    thread. You must have this in mind when using common resources 
                    inside the callback. Also, the screen's refresh won't happen 
                    until the callback exits, so operations here may affect performance. 
                    It's safe to clear the procedure with VIDJ_SetUpdateProc 
                    (NULL, NULL) and then re-set it in order to perform intensive 
                    operations with shared resources. The following functions can be safely called inside the Update 
                    callback: VIDJ_LayerSetSurfaceVIDJ_LayerSetOrigin
 VIDJ_LayerSetAspectRatio
 VIDJ_LayerSetText
 VIDJ_LayerSetTextColor
 VIDJ_LayerSetShadow
 VIDJ_LayerSetShadowParams
 VIDJ_LayerSetOptions
 VIDJ_LayerSetVisible
 VIDJ_LayerSetPosition
 VIDJ_LayerSetAlpha
 The following 
                    functions can ONLY be called inside the Update callback: VIDJ_LayerGetDCVIDJ_LayerReleaseDC
 Releasing the library Just call: VIDJ_Free (); This function closes all open files (if any) 
                    and releases all resources associated with the library. Opening 
                    and playing files Opening a media file Just call: VIDJ_DeckOpen (VIDJ_DECKA, szFileName, dwOptions); See the vidj.h file for info on the available 
                    options (VIDJ_OPEN_ flags). The PositionProcedure 
                    callback will be called several times during the Open process. 
                   Opening a live input device Use VIDJ_DeckOpen as abobe but specify "Live://" 
                    as the file name: VIDJ_DeckOpen (VIDJ_DECKA, "Live://", dwOptions); If multiple devices are present you 
                    can select the one to open by adding its number to the file 
                    name. Thus, "Live://00" opens the first device (default); 
                    "Live://01" opens the second device, and so on. 
                    Each device can be opened in a single deck. Trying to open 
                    an already opened device will return a error. Opening an internet stream Use VIDJ_DeckOpen as abobe specifying the stream 
                    full URL as the file name: VIDJ_DeckOpen (VIDJ_DECKA, "mms://wm.somesite.com/reflector:49850", dwOptions); Note that VIDJ won't interpret Windows 
                    Media playlist files. Some URLs that ends in a .ASX file are 
                    refering to a XML-ASX playlist file which contains the final 
                    Windows Media URL. VIDJ_DeckOpen requires that final URL which 
                    sends the video stream to the user. ShoutCast audio streams are also supported: VIDJ_DeckOpen (VIDJ_DECKA, "http://sc.somesite.com:49850", dwOptions); Retrieving the 
                    media format After the file is successfully open you can retrieve its 
                    format with this function: VIDJ_DeckGetFormat (VIDJ_DECKA, pFormat); See the vidj.h file for info on the VIDJ_SStreamFormat 
                    structure. Note: When a video-only file is opened the engine 
                    will provide a 44100-16-st audio silence signal, so the audio 
                    properties of the VIDJ_SStreamFormat will always 
                    be valid. Thus, the VIDJ_DeckRead / VIDJ_DeckSeek 
                    functions can be used without changes with video-only files. Positioning and reading audio data To seek to a position inside the file call: VIDJ_DeckSeek (VIDJ_DECKA, dwPosition); dwPosition is the desired position in 
                    bytes of the audio stream. Check the stream format 
                    to know about the total length in bytes of the song. The position 
                    is automatically rounded down to the nearest sample. After 
                    the function returns you can start reading audio data inmediately. 
                    To read audio data call: VIDJ_DeckRead (VIDJ_DECKA, pBuffer, dwBufferSize, &dwRead, &dwStartPos, &dwEndPos); 
                    pBuffer is the byte buffer where the function will 
                      store the audio data. dwbufferSize is the size of the buffer, in bytes. 
                      This value is automatically rounded down to the nearest 
                      sample.dwRead returns the total amount of data in bytes 
                      written to the buffer. Use NULL if not required.dwStartPos returns the stream position in bytes 
                      at the start of the returned block. Use NULL if not required.dwEndPos returns the stream position in bytes after 
                      the last byte of the returned block. Use NULL if not required. Example: a sequence of seeks and reads produces the 
                    following result: 
                     
                      |  | dwRead | dwStartPos | dwEndPos |   
                      | VIDJ_DeckSeek (VIDJ_DECKA, 20000) | - | - | - |   
                      | VIDJ_DeckRead (VIDJ_DECKA, pBuffer, 500, &dwRead, 
                        &dwStartPos, &dwEndPos) | 500 | 20000 | 20500 |   
                      | VIDJ_DeckRead (VIDJ_DECKA, pBuffer, 500, &dwRead, 
                        &dwStartPos, &dwEndPos) | 500 | 20500 | 21000 |   
                      | VIDJ_DeckRead (VIDJ_DECKA, pBuffer, 500, &dwRead, 
                        &dwStartPos, &dwEndPos) | 500 | 21000 | 21500 |  You can call VIDJ_Read just after opening the file. 
                    It will be positioned at the beggining of the stream (0). Note: You must keep track of the stream position of 
                    the received audio data in order to calculate the actual position 
                    of the song while playback and be able to pass this position 
                    to the PositionProcedure callback. This can be done 
                    by keeping the total audio data read or by storing the dwStartPos 
                    and dwEndPos values.  Note 2: Sometimes the value of dwStartPos returned 
                    by the first read after a seek operation may not be the same 
                    as specified in the VIDJ_DeckSeek function. VIDJ_DeckRead 
                    will return the values just as returned by the video codec, 
                    and some codecs may start decoding audio from a position *near* 
                    the seeked position. VIDJ_DeckSeek and VIDJ_DeckRead can safely 
                    be called from your own poll thread.  Detecting end of stream Use the function: VIDJ_DeckEOS (VIDJ_DECKA); It returns FALSE when a file is opened and the 
                    end has not been reached yet. Returns TRUE in any other case. 
                    When the stream has reached the end then the VIDJ_DeckRead 
                    function will return 0 bytes read. Mixing video Set each deck's video output parameters by calling: VIDJ_DeckSetOutput (VIDJ_DECKA, bShowInMaster, fLevel); 
                    bShowInMaster tells wether to send the deck's output 
                      to the master or not.fLevel can be from 0.0 to 1.0 and represents the 
                      deck's relative video "volume".  When both A and B decks are sent to the master output, their 
                    relative levels are used to determine the "predominance" 
                    of one over the other. For instance, if both decks are sent 
                    to the output and their levels are 1.0 and 1.0, then each 
                    deck is shown at 50%. When only one level is sent to the master 
                    then its level value means the "fade" degree against 
                    the background (1.0 = full visible, 0.0 = completely faded 
                    out).  You can select the master mixing effect anytime by calling: VIDJ_SetVideoMixEffect (dwEffectId); dwEffectId is one of the VIDJ_EFFECTID_ 
                    constants available at the vidj.h file. Mixing effect only affects Deck A and Deck B. Deck C works 
                    independently. Deck C is always placed over A and B with the 
                    transparency set by its fLevel value. Closing a file Just call: VIDJ_DeckClose (VIDJ_DECKA); Note: when a deck is closed its preview 
                    window stops updating inmediately, so the last displayed frame 
                    will keep visible. After closing you should send a WM_PAINT 
                    message to the preview window to make it repaint itself, thus 
                    clearing the frame. Retrieving buffer state You can retrieve the audio and video buffers state anytime 
                    for debugging or information purposes: VIDJ_DeckGetBufferState (VIDJ_DECKA,
                         &dwVideoFrames, &dwVideoCapacity,
                         &dwAudioData, &dwAudioCapacity);dwVideoFrames is the 
                    number of frames actually decoded and ready to be displayed. 
                    dwVideoCapacity is the maximum number of frames that 
                    the video buffer can hold. This number is determined by the 
                    dwBufferLength value of the configuration (VIDJ_SConfig). 
                    The video frames are displayed and the buffer is "advanced" 
                    according to the playback position supplied to the PositionProcedure 
                    callback. dwAudioData is the amount in bytes of audio data actually 
                    decoded and ready to be served throught the VIDJ_DeckRead 
                    function. dwAudioCapacity is the current size of the 
                    buffer. This size is initially determined by the dwBufferLength 
                    value of the configuration (VIDJ_SConfig), but it dinamically 
                    increases itself if required. Additional 
                    settings and functions Aspect ratio adjustment The members dwAspectRatioX and dwAspectRatioY 
                    of the VIDJ_SConfig struct set the dimensions of the 
                    Master video screen. You can set any standard ratio such as 
                    4:3, 16:9, or any other custom ratio. Even you can set here 
                    the real width and height of the screen using any measure 
                    unit (centimeters, inches...). The numbers themselves are 
                    meaningless, but the ratio between them is used. If any of 
                    the values is zero then the aspect ratio is calculated using 
                    the screen's resolution in pixels (i.e. 1024x768 is 4:3). The member VIDJ_SConfig.dwAspectRatioMode defines 
                    what to do when screen and picture aspect ratios don't match. 
                    This happens, for instance, when you're trying to play a 4:3 
                    movie in a 16:9 screen, or vice-versa. The availabe modes 
                    are: 
                    0 - Auto: (default) chooses between ignore 
                      and shrink-to-frame (below) in order to avoid vertical 
                      black bands.1 - Ignore: no aspect ratio correction. Videos 
                      are stretched to cover the entire screen.2 - Shrink-to-frame: shrinks the picture until 
                      it fits into the screen keeping the picture's aspect ratio. 
                      Top-bottom or left-right black bands may be introduced.3 - Zoom-to-fit: zooms the picture keeping its 
                      aspect ratio until all the screen is filled. Top-down or 
                      left-right portions of the picture may be discarded. Layout setup (background and logo) Use the functions VIDJ_SetLayoutConfig and VIDJ_GetLayoutConfig 
                    for setting up the background and logo pictures. The options 
                    are pretty self-explained. See the struct VIDJ_SLayoutConfig 
                    in vidj.h file for details. You must call VIDJ_TimerUpdate from the application's 
                    main thread in a regular basis in order the changes to have 
                    effect. Background and logo could be: 
                     Static images (BPM, DDS, DIB, HDR, JPG, PFM, PNG, PPM, 
                      TGA). Alpha channel is supported.Video files (any supported video format, codec-based). 
                      They will be played in a silent endless loop.Live input devices. Use the same file format as specified 
                      in "Opening a live input device", below. Background picture alignment: When using any of the 
                    aspect ratio options for the background picture you can also 
                    force it to be aligned in the way you want. For instance, 
                    if top-down black bars are to be introduced as result of the 
                    aspect ratio correction, then you can force the picture to 
                    align to the upper border instead of keeping in the center 
                    of the bars. See the VIDJ_LAYER_ defines at the vidj.h file for details. Ticker text Ticker text offers two modes for displaying text messages: 
                    scrolling tape or static text. You can set up 
                    all parameters for each mode with the functions VIDJ_SetTickerConfig 
                    and VIDJ_GetTickerConfig. The options are pretty 
                    self-explained. See the struct VIDJ_STickerConfig in 
                    vidj.h file for details. Showing a text:  VIDJ_StartTicker (dwMode, "Hello world!"); dwMode can be VIDJ_TICKERMODE_STATIC 
                    or VIDJ_TICKERMODE_SCROLLER. The text will be shown according 
                    to the selected mode and its settings configured in VIDJ_SetTickerConfig. 
                    If a text is already being shown then it will be hidden before 
                    showing the new one. Hidding the text: VIDJ_StopTicker ( ); You must call VIDJ_TimerUpdate from 
                    the application's main thread in a regular basis in order 
                    the ticker text function to work properly. Displaying 
                    custom bitmaps The VIDJ library can show a custom bitmap on a deck instead 
                    of the deck's video output (overlay bitmap). Showing 
                    a bitmap is independent of video playback. Bitmaps can be 
                    shown while video playback and also when no file is open. 
                    Each deck can have its own custom bitmap, which responds properly 
                    to the video output and mixing parameters. Enabling custom bitmaps VIDJ_DeckEnableOverlay (VIDJ_DECKA, 300, 216); This tells the library the deck that will be 
                    used for output and the size (width, height) of the source 
                    bitmap, in pixels. At this point the video output for the 
                    selected deck doesn't actually change. Show or update a custom bitmap VIDJ_DeckSetOverlayBitmap (VIDJ_DECKA, hBitmap); hBitmap is the handle of the bitmap to 
                    show (HBITMAP type). It must be the same size as specified 
                    in VIDJ_DeckEnableOverlay. Any color format is allowed. 
                   The bitmap is shown the first time this function is called. 
                    Further calls will update the bitmap on screen. It highly 
                    recommended to call this function only when the bitmap changes 
                    in order to avoid overload. Disable the custom bitmap VIDJ_DeckDisableOverlay (VIDJ_DECKA); Disables the overaly bitmap for the specified 
                    deck. The deck will show the video output again if a video 
                    file is being played, or the black background is no file is 
                    loaded. Custom 
                    graphic layers  Understanding layers A layer is a graphic that is placed at some region of the 
                    screen (rectangle) with a specified opacity. Each layer has 
                    its own Z position, with defines whether its displayed over 
                    or under other layers. Layers are displayed on the Master 
                    video output (both preview and full-screen). The parameters 
                    that define a layer are: 
                    Position (VIDJ_SRect, floats): left, top, 
                      right, bottom coordinates in the screen. Upper left corner 
                      of the screen is always 0.0, 0.0 and bottom right 
                      corner is 1.0, 1.0. The picture inside the layer 
                      is scaled to fit its rectangle unless aspect-ratio options 
                      are specified (see below). The default position is full-screen 
                      (0,0 - 1,1).
Opacity or Alpha (float): from 0.0 (fully transparent) 
                      to 1.0 (fully opaque). The picture can also have its own 
                      transparency channel (i.e PNG and TIF bitmaps), which is 
                      combined with the layer's alpha setting. The default alpha 
                      is 1.
Z-Position (float): front-back setting of the layer. 
                      Layers with greater Z positions are displayed on top of 
                      layers with less Z. Z-Position is specified when creating 
                      the layer.
 The videos are displayed and mixed at Z = 0. Layers with 
                      Z > 0 are displayed on top of the videos. Layers with 
                      Z < 0 are displayed below the videos, so there won't 
                      generally be visible unless no videos are being played or 
                      the playing video is fading in or out. It's not a good idea 
                      to create layers with Z=0 as their placement over or under the 
                      videos is undefined.
 
 The layout's Background picture (VIDJ_SetLayoutConfig) 
                      is a layer with Z = -10000. The Logo picture is a layer 
                      with Z = +10000.
 
Visible (boolean): true when the layer is visible 
                      and is being rendered. false when the layer is not being 
                      renderer. New layers are created with Visible = false.
Layer options: zero or more VIDJ_LAYER_ flags. 
                      See the vidj.h file for details. Aspect ratio in graphic layers Layer options (VIDJ_LAYER_ flags, see vidj.h) include aspect 
                    ratio options. The layer options can be set up when creating 
                    the layer and/or later with the VIDJ_LayerSetOptions 
                    function. Note that aspect ratio adjustment does NOT modify the layer's 
                    position rect (VIDJ_LayerSetPosition). It just adjusts 
                    how and where to place the picture inside the rect. Also, 
                    no part of the picture will be ever displayed outside the 
                    position rect. Important: The aspect ratio adjustment will display 
                    the picture at the correct aspect ratio when the layer's position 
                    rect is a logical square (same width and height). Remember 
                    that screen's logical coordinates are 0,0 for top-left corner 
                    and 1,1 for bottom right corner, so the real rect will typically 
                    be a rectangle. This allows picture scaling even with aspect 
                    ratio correction. Aspect ratio flags: 
                    None: (default) Ignores aspect ratio. The picture 
                      is just scaled to fit exactly the layer's position rect.VIDJ_LAYER_ASPECTRATIO: Auto mode. Chooses between 
                      ignore and shrink-to-frame (below) in order 
                      to avoid vertical transparent bands.VIDJ_LAYER_ASPECTRATIO_SHRINKTOFRAME: Shrinks the 
                      picture until it fits into the layer's position rect while 
                      keeping the picture's aspect ratio. Top-bottom or left-right 
                      transparent bands may be introduced.VIDJ_LAYER_ASPECTRATIO_ZOOMTOFIT: Zooms the picture 
                      keeping its aspect ratio until all the layer's rect is filled. 
                      Top-down or left-right portions of the picture may be discarded. Alignment flags (VIDJ_LAYER_ALIGN_, see vidj.h for details): 
                   
                    These flags force the picture to be aligned inside the 
                      position rect in a specific way when aspect ratio correction 
                      is applied. For instance, if vertical transparent bands 
                      are to be introduced as result of the aspect ratio correction, 
                      then you can force the picture to be aligned to the left 
                      border instead of keeping the central position. Creating an emtpy graphic layer VIDJ_HLAYER hLayer;
 VIDJ_LayerCreate (dwWidth, dwHeight, fZPosition, dwOptions, &hLayer);
 Now you can set the bitmap for the 
                    layer with: VIDJ_LayerSetBitmap (hLayer, hBitmap) hBitmap is the handle of the bitmap to 
                    show (HBITMAP type). It must be the same size as specified 
                    in VIDJ_LayerCreate. Any color format is allowed. 
                   You can also modify the layer's content by using the layer's 
                    GDI-compatible device context (DC). See below for details. Creating a layer from a picture file VIDJ_HLAYER hLayer;
 VIDJ_LayerCreateFromFile (szFileName, dwColorKey, fZPosition, dwOptions, &hLayer);
 
                    szFileName is the picture file (.dds, .dib, .hdr, 
                      .jpg, .pfm, .png, .ppm, .tga).dwColorKey allows to specify a color which will 
                      be transparent in the layer (32-bit ARGB, i.e. fuchsia is 
                      0xFFFF00FF). You can also display only a selected region inside the picture 
                    file: VIDJ_LayerSetOrigin (hLayer, &rcOrigin) rcOrigin is a VIDJ_SRect 
                    structure with the left-top right-bottom coordinates inside 
                    the picture file that will be displayed. Left-top is 0,0 and 
                    right-bottom is 1,1. If the picture has an special aspect ratio not defined by 
                    its pixel dimensions (i.e. non-square pixels) then you can 
                    specify the picture's aspect ratio with: VIDJ_LayerSetAspectRatio (hLayer, dwAspectRatioX, dwAspectRatioY) The picture will be properly displayed according 
                    with the screen's aspect ratio specified in VIDJ_SetConfig. Working with layers First to do is display the layer: VIDJ_LayerSetVisible (hLayer, true) Layers are not visible after creation. Thus you 
                    can adjust any of their paramenters before actually displaying 
                    them. You can move, reposition (Z) or adjust any of the other parameters 
                    anytime:  VIDJ_LayerSetPosition (hLayer, &rcPosition)
VIDJ_LayerSetZPosition (hlayer, 10.7)
VIDJ_LayerSetAlpha (hLayer, 0.5)
VIDJ_LayerSetOptions (hLayer, dwOptions) Using layer's Device Context 
                    (DC) You can directly access and modify a graphic layer throught 
                    its device context (HDC) with the following code inside a 
                    VIDJ_UPDATEPROC callback: HDC hDC;
DWORD dwDevice = VIDJ_GetMasterDevice();
 if (VIDJ_LayerGetDC (hLayer, dwDevice, &hDC))
 {
 // ( Do something with the HDC here )
 
 VIDJ_LayerReleaseDC (hLayer, dwDevice, hDC);
 }
 In a dual-screen 
                    screen scenario the Master and Preview devices will be different. 
                    You must then change each layer's DC two times, once per device. 
                    The following code will work in any scenario: HDC hDC;
DWORD dwMasterDevice = VIDJ_GetMasterDevice();
DWORD dwPreviewDevice = VIDJ_GetPreviewDevice();
 if (VIDJ_LayerGetDC (hLayer, dwMasterDevice, &hDC))
 {
 // ( Do something with the HDC here )
 
 VIDJ_LayerReleaseDC (hLayer, dwMasterDevice, hDC);
 }
if (dwMasterDevice != dwPreviewDevice && VIDJ_LayerGetDC (hLayer, dwPreviewDevice, &hDC))
 {
 // ( Do with this HDC the same as above )
 
 VIDJ_LayerReleaseDC (hLayer, dwPreviewDevice, hDC);
 }
 Layer updates throught HDC are persistent, so you don't need 
                    to request and update the DC on each screens update. In fact, 
                    is much better to update the layer only when it has really 
                    changed. For instance, if you have a visualization routine that works 
                    at 30 frames per second, then it's a good idea to use a timer 
                    and upgrade the layer 30 times per second instead of on each 
                    callback, which could be called 60, 100 or more times per 
                    second depending on the screen's refresh rate. Also, you could implement a counter in order to check the 
                    dwPreviewFrameSkip config option before upgrading the 
                    DC for the preview device. This would save CPU by skipping 
                    innecesary updates. IMPORTANT: Layer's HDC can ONLY be requested and used 
                    inside a VIDJ_UPDATEPROC callback, which can be set 
                    or cleared with the function VIDJ_SetUpdateProc. EVEN MORE IMPORTANT: You must ALWAYS release the HDC 
                    right after successfully retrieving it. Otherwise the entire 
                    video engine will not be able to continue rendering the graphic 
                    scene, and will probably end crashing the application. Deleting layers Just call: VIDJ_LayerDelete (hLayer) It's a good idea to make hLayer = NULL after 
                    deleting the layer. VIDJ layer funtions check against null 
                    handles, but invalid or already-freed handles may raise access 
                    violation errors. All non-deleted layers will be automatically deleted upon 
                    library termination (VIDJ_Free). Fonts 
                    and Text layers  Understanding fonts and texts Texts are shown as a special kind of layer with its own special 
                    properties and functions. Most layer functions can be used 
                    also with text layers. The parameters for a text layer are: 
                    Common layer parameters: Position, Opacity, Z-Position, 
                      Visible, Options.
Font: Defines the font's appearance: face, size, 
                      style. A single font can be used to create multiple text 
                      layers.
Text: the string of text that is displayed. The 
                      text will be adjusted to fit inside the layer's position 
                      rect using the font's properties. The text will be formatted 
                      according to the alignment options (VIDJ_LAYER_ALIGN_) and 
                      the text-specific options (VIDJ_LAYER_TEXT_).
Text Color: self explained.
Shadow: display the text with an adjustable shadow. 
                      Shadow increases readability as one tyipically can't predict 
                      the background's color (video clips playing). Font parameters: 
                    Face: common font name (Arial, Verdana...). Any 
                      font can be used as long as it's available in Windows.
Size: font height, relative to main screen's height: 
                      100 = 100%. For instance, size 10 means that the text's 
                      height will be 10% of the main screen's height.
Options: VIDJ_FONT_ flags, for style and aspect-ratio 
                      options. See vidj.h for more information.
 Font size and aspect ratio Font size is specified as height percent of the screen's 
                    height. A font size of 10 means that the text height will 
                    be the tenth part of the screen's height. This allows you 
                    to choose uniform font sizes that will be displayed properly 
                    regardless the final screen's dimensions. This also makes 
                    easy to calculate the layer's position rect for the text (VIDJ_LayerSetPosition), 
                    as screen cordinates are also relative. Example: 
                    Font size is 10Position rect: (0, 0)-(1, 0.2) -> the rect's height 
                      is 0.2 The above means that the text layer will hold exactly TWO 
                    lines of text: rect's height is 0.2, exactly 20% of the screen's 
                    height. Font size is 10, that is, 10% of the screen's height. 
                    So the layer will hold exactly two lines of text. Aspect ratio adjustment in texts can be enabled only when 
                    creating the font as a creation option (VIDJ_FONT_ASPECTRATIO). 
                    The aspect ratio is applied by adjusting the font's width 
                    so the letters will match the screen's aspect ratio. The font's 
                    height is always the same. Unlike graphic layers, font options (bold, italic, aspect 
                    ratio) can't be changed on the fly. You will need to create 
                    a new font with the new options and use the VIDJ_LayerSetFont 
                    function to set the new fonts in the appropiate layers. Creating and deleting fonts VIDJ_HFONT hFont;
                     
VIDJ_FontCreate ("Arial", 10, 0, &hFont);Using font options: VIDJ_FontCreate ("Verdana", 20, VIDJ_FONT_BOLD|VIDJ_FONT_ASPECTRATIO, &hFont);Deleting fonts: VIDJ_FontDelete (hFont); Important: You must delete all text layers 
                    that are using the font before deleting it. Otherwise you 
                    will receive an error and the font won't be deleted. Creating text layers First you need to create a font with VIDJ_FontCreate. VIDJ_HLAYER hLayer;
                     
VIDJ_TextLayerCreate (hFont, fZPosition, dwOptions, &hLayer);Word-wrap is a feature specific for text 
                    layers: VIDJ_TextLayerCreate (hFont, fZPosition, VIDJ_LAYER_TEXT_WORDWRAP, &hLayer);  Working with text layers First to do is display the layer: VIDJ_LayerSetVisible (hLayer, true) As with graphic layers, text layers are not visible 
                    after creation. Thus you can adjust any of their paramenters 
                    before actually displaying them. You can move, reposition (Z) or adjust any of the other common 
                    layer parameteers parameters anytime:  VIDJ_LayerSetPosition (hLayer, &rcPosition)
VIDJ_LayerSetZPosition (hlayer, 10.7)
VIDJ_LayerSetAlpha (hLayer, 0.5)
VIDJ_LayerSetOptions (hLayer, dwOptions) Text layers feature some specific functions 
                    for changing the text paramerets: text, text color (32-bit 
                    ARGB), and font: VIDJ_LayerSetText (hLayer, "Hello World\nThis is a sample two-lines text");
VIDJ_LayerSetTextColor (hLayer, dwColor);
VIDJ_LayerSetFont (hLayer, hNewFont); Text layers also feature shadow capabilities: VIDJ_LayerSetShadow (hLayer, true); If you don't like the default shadow properties, 
                    you can change them: VIDJ_LayerSetShadowParameters (hLayer, fDistance, fAngle, fAlpha); 
                    fDistance uses the same units as font size. For 
                      instance, if the font size is 10 then a shadow distance 
                      of 10 will draw it with a "one line height" distance.fAngle is degrees, from 0 to 360, 0 = "up", 
                      clockwise.fAlpha is the shadow's transparency. Deleting text layers Same as graphic layers: VIDJ_LayerDelete (hLayer) It's a good idea to make hLayer = NULL after 
                    deleting the layer. VIDJ layer funtions check against null 
                    handles, but invalid or already-freed handles may raise access 
                    violation errors. All non-deleted layers will be automatically deleted upon 
                    library termination (VIDJ_Free). Important: Deleting a text layer does NOT delete the 
                    font (VIDJ_HFONT). Fonts are intended to be created once then 
                    used many times by text layers. Layer 
                    effects Initializing layer effects Effects for layers are initialized with the function VIDJ_LayerSetEffect. 
                    Each layer can have a single effect active. Setting a new 
                    effect on a layer that already has an active effect will cancel 
                    the ongoing effect and apply the new one. The effect will 
                    remain active until it's completed. float afParams[] = { param0, param1, param2, param3, ... };
 VIDJ_LayerSetEffect (hLayer, dwEffectId, dwOptions, fStartDelay, afParams, dwParamCount);
                    dwEffectId is the desired effect (VIDJ_LAYEREFFECT_)dwOptions are the options for the effect (VIDJ_EFFECTOPTIONS_)fStartDelay is the time (in seconds) that the effect 
                      will delay until start. 0 means "start inmediately". 
                    afParams is a pointer to an array of floats. dwParamCount 
                      is the number of parameters. The number and meaning of the 
                      parameters depends on each effect. Available effects (dwEffectId). See details below. 
                    VIDJ_LAYEREFFECT_ALPHAFADE: transitions with 
                      alpha (opacity).VIDJ_LAYEREFFECT_MOVE: layer movement. Effect options (dwOptions): 
                    VIDJ_EFFECTOPTIONS_AUTODELETE: automatically 
                      deletes the layer when the effect is completed. The layer 
                      handle will be no longer valid when the effect is completed, 
                      so it's a good idea to set it to NULL after calling VIDJ_LayerSetEffect.
VIDJ_EFFECTOPTIONS_LOOP: makes the effect start 
                      over when is completed. The effect will be active indefinitely 
                      until the layer is deleted or VIDJ_LayerSetEffect is called 
                      with the effect VIDJ_LAYEREFFECT_OFF. Alpha transitions dwEffectId = VIDJ_LAYEREFFECT_ALPHAFADE; Notes:  
                    All times are seconds, and are NOT cummulative: each time 
                      refers to its own stage in the effect, independently from 
                      other stages.All alpha values are from 0.0 (transparent) to 1.0 (opaque).Specifying -1 in any alpha value means "use layer's 
                      current alpha".The last time value ("stand-by" time) is useful 
                      for loops. It can be used for specyfing a delay between 
                      each cycle.Bias values: "smoothness" of the transition 
                      from a value to the following. 0.5 means lineal transition 
                      (same as with no bias). 0.8 means "starting fast, ending 
                      slow". 0.2 means "starting slow, ending fast". Simple alpha fade (4 parameters): float afParams[] = { a0, t0, a1, t1 }; 
                    a0: starting alpha.t0: fade duration from a0 to a1a1: ending alpha.t1: stand-by time with alpha = a1 Simple alpha with bias curve (5 parameters): float afParams[] = { a0, t0, a1, t1, bias }; 
                    a0, t0, a1, t1: same as above.bias: "smoothness" of the transition 
                      curve from a0 to a1, between 0 and 1. Alpha with 4-points evenlope (8 parameters): float afParams[] = { a0, t0, a1, t1, a2, t2, a3, t3 }; 
                    a0: starting alpha. t0: fade duration from a0 to a1a1: second alpha valuet1: fade duration from a1 to a2a2: third alpha valuet2: fade duration from a2 to a3a3: ending alphat3: standby time with alpha = a3 Alpha with 4-points evenlope and bias (11 parameters): float afParams[] = { a0, t0, a1, t1, a2, t2, a3, t3, bias0, 
                    bias1, bias2 }; 
                    a0, t0, a1, t1, a2, t2, a3, t3: same as above.bias0: "smoothness" of the transition 
                      curve from a0 to a1.bias1: "smoothness" of the transition 
                      curve from a1 to a2.bias2: "smoothness" of the transition 
                      curve from a2 to a3. Movement effects dwEffectId = VIDJ_LAYEREFFECT_MOVE; Notes:  
                    All times are seconds, and are NOT cummulative: each time 
                      refers to its own stage in the effect, independently from 
                      other stages.Only position is changed, not size. The size of the layer 
                      is kept during the effect, so it should be specyfied with 
                      VIDJ_LayerSetPosition before setting the effect.Positions are always relative to the screen. 0,0 is the 
                      top-left corner, 1,1 is the bottom right corner.The last time value ("stand-by" time) is useful 
                      for loops. It can be used for specyfing a delay between 
                      each cycle.Bias values: "smoothness" of the transition 
                      from a value to the following. 0.5 means lineal transition 
                      (same as with no bias). 0.8 means "starting fast, ending 
                      slow". 0.2 means "starting slow, ending fast". Simple movement (6 parameters): float afParams[] = { x0, y0, t0, x1, y1, t1 }; 
                    x0,y0: starting position.t0: movement duration from x0,y0 to x1,y1x1,y1: ending position.t1: stand-by time at x1,y1 Simple movement with bias (7 parameters): float afParams[] = { x0, y0, t0, x1, y1, t1, bias }; 
                    x0,y0, t0, x1,y1, t1: same as above.bias: "smoothness" of the transition 
                      curve from x0,y0 to x1,y1, between 0 and 1. Movement between 4 positions (12 parameters): float afParams[] = { x0, y0, t0, x1, y1, t1, x2, y2, t2, 
                    x3, y3, t3 }; 
                    x0,y0: starting position.t0: movement duration from x0,y0 to x1,y1x1,y1: second positiont1: movement duration from x1,y1 to x2,y2x2,y2: third positiont2: movement duration from x2,y2 to x3,y3x3,y3: ending positiont3: stand-by time at x3,y3 Movement between 4 positions with bias (15 parameters): float afParams[] = { x0, y0, t0, x1, y1, t1, x2, y2, t2, 
                    x3, y3, t3, bias0, bias1, bias2 }; 
                    x0,y0, t0, x1,y1, t1, x2,y2, t2, x3,y3, t3: same as above.bias0: "smoothness" of the transition 
                      curve from x0,y0 to x1,y1.bias1: "smoothness" of the transition 
                      curve from x1,y1 to x2,y2.bias2: "smoothness" of the transition 
                      curve from x2,y2 to x3,y3. Additional 
                    functions & advanced topics Retrieving the format of a file You can retrieve the format of a file without actually opening 
                    it with the function: VIDJ_GetFileFormat (szFileName, &Format); This function works like VIDJ_DeckOpen, 
                    but it just opens the file with the minimum features for retrieving 
                    its format and then closes it. 
                    szFileName is the stream name or URL.Format is a VIDJ_SStreamFormat structure, 
                      the same as used in the VIDJ_DeckGetFormat function. VIDJ_GetFileFormat is useful for "media library" 
                    features, when many files need to be analysed in order to 
                    build a database. It runs completely "isolated" 
                    from the rest of engine, so it can be called from any thread 
                    at any time (provided only than the library has been initialized 
                    with VIDJ_Init). Even multiple simultaneous calls 
                    are supported. See "Multithreading Considerations" 
                    below for more information. Playing DRM-enabled files You need to compile a DLL using the enclosed EnableDRM Visual 
                    Studio project: 
                    Load the project EnableDRM in Visual Studio. Remove the "WMStubDRM.lib" reference from the 
                      project and add your own WM stub library. Build the project. It will output a DLL file named EnableDRM.dll. Rename the DLL file to bassdmc.dll and put it 
                      in the same folder as your executable file.  When a DRM-enabled file is loaded then VIDJ will try to locate 
                    the bassdmc.dll library. If it exists, VIDJ will call its 
                    exported function in order to create a WM certificate for 
                    the file. If a certificate can be created then the file is 
                    loaded and opened properly. Otherwise (i.e. the user has no 
                    license for playing that file) the VIDJ_DeckOpen 
                    function returns VIDJ_ERROR_DRM. Note: DRM-enabled files cannot be played while debugging 
                    the application. The files can be opened, but they will return 
                    invalid or no data. How to adquire Windows Media licenses If opening a DRM file returns VIDJ_ERROR_DRM then the user 
                    must first open the file in Windows Media Player and follow 
                    the instructions for adquiring a license for that file. Once 
                    the license is properly adquired and the file can be played 
                    in Windows Media Player then VIDJ will be able to load and 
                    play the file as well. Performance tunning The following initialization option (VIDJ_Init) 
                    affect the usage of display memory: VIDJ_INIT_TRIPLEBUFFER 
                    When enabled, each viewport will be initialized with 2 
                      backbuffers instead of one. This typically improves video 
                      playback smoothness on less-powerful computers. The display memory used per viewport is increased by 50% 
                      with this setting. For instance, if creating a viewport 
                      takes 20Mb of display memory, enabling triple-buffering 
                      will take 30Mb for the same viewport.This setting does NOT affect the CPU usage. The following config options (VIDJ_SConfig) affect 
                    the usage of CPU and/or display memory: dwPreviewFrameSkip 
                    The more frame-skip value, less CPU will be used during 
                      video playback as the preview windows will be refreshed 
                      less frequently. The default value is 2. dwMaxVideoSize 
                    By setting a upper limit to the video frame size can save 
                      a bit of display memory. It's useful for playing HD videos 
                      in old display cards with small display memory. The default 
                      value is 0, which means no upper limit.Using this setting will force the engine to use a off-screen 
                      surface in order to resize the video frames, which may decrease 
                      the performance on some systems. Precise seeking in video streams Most video codecs will always seek to the nearest video frame. 
                    This means that if you call VIDJ_DeckSeek (VIDJ_DECKA, 
                    200000), and then call VIDJ_DeckSeek (VIDJ_DECKA, 
                    205000) you will likely get positioned at the same position. 
                    So the accuracy of our seek operations seems to depend on 
                    the video framerate. This behavior is imposed by the codecs. However, calling VIDJ_DeckRead after the seek operation 
                    will return the dwStartPos and dwEndPos values 
                    according to the last seeked position. This means that the 
                    codec wants us to believe that it has been positioned at the 
                    exact requested position, but it really hasn't. It seems that we can do little to improve accuracy. If the 
                    codec seeks to video-frame boundary (it's undefined whether 
                    the position is rounded to the next or to the previous frame) 
                    then actually we can't know what's the exact seeked position 
                    as the upcoming data will be timestampted as if the seek operation 
                    had been exact. The workaround: there is a little trick we can use 
                    to improve acuracy when positioning in video streams. If we 
                    know the exact framerate of the video stream, then we can 
                    calculate the exact byte position at which each video frame 
                    is located. Thus, we can seek to the start of the video frame 
                    knowing that the video codec will accurately find that frame, 
                    and then read and discard audio data until the exact requested 
                    postition is reached. For instance, if we want to position at "dwPosition", 
                    then we could use this code: dwBytesPerFrame = Format.dwBytesPerSecond / Format.fFrameRate;
dwFramePos = (dwPosition/dwBytesPerFrame) * dwBytesPerFrame;
VIDJ_DeckSeek (VIDJ_DECKA, dwFramePos);
VIDJ_DeckRead (VIDJ_DeckA, pBuffer, dwPosition-dwFramePos, NULL, NULL, NULL);
 Next VIDJ_DeckRead calls will return 
                    the data from the position "dwPosition". But... some codecs doesn't just seek to frame-boundary, 
                    but also to KEY frame-boundary. In these formats there are 
                    some "key" frames which are "safe" to 
                    start decoding from. When you seek to some position, the codec 
                    will first seek to that position and then start reading forward 
                    until nearest KEY frame is reached. Actually you can't know 
                    what's the real position you're at, as you cannot know the 
                    frequency nor positions of the key frames unless you manually 
                    decode the file. In summary, the seek-to-frame workaround above should 
                    work fine in most circumstances. However, in some cases won't 
                    be possible to achieve a good accuracy on positioning. Each 
                    case depends on the file format and the codecs that are used 
                    to read that format. Multithreading 
                    considerations The following functions must allways be called from the main 
                    thread: VIDJ_Init
VIDJ_Free
VIDJ_TimerUpdate The following functions can be called from a 
                    thread other than the main thread, provided that they are 
                    not called at the same time and thet they are always called 
                    *after* VIDJ_DeckOpen and *before* VIDJ_DeckClose: VIDJ_DeckSeek
VIDJ_DeckRead The following function can be called from any 
                    thread, anytime. Even multiple simultaneous calls are supported: VIDJ_GetFileFormat All other functions can be called from any thread 
                    provided than only one function is called at once. Opening files in a separate thread Files can be opened in a separate thread by creating a worker 
                    thread and calling VIDJ_DeckOpen from it. No special 
                    requirements at all. Notes: 
                    Set a low priority to the worker thread. Otherwise, video 
                      frame-skip or sound stutter could happen while loading.It's a good idea to set a time-out for the worker thread 
                      to complete (30 - 60 seconds is ok). In some (very rare) 
                      cases the VIDJ_DeckOpen function may never return due to malfunctioning codecs. 
                      If the timeout elapses without response, then kill the worker 
                      thread and assume "load error". |