Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
322
QTFileTools/RTPFileGen.tproj/RTPFileGen.cpp
Normal file
322
QTFileTools/RTPFileGen.tproj/RTPFileGen.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "SafeStdLib.h"
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef __MacOSX__
|
||||
#include "getopt.h"
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "RTPFileDefs.h"
|
||||
#include "QTRTPFile.h"
|
||||
#include "QTHintTrack.h"
|
||||
#include "OSHeaders.h"
|
||||
|
||||
|
||||
class QTRTPGenFile : public QTRTPFile
|
||||
{
|
||||
public:
|
||||
|
||||
QTRTPGenFile() : QTRTPFile() {}
|
||||
virtual ~QTRTPGenFile() {}
|
||||
|
||||
// Accessors
|
||||
UInt32 GetNumHintTracks() { return fNumHintTracks; }
|
||||
RTPTrackListEntry* GetFirstTrack() { return fFirstTrack; }
|
||||
};
|
||||
|
||||
|
||||
UInt8* WriteTempFile(QTRTPFile* inQTRTPFile, int inTempFile, UInt32* outNumBlocks);
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
qtss_printf("Usage: rtpfilegen *hintedqtfilename*\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char* theFileName = argv[1];
|
||||
|
||||
QTRTPFile::Initialize();
|
||||
|
||||
// Init our qt file
|
||||
QTRTPGenFile theFile;
|
||||
QTRTPFile::ErrorCode initErr = theFile.Initialize(theFileName);
|
||||
switch (initErr)
|
||||
{
|
||||
case QTRTPFile::errFileNotFound:
|
||||
qtss_printf("Movie file not found\n"); exit(0);
|
||||
case QTRTPFile::errInvalidQuickTimeFile:
|
||||
qtss_printf("File is not a hinted quicktime file\n"); exit(0);
|
||||
case QTRTPFile::errNoHintTracks:
|
||||
qtss_printf("File has no hint tracks\n"); exit(0);
|
||||
case QTRTPFile::errInternalError:
|
||||
qtss_printf("Internal error\n"); exit(0);
|
||||
|
||||
case QTRTPFile::errNoError:
|
||||
case QTRTPFile::errTrackIDNotFound:
|
||||
case QTRTPFile::errCallAgain:
|
||||
//noops
|
||||
break;
|
||||
}
|
||||
|
||||
// Open our output file
|
||||
char* outputFileName = new char[::strlen(theFileName) + 5];
|
||||
::strcpy(outputFileName, theFileName);
|
||||
::strcat(outputFileName, ".rtp");
|
||||
int theOutFile = open(outputFileName, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
if (theOutFile == -1)
|
||||
{ qtss_printf("Failed to open output file at %s.\n", outputFileName); exit(0); }
|
||||
|
||||
// Open a temp file
|
||||
char* tempFileName = new char[::strlen(theFileName) + 6];
|
||||
::strcpy(tempFileName, theFileName);
|
||||
::strcat(tempFileName, ".temp");
|
||||
int theTempFile = open(tempFileName, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
if (theTempFile == -1)
|
||||
{ qtss_printf("Failed to open temp file at %s.\n", tempFileName); exit(0); }
|
||||
|
||||
// Setup all our tracks
|
||||
UInt32 theMaxTrackID = 0; // These variables are needed to write the file header
|
||||
UInt32 theNumTracks = 0;
|
||||
QTRTPFile::RTPTrackListEntry* curTrack = theFile.GetFirstTrack();
|
||||
while (curTrack != NULL)
|
||||
{
|
||||
if (theMaxTrackID < curTrack->TrackID)
|
||||
theMaxTrackID = curTrack->TrackID;
|
||||
|
||||
theNumTracks++;
|
||||
(void)theFile.AddTrack(curTrack->TrackID);
|
||||
// Make the cookie be the track ID, so we know what the track ID is when
|
||||
// we are retreiving packets
|
||||
theFile.SetTrackCookies(curTrack->TrackID, (void*) NULL, curTrack->TrackID);
|
||||
|
||||
curTrack = curTrack->NextTrack;
|
||||
}
|
||||
|
||||
// Seek to time 0
|
||||
(void)theFile.Seek(0);
|
||||
|
||||
// Write status
|
||||
qtss_printf("Generating RTP packets to temp file at %s...\n", tempFileName);
|
||||
|
||||
// Write out all the packets to the temp file
|
||||
UInt32 theNumBlocks = 0;
|
||||
UInt8* theBlockArray = WriteTempFile(&theFile, theTempFile, &theNumBlocks);
|
||||
::close(theTempFile);
|
||||
|
||||
// Write status
|
||||
qtss_printf("Generating RTP file at %s. Copying packets...\n", outputFileName);
|
||||
|
||||
// Get SDP
|
||||
int theSDPLen = 0;
|
||||
char* theSDPFile = theFile.GetSDPFile(&theSDPLen);
|
||||
|
||||
// Write file header
|
||||
RTPFileHeader theHeader;
|
||||
theHeader.fSDPLen = theSDPLen;
|
||||
theHeader.fNumTracks = theFile.GetNumHintTracks();
|
||||
theHeader.fMaxTrackID = theMaxTrackID;
|
||||
theHeader.fBlockMapSize = theNumBlocks;
|
||||
theHeader.fDataStartPos = theNumBlocks + theSDPLen + sizeof(RTPFileHeader) +
|
||||
(sizeof(RTPFileTrackInfo) * theNumTracks);
|
||||
theHeader.fMovieDuration = theFile.GetMovieDuration();
|
||||
|
||||
int theErr = ::write(theOutFile, &theHeader, sizeof(theHeader));
|
||||
if (theErr != sizeof(theHeader))
|
||||
{ qtss_printf("Write operation failed on output file\n"); exit(0); }
|
||||
|
||||
// Write the SDP data
|
||||
theErr = ::write(theOutFile, theSDPFile, theSDPLen);
|
||||
if (theErr != theSDPLen)
|
||||
{ qtss_printf("Write operation failed on output file\n"); exit(0); }
|
||||
|
||||
// Write track info
|
||||
curTrack = theFile.GetFirstTrack();
|
||||
while (curTrack != NULL)
|
||||
{
|
||||
RTPFileTrackInfo theTrackInfo;
|
||||
theTrackInfo.fID = curTrack->TrackID;
|
||||
theTrackInfo.fTimescale = curTrack->HintTrack->GetRTPTimescale();
|
||||
theTrackInfo.fBytesInTrack = curTrack->HintTrack->GetTotalRTPBytes();
|
||||
theTrackInfo.fDuration = curTrack->HintTrack->GetDurationInSeconds();
|
||||
|
||||
theErr = ::write(theOutFile, &theTrackInfo, sizeof(theTrackInfo));
|
||||
if (theErr != sizeof(theTrackInfo))
|
||||
{ qtss_printf("Write operation failed on output file\n"); exit(0); }
|
||||
|
||||
curTrack = curTrack->NextTrack;
|
||||
}
|
||||
|
||||
// Write the block map
|
||||
UInt32 numWritten = ::write(theOutFile, theBlockArray, theNumBlocks);
|
||||
if (numWritten != theNumBlocks)
|
||||
{ qtss_printf("Write operation failed on output file\n"); exit(0); }
|
||||
|
||||
//Copy the temp file into the out file
|
||||
theTempFile = open(tempFileName, O_RDONLY);
|
||||
if (theTempFile == -1)
|
||||
{ qtss_printf("Failed to open temp file for reading at %s.\n", tempFileName); exit(0); }
|
||||
|
||||
while (true)
|
||||
{
|
||||
char copyBuffer[kBlockSize];
|
||||
|
||||
// Read a block out of the temp file
|
||||
theErr = ::read(theTempFile, ©Buffer[0], kBlockSize);
|
||||
if (theErr <= 0)
|
||||
break;
|
||||
|
||||
int lenWritten = ::write(theOutFile, ©Buffer[0], theErr);
|
||||
if (theErr != lenWritten)
|
||||
{ qtss_printf("Write operation failed on output file\n"); exit(0); }
|
||||
}
|
||||
|
||||
qtss_printf("RTP file generation complete\n");
|
||||
|
||||
// Delete the temp file
|
||||
(void)::unlink(tempFileName);
|
||||
|
||||
// close the output file
|
||||
::close(theOutFile);
|
||||
|
||||
// We're done!
|
||||
}
|
||||
|
||||
|
||||
// Returns the complete block map
|
||||
UInt8* WriteTempFile(QTRTPFile* inQTRTPFile, int inTempFile, UInt32* outNumBlocks)
|
||||
{
|
||||
int theErr = -1;
|
||||
UInt32 theNumPackets = 0;
|
||||
|
||||
// Write all packets to the temp file. Pad out blocks appropriately
|
||||
UInt32 offsetInBlock = 0;
|
||||
|
||||
// As we write out packets, build our block map
|
||||
UInt8* theBlockMap = new UInt8[1024];
|
||||
UInt32 curBlockMapSize = 1024;
|
||||
UInt32 curBlockMapIndex = 0;
|
||||
Float64 theLastBlockTime = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
RTPFilePacket thePacketHeader;
|
||||
char* thePacketData = NULL;
|
||||
int thePacketLength = 0;
|
||||
|
||||
thePacketHeader.fTransmitTime = inQTRTPFile->GetNextPacket(&thePacketData, &thePacketLength);
|
||||
if (thePacketData == NULL)
|
||||
// We're done with all tracks
|
||||
break;
|
||||
|
||||
thePacketHeader.fPacketLength = thePacketLength;
|
||||
thePacketHeader.fTrackID = inQTRTPFile->GetLastPacketTrack()->Cookie2;
|
||||
|
||||
// Make sure there is enough room in the current block for this
|
||||
// packet plus a header for the next packet. If not, move onto the next block
|
||||
if ((offsetInBlock + thePacketHeader.fPacketLength + (2 * sizeof(RTPFilePacket))) > kBlockSize)
|
||||
{
|
||||
// Write out a pad packet
|
||||
RTPFilePacket pad;
|
||||
pad.fTrackID |= kPaddingBit;
|
||||
|
||||
theErr = ::write(inTempFile, &pad, sizeof(pad));
|
||||
if (theErr < (int) sizeof(pad))
|
||||
{ qtss_printf("Write operation failed on temp file\n"); exit(0); }
|
||||
|
||||
offsetInBlock += sizeof(pad);
|
||||
SInt32 spaceRemaining = kBlockSize - offsetInBlock;
|
||||
Assert(spaceRemaining >= 0);
|
||||
|
||||
// Fill out the rest of this block with crap
|
||||
char* dumpBuf = new char[spaceRemaining];
|
||||
::memset(dumpBuf, 0xFF, spaceRemaining);//Fill with FFs so we can debug easier
|
||||
theErr = ::write(inTempFile, dumpBuf, spaceRemaining);
|
||||
if (theErr < spaceRemaining)
|
||||
{ qtss_printf("Write operation failed on temp file\n"); exit(0); }
|
||||
|
||||
delete [] dumpBuf;
|
||||
|
||||
offsetInBlock = 0;
|
||||
}
|
||||
|
||||
// If this is the first packet in a block, we should mark the time in the
|
||||
// Write the packet header and the packet data
|
||||
if (offsetInBlock == 0)
|
||||
{
|
||||
// What is the offset between the first packet in the last block and this block?
|
||||
Float64 theOffset = thePacketHeader.fTransmitTime - theLastBlockTime;
|
||||
if (theOffset < 0)
|
||||
theOffset = 0; //This may happen with the stupid negative times
|
||||
theLastBlockTime = thePacketHeader.fTransmitTime;
|
||||
if (theLastBlockTime < 0)
|
||||
theLastBlockTime = 0; //This may happen with the stupid negative times
|
||||
|
||||
Assert(theOffset < 255);
|
||||
theBlockMap[curBlockMapIndex] = (UInt8)theOffset;
|
||||
|
||||
// We may need to reallocate the block array
|
||||
curBlockMapIndex++;
|
||||
if (curBlockMapIndex == curBlockMapSize)
|
||||
{
|
||||
UInt8* newBlockArray = new UInt8[curBlockMapSize * 2];
|
||||
::memcpy(newBlockArray, theBlockMap, curBlockMapSize);
|
||||
curBlockMapSize *= 2;
|
||||
|
||||
delete [] theBlockMap;
|
||||
theBlockMap = newBlockArray;
|
||||
}
|
||||
}
|
||||
|
||||
theNumPackets++;
|
||||
theErr = ::write(inTempFile, &thePacketHeader, sizeof(thePacketHeader));
|
||||
if (theErr < (int) sizeof(thePacketHeader))
|
||||
{ qtss_printf("Write operation failed on temp file\n"); exit(0); }
|
||||
|
||||
theErr = ::write(inTempFile, thePacketData, thePacketLength);
|
||||
if (theErr < thePacketLength)
|
||||
{ qtss_printf("Write operation failed on temp file\n"); exit(0); }
|
||||
|
||||
// update our block offset
|
||||
offsetInBlock += thePacketLength + sizeof(thePacketHeader);
|
||||
}
|
||||
|
||||
qtss_printf("Finished writing packets. Wrote %"_U32BITARG_" packets to temp file.\n", theNumPackets);
|
||||
*outNumBlocks = curBlockMapIndex-1;
|
||||
return theBlockMap;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue