videoeditorengine/h263decoder/src/h263dntc.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:  
* Video decoder control interface.
*
*/



/*
 * Includes
 */

/* Include the definition header for the active build target */
#include "h263dConfig.h"
/* Include the header for this file */
#include "h263dntc.h"
/* All other inclusions */
#include "biblin.h"
#include "h263dapi.h"
#include "vde.h"
#include "vdemain.h"
#include "vdeti.h"
#include "biblin.h"
/* MVE */
//#include "InnerTranscoder.h"
#include "core.h"
#include "MPEG4Transcoder.h"

/* 
 * Constants 
 */
const TUint KH263StartCodeLength = 3;  // H.263 picture start code length
const TUint KMPEG4StartCodeLength = 4; // MPEG4 picture start code length

/*
* Global functions
*/

/* {{-output"h263dClose.txt"}} */
/*
* h263dClose
*    
*
* Parameters:
*    hInstance                  instance handle
*
* Function:
*    This function closes an H.263 decoder instance.
*
* Returns:
*    Nothing
*/

void H263D_CC h263dClose(h263dHInstance_t hInstance)
/* {{-output"h263dClose.txt"}} */
{
    if (hInstance)
        vdeShutDown(hInstance);
}


/* {{-output"h263dDecodeFrame.txt"}} */
/*
* h263dDecodeFrameL
*    
*
* Parameters:
*    hInstance                  instance data
*    pStreamBuffer              pointer to input data (>= 1 video frames)
*    streamBufferSize           size of pStreamBuffer
*    fFirstFrame                pointer to flag telling if the very first
*                               frame is being decoded
*    frameSize                  If non-NULL, frameSize is used to return 
*                               the number of bytes that were decoded 
*                               to produce the reconstructed output frame.
*
* Function:
*    This function decodes the bitstream until it gets at least one decoded
*    frame. It also shows the resulting frames. 
*    In addition, the function handles the parameter updating synchronization.
*
* Returns:
*    H263D_OK                   if the function was successful
*    H263D_OK_EOS               if the end of stream has been reached
*    H263D_ERROR                if a fatal error, from which the decoder
*                               cannot be restored, has occured
*    H263D_ERROR_HALTED         the instance is halted, it should be closed
*/

int H263D_CC h263dDecodeFrameL(h263dHInstance_t hInstance,
                               void *pStreamBuffer,
                               void *pOutStreamBuffer,
                               unsigned streamBufferSize,
                               u_char *fFirstFrame,
                               TInt *frameSize,
                               TInt *outframeSize, 
                               vdeDecodeParamters_t *aDecoderInfo
                               )
                                                            
/* {{-output"h263dDecodeFrame.txt"}} */
{
    TInt colorEffect = aDecoderInfo->aColorEffect;
    TInt colorToneU  = aDecoderInfo->aColorToneU;
    TInt colorToneV  = aDecoderInfo->aColorToneV;
    TInt frameOperation = aDecoderInfo->aFrameOperation;
    TInt* trP = aDecoderInfo->aTrP;
    TInt* trD = aDecoderInfo->aTrD; 
    TInt videoClipNumber = aDecoderInfo->aVideoClipNumber; 
    TInt smSpeed = aDecoderInfo->aSMSpeed;
    TInt getDecodedFrame = aDecoderInfo->aGetDecodedFrame; 
    
    bibBuffer_t 
        *buffer = 0;                   /* input buffer */
    
    bibBuffer_t 
        *outbuffer = 0;               /* output buffer */

    bibBuffer_t 
        *tmpbuffer = 0;                /* temporary buffer */

    u_char* tmpbuf=0;

    bibBufferEdit_t
        *bufEdit = 0;
     
    int StartByteIndex=0;
    int StartBitIndex=7;

    int tr = 0;
    int newtr = 0;
    int efftr;
    int numBitsGot;
    int bitsErrorIndication;
    int16 bibError;
    
    int retValue;                  /* return value for vde functions */

    int leaveError = 0;
     
    int16
        errorCode = 0;             /* return code for bib functions */

  /* MVE */
    int startCodeLen = 0;
    CMPEG4Transcoder *hTranscoder = NULL;

    TBool modifyMPEG4Afterwards = EFalse;

    vdeAssert(hInstance);
    vdeAssert(pStreamBuffer);
    vdeAssert(pOutStreamBuffer);
    vdeAssert(streamBufferSize);
    vdeAssert(fFirstFrame);

    vdeInstance_t *vdeinstance = (vdeInstance_t *) hInstance;
    
    /* Create bit buffer */
    buffer = bibCreate(pStreamBuffer, streamBufferSize, &errorCode);
     if (!buffer || errorCode)
         return H263D_ERROR;
     
     /* MVE */

     if ((aDecoderInfo->streamMode==EVedVideoBitstreamModeMPEG4ShortHeader) || (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263) )
         outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-3, &errorCode);
     else
         outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-4-3, &errorCode);

     if (!outbuffer || errorCode)
     {
         bibDelete(buffer, &errorCode);
         return H263D_ERROR;
     }
     
     bufEdit = bibBufferEditCreate(&errorCode);
     if (!bufEdit || errorCode)
     {
         bibDelete(outbuffer, &errorCode);
         bibDelete(buffer, &errorCode);
         return H263D_ERROR;
     }   
     
     if(frameOperation==4 /*ENoDecodeNoWrite*/)
     {
         bufEdit->copyMode = CopyNone;
     }
     
     if(colorEffect==1 || colorEffect==2)
     {
         outbuffer->numBytesRead=0;
         outbuffer->size=0;
     }
     
   /* Associate bit buffer with the VDE instance */
     retValue = vdeSetInputBuffer(hInstance, buffer);
     if (retValue < 0)
         goto freeBufferAndReturn;
     
     /* Associate output bit buffer with the VDE instance */
     retValue = vdeSetOutputBuffer(hInstance, outbuffer);
     if (retValue < 0)
         goto freeBufferAndReturn;
     
     retValue = vdeSetBufferEdit(hInstance, bufEdit);
     if (retValue < 0)
         goto freeBufferAndReturn;
     
     retValue = vdeSetVideoEditParams(hInstance, colorEffect,
       getDecodedFrame, colorToneU, colorToneV);
     if (retValue < 0)
         goto freeBufferAndReturn;
     
   /* MVE */
     if (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263 /*H.263*/)
     {
         /* read current TR */
         bibForwardBits(22,buffer); // streamBufferSize is in bytes
         tr = bibGetBits(8,buffer,&numBitsGot, &bitsErrorIndication, &bibError);    
         bibRewindBits(30,buffer,&bibError);
     }

  /* get first frame's QP */
  if (!(*fFirstFrame))
  {
    vdeinstance->iRefQp = aDecoderInfo->aFirstFrameQp;
  }
  vdeinstance->iColorEffect = aDecoderInfo->aColorEffect;
  vdeinstance->iColorToneU = aDecoderInfo->aColorToneU;
  vdeinstance->iColorToneV = aDecoderInfo->aColorToneV;
  
  /* MVE */
  /* one frame is ready, initialize the transcoder */
    TRAP( leaveError, (hTranscoder = CMPEG4Transcoder::NewL(vdeinstance, vdeinstance->inBuffer, vdeinstance->outBuffer)) );
    if ( leaveError != 0 )
    {
        retValue = leaveError;
        goto freeBufferAndReturn;
    }

    if (aDecoderInfo->aGetVideoMode)
    {
        /* we are to determine the bitstream mode */
        aDecoderInfo->aOutputVideoFormat = EVedVideoTypeNoVideo;
        int dummy1, dummy2; // position of the error resillence bit,not used here
        vdtGetVideoBitstreamInfo(buffer, aDecoderInfo, &dummy1, &dummy2);
    }

    /* set transcoding information */
    retValue = hTranscoder->SetTranscoding(aDecoderInfo);
    if ( retValue != TX_OK )
    {
        goto freeBufferAndReturn;
    }
    
    /* before the first frame is decoded, determine the stream type */
    if (*fFirstFrame) {
        retValue = vdeDetermineStreamType(hInstance, hTranscoder);
        if (retValue < 0)
            goto freeBufferAndReturn;
        
    /* MVE */
        /* for the first frame of the bitstream, we may need to construct a new VOS */
        hTranscoder->ConstructVOSHeader(vdeinstance->fMPEG4, aDecoderInfo);
        
        if (vdeinstance->fMPEG4 == 1 )
        {
            StartByteIndex = buffer->getIndex;
            StartBitIndex  = buffer->bitIndex;
            
            /* for MPEG4 (not including shortheader) stuffing bits are inserted at the end of the VOS
            but the index here indicates the position of the stuffing bits
            */
            if (StartBitIndex != 7)
            {
                StartByteIndex += 1;
                StartBitIndex = 7;
            }
            
            // update the output stream size by removing VOS size
            streamBufferSize -= StartByteIndex; 
        }
        
        else if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader)
        {
            if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level10 ||
                aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level45)
            {
                // we don't need the VOS header
                StartByteIndex = buffer->getIndex;
                StartBitIndex  = buffer->bitIndex;
                // update the output stream size by removing VOS size
                streamBufferSize -= StartByteIndex; 
            }
            else if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile &&
                aDecoderInfo->fModeChanged == EFalse)
            {
                // update the output stream size by removing VOS size
                // but we need the original MPEG4 shortheader VOS, which is not yet copied to the output buffer
                streamBufferSize -= buffer->getIndex;
                
            }
        }
        
    }

    /* This may produce multiple output frames, and that is why it is commented
     out. However, it may be useful if the bitstream is corrupted and picture
     start codes are lost
     while (buffer->bitsLeft > 8) { */
     /* Decode frame */

  /* MVE */
  /* The buffer size is changed in h263decoder.cpp
    In the old version, it is fixed to 3, which may be incorrect 
    */
    startCodeLen = (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263)? KH263StartCodeLength : KMPEG4StartCodeLength;
    
    
    
    if ( ((aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile) 
            && !(aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader))
        || ((aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader) && aDecoderInfo->fModeChanged) )
        {
        modifyMPEG4Afterwards = ETrue;
        }

    if (frameOperation==1/*EDecodeAndWrite*/ || frameOperation==2/*EDecodeNoWrite*/)
        {
        if ( vdeinstance->fMPEG4 == 1 )
            {
            buffer->size -= startCodeLen;
            buffer->bitsLeft -= ( startCodeLen << 3 );
            }
        retValue = vdeDecodeFrame(hInstance, StartByteIndex, StartBitIndex, hTranscoder);
        if ( retValue < VDE_OK )
            {
            // negative means fatal error
            goto freeBufferAndReturn;
            }
         // get first frame QP for possible color toning
         if (*fFirstFrame)
         {
           aDecoderInfo->aFirstFrameQp = hTranscoder->GetRefQP();
        }
     }
     else if (frameOperation==3/*EWriteNoDecode*/) 
        {
        /* first reset bit counter to beginning of buffer */
        /* copy input frame as it is */
        bibForwardBits((streamBufferSize-startCodeLen)<<3,buffer); // streamBufferSize is in bytes
         
        if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader &&
            aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile &&
            !(aDecoderInfo->fModeChanged))
            {
            bibRewindBits(32,buffer,&bibError);
            }
         
        /* reset buffer edit to CopyWhole mode */
        bufEdit->copyMode = CopyWhole/*CopyWhole*/;
         
        if ( vdeinstance->fMPEG4 == 1 )
            {
            if (*fFirstFrame)
                {
                buffer->getIndex = buffer->size - startCodeLen;
                buffer->bitIndex = 7;
                buffer->bitsLeft = 24;
                buffer->numBytesRead = buffer->size - startCodeLen;
                }
             
            if ( buffer->numBytesRead > 4 )
                {
                buffer->numBytesRead -= 4;
                buffer->getIndex = buffer->numBytesRead;
                }
            }
         // Reassign pointers so that outbuffer actually has the pointer to (in)buffer's data, 
         // if we have MPEG4 output (not short header) and we need to change e.g. timestamps
         // This eliminates 2 memory copies - otherwise we would copy from buffer to outbuffer to tmpbuffer to outbuffer; 
         // the content is modified when copying from tmpbuffer to outbuffer. 
         // tmpbuffer is needed since we can't modify the content directly in the outbuffer.
         // Now we can copy directly from buffer to outbuffer.
         // In this branch we don't call vdeDecodeFrame at all, but use either CopyEditVopL for MPEG-4 or
         // CopyStream for H.263
         if ( modifyMPEG4Afterwards )
             {
             tmpbuffer = buffer;
             }
         else
             {
             /* copy from buffer to outbuffer. This simulates vdeDecodeFrame with EDecodeAndWrite */
             CopyStream(buffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex);
             }
         retValue=0;
     }
     
     outbuffer->size = outbuffer->getIndex;
     outbuffer->bitsLeft = 0;

     if ( !tmpbuffer )
        {
         /* if tr values are changes, need another buffer */
         /* first create temp buffer in memory */
         tmpbuf = (u_char*) malloc(outbuffer->size + 4);
         if (tmpbuf == NULL) 
         {
             bibDelete(outbuffer, &errorCode);
             bibDelete(buffer, &errorCode);
             bibBufEditDelete(bufEdit, &errorCode);
             return H263D_ERROR;
         }
         tmpbuffer = bibCreate((void*)tmpbuf, outbuffer->size + 4, &errorCode);
         if (!tmpbuffer || errorCode)
         {
            free(tmpbuf);
            bibDelete(outbuffer, &errorCode);
            bibDelete(buffer, &errorCode);
            bibBufEditDelete(bufEdit, &errorCode);
            return H263D_ERROR;
         }
        }
     
   /* MVE */
     if (aDecoderInfo->aOutputVideoFormat != EVedVideoTypeNoVideo)
        {

        if ( modifyMPEG4Afterwards )
            {
            if ( tmpbuffer != buffer )
                {
                // the bitstream was decoded too, need to copy it temporarily from outbuffer to tmpbuffer since it needs to be modified
                bibRewindBits(bibNumberOfFlushedBits(tmpbuffer),tmpbuffer,&bibError);
                bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError);
                bibForwardBits(((outbuffer->size)<<3),outbuffer);
                outbuffer->bitsLeft = 0;

                StartByteIndex = 0;
                StartBitIndex = 7;
                
                CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex);
                tmpbuffer->baseAddr[tmpbuffer->getIndex] = 0x0;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+1] = 0x0;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+2] = 0x01;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+3] = 0xb6;
                }
             else
                {
                // the tmpbuffer was used as a shortcut to the buffer, no need to copy anything here. 
                tmpbuffer->bitsLeft = 32;
                // the following ones are probably not needed
                tmpbuffer->baseAddr[tmpbuffer->getIndex+4] = 0x0;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+5] = 0x0;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+6] = 0x01;
                tmpbuffer->baseAddr[tmpbuffer->getIndex+7] = 0xb6;
                }
                
           
            bibForwardBits(32,tmpbuffer);
            
            // Copy bitstream part-by-part, possibly modifying it, from tmp to output. 
            // StartByteIndex may be > 0 if there is VOS header in tmpbuffer already. It is always byte-aligned so no need to have StartBitIndex
            TInt skip = 0;
            if ( StartByteIndex > 0 )
                {
                // startByteIndex refers to input buffer. 
                // The skip however should refer to the output buffer. The output header size is in aDecoderInfo
                skip = aDecoderInfo->vosHeaderSize;
                }
            int retVal= CopyEditVop(hInstance, skip, tmpbuffer, aDecoderInfo);
            if(retVal<0)
                {
                retValue = retVal;  //will be handled later
                }
            }
        else
            {
            /* copy input frame while changing TR */
            if((videoClipNumber>0) || (smSpeed!=1000))
                {
                if ((frameOperation==1) || ((frameOperation==2) && !getDecodedFrame))
                    {
                    /* if the output buffer will not be use, leave it as it is! */
                    }
                else
                    {

                    /* get new TR */
                    StartByteIndex = 0;
                    StartBitIndex = 7;
                    outbuffer->bitsLeft = 0;
                    newtr = GetNewTrValue(tr, trP, trD, smSpeed);
                    /* change TR value in output bitstream */
                    /* prepare editing position */
                    if (!bufEdit->editParams)
                        {
                        bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t));
                        if (bufEdit->editParams == NULL)
                            {
                            retValue = H263D_ERROR;
                            goto freeBufferAndReturn;
                            }
                        
                        bufEdit->numChanges=1;
                        bufEdit->copyMode = CopyWithEdit; // CopyWithEdit
                        }
                    bufEdit->editParams->curNumBits = bufEdit->editParams->newNumBits = 8; 
                    bufEdit->editParams->StartByteIndex=2; //2;     // starting position for the TR marker 
                    bufEdit->editParams->StartBitIndex=1; //1;          // starting position for the TR marker 
                    bufEdit->editParams->newValue=newtr; 
                    /* copy the input buffer to the output buffer with TR changes */
                    CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex);
                    bibRewindBits((streamBufferSize)<<3,buffer,&bibError);
                    /* copy the changed bitstream from tmpbuffer back to buffer */
                    bufEdit->copyMode = CopyWhole; // CopyWhole
                    bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError);
                    CopyStream(tmpbuffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex);
                    bibRewindBits((streamBufferSize)<<3,buffer,&bibError);
                    }
                }
            /* update TR values */
            efftr = (videoClipNumber>0 || smSpeed!=1000) ? newtr : tr; 
            *trP = efftr;
            *trD = tr; 
        }
    }
    
    *fFirstFrame = 0;

    if (retValue < 0)
        goto freeBufferAndReturn;   
        /* See the comment above.
        else if (retValue == H263D_OK_EOS)
        break;
   } */

    if (frameSize)
        *frameSize = bibNumberOfFlushedBytes(buffer) + 
        ((bibNumberOfFlushedBits(buffer) % 8 > 0) ? 1 : 0);

    *outframeSize = outbuffer->numBytesRead; 

        
freeBufferAndReturn:

    int bitError = buffer->error;

    if (hTranscoder)
    {
        delete hTranscoder;
        hTranscoder = NULL;
    }
     
    if ( tmpbuffer == buffer )
        {
        // tmpbuffer was a shortcut to inbuffer, set it to NULL to avoid deleting it
        tmpbuffer = NULL;
        }

    int16 deleteError = 0;
    /* Delete bit buffer */
    bibDelete(buffer, &errorCode);
    if ( errorCode )
        {
        deleteError = errorCode;
        }
    
    /* Delete output bit buffer */
    bibDelete(outbuffer, &errorCode);
    if ( errorCode )
        {
        deleteError = errorCode;
        }

    /* Delete tmp bit buffer, if it was used */
    if ( tmpbuffer )
        {
        bibDelete(tmpbuffer, &errorCode);
        if ( errorCode )
            {
            deleteError = errorCode;
            }
        }
    if(tmpbuf)
        free(tmpbuf);
    
    /* Delete bufEdit */
    bibBufEditDelete(bufEdit, &errorCode);
    if ( errorCode )
        {
        deleteError = errorCode;
        }
    if (deleteError || errorCode)
        return H263D_ERROR;

    if ( bitError )
        {
        return H263D_OK_BUT_FRAME_USELESS;
        }

    return retValue;
}


/* {{-output"h263dGetLatestFrame.txt"}} */
/*
* h263dGetLatestFrame
*    
*
* Parameters:
*    hInstance                  instance data
*    
*    ppy, ppu, ppv              used to return Y, U and V frame pointers
*
*    pLumWidth, pLumHeight      used to return luminance image width and height
*
*    pFrameNum                  used to return frame number
*
* Function:
*    This function returns the latest correctly decoded frame
*    (and some side-information).
*
* Returns:
*    H263D_OK                   if the function was successful
*    H263D_ERROR                if a fatal error, from which the decoder
*                               cannot be restored, has occured
*    H263D_ERROR_HALTED         the instance is halted, it should be closed
*/


int H263D_CC h263dGetLatestFrame(
                                                                 h263dHInstance_t hInstance,
                                                                 u_char **ppy, u_char **ppu, u_char **ppv,
                                                                 int *pLumWidth, int *pLumHeight,
                                                                 int *pFrameNum)
                                                                 /* {{-output"h263dGetLatestFrame.txt"}} */
{
    vdeAssert(hInstance);
    vdeAssert(ppy);
    vdeAssert(ppu);
    vdeAssert(ppv);
    vdeAssert(pLumWidth);
    vdeAssert(pLumHeight);
    vdeAssert(pFrameNum);
    
    return vdeGetLatestFrame(hInstance, ppy, ppu, ppv, pLumWidth, pLumHeight,
        pFrameNum);
}



/* {{-output"h263dIsIntra.txt"}} */
/*
* h263dIsIntra
*    
*
* Parameters:
*    hInstance                  handle of instance data
*    frameStart                 pointer to memory chunk containing a frame
*    frameLength                number of bytes in frame
*
* Function:
*    This function returns 1 if the passed frame is an INTRA frame.
*    Otherwise the function returns 0.
*
* Returns:
*    See above.
*/

int h263dIsIntra(
                                 h263dHInstance_t hInstance,
                                 void *frameStart,
                                 unsigned frameLength)
                                 /* {{-output"h263dIsIntra.txt"}} */
{
    vdeAssert(hInstance);
    vdeAssert(frameStart);
    vdeAssert(frameLength);
    
    return vdeIsINTRA(hInstance, frameStart, frameLength);
}

/* {{-output"h263dOpen.txt"}} */
/*
* h263dOpen
*    
*
* Parameters:
*    openParam                  initialization parameters
*
* Function:
*    This function creates and initializes a new H.263 decoder instance.
*
* Returns:
*    an instance handle if the function was successful
*    NULL if an error occured
*/

h263dHInstance_t H263D_CC h263dOpen(h263dOpen_t *openParam)
/* {{-output"h263dOpen.txt"}} */
{
    vdeAssert(openParam);
    
    /* No extra space needs to be allocated after the VDE instance data
    (of type vdeInstance_t) due to the fact that no thread specific
    data is needed. */
    openParam->freeSpace = 0;
    
    return vdeInit(openParam);
}



int GetNewTrValue(int aTrCurOrig, int* aTrPrevNew, int* aTrPrevOrig, int aSMSpeed)
{
    int trCurNew=0;
    int trDiff=0;
    TReal speedFactor = (TReal)aSMSpeed/1000.0;

    trDiff = aTrCurOrig - *aTrPrevOrig;
    if(trDiff==0)  // if corrupt TR values
        trDiff=1;  
    else if(trDiff<0)  // jump in TR values (change of clip or end of limit)
        trDiff = 3;    // arbitrary, for 10 fps default
    // check for slow motion 
    vdeAssert(aSMSpeed);
    if(aSMSpeed!=1000)
        trDiff = (int)((TReal)trDiff/speedFactor + 0.5);
    trCurNew = *aTrPrevNew + trDiff; 
    if(trCurNew>255)
        trCurNew = trCurNew%256;
    return trCurNew;
}



// End of File