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; }
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; }