Bool16 QTFile_FileControlBlock::ReadInternal(FILE_SOURCE *dataFD, UInt64 inPosition, void* inBuffer, UInt32 inLength, UInt32 *inReadLenPtr)
{
    UInt32 readLen = 0;
    if (NULL != inReadLenPtr)
        *inReadLenPtr = 0;

#if DSS_USE_API_CALLBACKS
    QTSS_Error  theErr = QTSS_Seek(*dataFD, inPosition);
    if (theErr == QTSS_NoErr)
        theErr = QTSS_Read(*dataFD, inBuffer, inLength, &readLen);
    if (theErr != QTSS_NoErr)
        return false;
#else
    if( dataFD->Read(inPosition, inBuffer, inLength, &readLen) != OS_NoErr )
        return false;
#endif
    if (NULL != inReadLenPtr)
        *inReadLenPtr = readLen;

    if(inReadLenPtr == NULL && readLen != inLength) //external reads expect false if it fails to read all the requested data.
        return false;

    return true;
}
Exemple #2
0
RTPFileSession::ErrorCode   RTPFileSession::Seek(Float64 inTime)
{
    if ((inTime < 0) || (inTime > fFile->GetMovieDuration()))
        return errSeekToNonexistentTime;
    
    UInt64 theBlockLocation = fFile->GetBlockLocation(inTime);
    Assert(theBlockLocation >= fFile->fHeader.fDataStartPos);
    Assert(theBlockLocation < fFileLength);
    
    // Seek to the right file location.
    //fFileSource.Seek(theBlockLocation);
    QTSS_Error theErr = QTSS_Seek(fFileSource, theBlockLocation);
    Assert(theErr == QTSS_NoErr);
    fCurrentPosition = theBlockLocation;
    
    // Read the file data
    this->ReadAndAdvise();
    
    for (UInt32 x = 0; x <= fFile->GetMaxTrackNumber(); x++)
        fTrackInfo[x].fMarked = false;
    
    //
    // We need to find out what the first packet is for each enabled track.
    // So scan ahead until we find the very first packet we need to send.
    // At that point, "freeze" the current block in memory, and that position,
    // because that's the position we'll be starting from when GetNextPacket gets
    // called. In order to "freeze" we store lots of info about the current position
    // on the stack with the variables defined below.
    //
    // Keep on going until we find the first packets for all the enabled tracks,
    // and if that involves traversing multiple blocks, keep those blocks in a temporary
    // buffer, allowing us to easily go back to the start point when done.
    
    UInt8* theStartPos = NULL;
    UInt32 origDataBufferLen = 0;
    UInt64 currentFileOffset = 0;
    UInt32 tracksFound = 0;
    
    // Needed to call GetNextPacket
    UInt8* thePacketP = NULL;
    UInt32 thePacketLength = 0;
    void* theCookie = NULL;
    
    while (tracksFound < fNumTracksEnabled)
    {
        Float64 theTransmitTime = this->GetNextPacket(&thePacketP, &thePacketLength, &theCookie);
        if (thePacketP == NULL)
        {
            Assert(tracksFound > 0);
            break; // We're at the end of the file!
        }
        // Ignore < 0 timed packets
        RTPFilePacket* thePacket = (RTPFilePacket*)thePacketP;
        Assert((thePacket - 1)->fTransmitTime == theTransmitTime);
        if (theTransmitTime < 0)
            theTransmitTime = 0;

        UInt32 theTrackID = (thePacket - 1)->fTrackID;
        
        if ((theTransmitTime >= inTime) && (!fTrackInfo[theTrackID].fMarked) &&
            (fTrackInfo[theTrackID].fEnabled))
        {
            // This is the first packet for this track after our fCurrentPtr mark.
            // Record the first seq # and timestamp of the packet
            UInt16* theSeqNumPtr = (UInt16*)thePacketP;
            UInt32* theTimestampPtr = (UInt32*)thePacketP;
            
            fTrackInfo[theTrackID].fSeekSeqNumber = theSeqNumPtr[1];
            fTrackInfo[theTrackID].fSeekTimestamp = theTimestampPtr[1];
            fTrackInfo[theTrackID].fMarked = true;
            
            if (tracksFound == 0)
            {
                //
                // If this is the first packet that we're going to send (for all
                // streams), then mark the position, and make sure that if we
                // need to dump this buffer to find first packets for other tracks,
                // we'll be able to come back to this very place so we can start streaming.
                fReadBuffer = NULL;
                theStartPos = (UInt8*)(thePacket-1);
                origDataBufferLen = fDataBufferLen;
                currentFileOffset = fCurrentPosition;
            }

            tracksFound++;
        }
    }
    
    if (fReadBuffer != NULL)
    {
        // We had to skip ahead in the file. Restore everything to
        // the way it was when we found the first packet, so GetNextPacket
        // will work fine.
        delete [] fReadBuffer;
        fReadBuffer = fDataBuffer;
        Assert(origDataBufferLen > 0);
        fDataBufferLen = origDataBufferLen;
        Assert(currentFileOffset > 0);
        //fFileSource.Seek(currentFileOffset);
        theErr = QTSS_Seek(fFileSource, theBlockLocation);
        Assert(theErr == QTSS_NoErr);
    }
    
    // Start at the first packet we need to send.
    Assert(theStartPos != NULL);
    fCurrentPacket = theStartPos;
    
    return errNoError;
}