[PXCDD-commit] SF.net SVN: pxcdd: [361] trunk/server/pxcqtassy
Status: Alpha
Brought to you by:
tangentsoft
From: <tan...@us...> - 2006-07-06 05:03:19
|
Revision: 361 Author: tangentsoft Date: 2006-07-05 22:03:11 -0700 (Wed, 05 Jul 2006) ViewCVS: http://svn.sourceforge.net/pxcdd/?rev=361&view=rev Log Message: ----------- Added timecode track creation code. It builds, runs without error, and follows the example...and fails to work. It's got to be *close*. Modified Paths: -------------- trunk/server/pxcqtassy/main.m trunk/server/pxcqtassy/qttimecode.h trunk/server/pxcqtassy/qttimecode.m trunk/server/pxcqtassy/qtvideo.h trunk/server/pxcqtassy/qtvideo.m Modified: trunk/server/pxcqtassy/main.m =================================================================== --- trunk/server/pxcqtassy/main.m 2006-07-04 21:29:22 UTC (rev 360) +++ trunk/server/pxcqtassy/main.m 2006-07-06 05:03:11 UTC (rev 361) @@ -74,11 +74,12 @@ BOOL success = NO; @try { + QTMovie* movie; NSString* fileSpec; NSString* movieFileName; if (ParseCommandLine(argc, argv, &fileSpec, &movieFileName) && - CreateVideoTrack(movieFileName, fileSpec) && - CreateTimecodeTrack() && + CreateVideoTrack(&movie, movieFileName, fileSpec) && + AddTimecodeTrackToMovie(movie) && CloseMovie()) { success = YES; } Modified: trunk/server/pxcqtassy/qttimecode.h =================================================================== --- trunk/server/pxcqtassy/qttimecode.h 2006-07-04 21:29:22 UTC (rev 360) +++ trunk/server/pxcqtassy/qttimecode.h 2006-07-06 05:03:11 UTC (rev 361) @@ -8,6 +8,6 @@ #include <Cocoa/Cocoa.h> -BOOL CreateTimecodeTrack(); +BOOL AddTimecodeTrackToMovie(); #endif // !defined(QTASSY_QTTIMECODE_H) \ No newline at end of file Modified: trunk/server/pxcqtassy/qttimecode.m =================================================================== --- trunk/server/pxcqtassy/qttimecode.m 2006-07-04 21:29:22 UTC (rev 360) +++ trunk/server/pxcqtassy/qttimecode.m 2006-07-06 05:03:11 UTC (rev 361) @@ -15,10 +15,264 @@ #include <QTKit/QTKit.h> +//////////////////////////////////////////////////////////////////////// +// Constants + +// Height of the frame containing timecode data. Width will be same as +// that of the video frames. +static const int kTimecodeTrackHeight = 50; + + +//// CStrToPascal255 /////////////////////////////////////////////////// +// Converts a C string to a 1-byte length-prefixed Pascal string. + +static void +CStrToPascal255(char* ppstr, const char* pcstr) +{ + size_t len = strlen(pcstr); + *ppstr = (len < 256 ? len : 255); + memcpy(ppstr + 1, pcstr, *ppstr); +} + + +//// GetVideoFrameDimensions /////////////////////////////////////////// +// Returns the dimensions of the video track's frames, so we can size +// the timecode track accordingly. + +static BOOL +GetVideoFrameDimensions(QTMovie* movie, Track* pVideoTrack, + int* pw, int* ph) +{ + // Find first track holding video info + *pVideoTrack = GetMovieIndTrackType([movie quickTimeMovie], 1, + VisualMediaCharacteristic, movieTrackMediaType); + if (*pVideoTrack) { + // Return that track's frame dimensions + Fixed w, h; + GetTrackDimensions(*pVideoTrack, &w, &h); + NSLog(@"Retrieved video track dimensions: %d x %d\n", w, h); + *pw = w; *ph = h; + return YES; + } + else { + return NO; + } +} + + //// CreateTimecodeTrack /////////////////////////////////////////////// -// Adds a timecode track to the QT movie. +// Creates the actual timecode track object. +static BOOL +CreateTimecodeTrack(QTMovie* movie, int frameWidth, QTTrack** ppTrack, + QTMedia** ppMedia, MediaHandler* pHandler) +{ + NSError* qtError; + Track track = NewMovieTrack([movie quickTimeMovie], frameWidth, + kTimecodeTrackHeight, kNoVolume); + if (track) { + Media media; + *ppTrack = [QTTrack trackWithQuickTimeTrack:track + error:&qtError]; + media = NewTrackMedia(track, TimeCodeMediaType, + GetMovieTimeScale([movie quickTimeMovie]), NULL, 0); + if (media) { + *ppMedia = [QTMedia mediaWithQuickTimeMedia:media + error:&qtError]; + *pHandler = GetMediaHandler([*ppMedia quickTimeMedia]); + if (*pHandler) { + return YES; + } + else { + NSLog(@"Failed to retrieve handler for QuickTime " + "timecode media!\n"); + return NO; + } + } + else { + NSLog(@"Failed to create QuickTime media for timecode " + "track: %@\n", [qtError localizedDescription]); + return NO; + } + } + else { + NSLog(@"Failed to create QuickTime timecode track: %@\n", + [qtError localizedDescription]); + return NO; + } +} + + +//// SetupTimecodeTrack //////////////////////////////////////////////// +// Sets up the parameters of the timecode track. + +static BOOL +SetupTimecodeTrack(QTTrack* track, MediaHandler handler, + int frameHeight, TimeCodeDef* pTCDef) +{ + MatrixRecord matrix; + + // Set up timecode definition: 30 fps, maximum 24 hours + pTCDef->flags = tc24HourMax; + pTCDef->fTimeScale = 600; + pTCDef->frameDuration = 20; + pTCDef->numFrames = 30; + + // Position timecode frame below video content + GetTrackMatrix([track quickTimeTrack], &matrix); + TranslateMatrix(&matrix, 0, frameHeight); + SetTrackMatrix([track quickTimeTrack], &matrix); + + // Make timecode track visible + SetTrackEnabled([track quickTimeTrack], YES); + TCSetTimeCodeFlags(handler, tcdfShowTimeCode, tcdfShowTimeCode); + + return YES; +} + + +//// GetVideoTrackDuration ///////////////////////////////////////////// +// Grab video track's duration. We don't need to do any conversion in +// here because the timecode track is created with the same time base +// as the video track. If they diverge, this will break. + +static TimeValue +GetVideoTrackDuration(QTMovie* movie) +{ + return GetMovieDuration([movie quickTimeMovie]); +} + + +//// AddTimeCodeSample ///////////////////////////////////////////////// +// Adds a media sample to the timecode track. We add just one, with the +// time being zero, which causes QuickTime to simply count up from there +// through the end of the video. + +static BOOL +AddTimeCodeSample(QTMedia* media, TimeValue duration, TimeCodeDef tcDef, + MediaHandler handler) +{ + OSErr err; + BOOL bSuccess = NO; + Handle frameHandle = 0; + TimeCodeDescriptionHandle tcDesc = 0; + + if ((err = BeginMediaEdits([media quickTimeMedia])) == noErr) { + long tcSize = sizeof(TimeCodeDescription); + tcDesc = (TimeCodeDescriptionHandle)NewHandleClear(tcSize); + if (tcDesc) { + UserData userData; + + // Create a handle object to store a frame count + frameHandle = NewHandle(sizeof(SInt32)); + if (!frameHandle) { + NSLog(@"Failed to create frame handle!!\n"); + goto bail; + } + + // Set up timecode description record + (**tcDesc).descSize = tcSize; + (**tcDesc).dataFormat = TimeCodeMediaType; + (**tcDesc).timeCodeDef = tcDef; + + if ((err = NewUserData(&userData)) == noErr) { + // Store the media name info in the timecode sample + UserData userData; + char sourceName[256]; + Handle nameHandle = 0; + + CStrToPascal255(sourceName, "?? the source name ??"); + if ((PtrToHand(sourceName + 1, &nameHandle, + sourceName[0]) == noErr) && + (AddUserDataText(userData, nameHandle, + TCSourceRefNameType, 1, langEnglish) == + noErr)) { + TCSetSourceRef(handler, tcDesc, userData); + } + + // Clean up + if (nameHandle) { + DisposeHandle(nameHandle); + } + DisposeUserData(userData); + } + + //// Add starting time sample to timecode track + // Create timecode record, all zeroes, meaning that this + // is the start of the movie. + TimeCodeRecord tcRec; + memset(&tcRec, 0, sizeof(TimeCodeRecord)); + + // Convert timecode record info to a frame number, in + // big-endian byte order. + TCTimeCodeToFrameNumber(handler, + &(**tcDesc).timeCodeDef, &tcRec, + (long*)*frameHandle); + **frameHandle = EndianS32_NtoB(**frameHandle); + + // Finally, add the timecode sample + if (AddMediaSample([media quickTimeMedia], frameHandle, 0, + GetHandleSize(frameHandle), duration, + (SampleDescriptionHandle)tcDesc, 1, 0, 0) == + noErr) { + bSuccess = YES; + } + else { + NSLog(@"Failed to add timecode sample!\n"); + } + } + } + +bail: + if (tcDesc) { + DisposeHandle((Handle)tcDesc); + } + + if (frameHandle) { + DisposeHandle(frameHandle); + } + + return (EndMediaEdits([media quickTimeMedia]) == noErr) && bSuccess; +} + + +//// FinalizeTimecodeTrack ///////////////////////////////////////////// +// Insert the timecode media into the timecode track, and tie the +// timecode track to the video track. + +static BOOL +FinalizeTimecodeTrack(QTTrack* tcTrack, Track videoTrack, + TimeValue duration) +{ + return (InsertMediaIntoTrack([tcTrack quickTimeTrack], 0, 0, + duration, fixed1) == noErr) && (AddTrackReference( + videoTrack, [tcTrack quickTimeTrack], TimeCodeMediaType, + NULL) == noErr); +} + + +//// AddTimecodeTrackToMovie /////////////////////////////////////////// +// Adds a timecode track to the given QT movie. This is based loosely +// on QTTC_AddTimeCodeToMovie() in the sample referenced above. + BOOL -CreateTimecodeTrack() +AddTimecodeTrackToMovie(QTMovie* movie) { + int frameWidth, frameHeight; + QTTrack* tcTrack; + Track videoTrack; + QTMedia* tcMedia; + MediaHandler handler; + TimeCodeDef tcDef; + + TimeValue duration = GetVideoTrackDuration(movie); + NSLog(@"Movie duration: %d time units\n", duration); + + return GetVideoFrameDimensions(movie, &videoTrack, &frameWidth, + &frameHeight) && + CreateTimecodeTrack(movie, frameWidth, &tcTrack, &tcMedia, + &handler) && + SetupTimecodeTrack(tcTrack, handler, frameHeight, &tcDef) && + AddTimeCodeSample(tcMedia, duration, tcDef, handler) && + FinalizeTimecodeTrack(tcTrack, videoTrack, duration); } Modified: trunk/server/pxcqtassy/qtvideo.h =================================================================== --- trunk/server/pxcqtassy/qtvideo.h 2006-07-04 21:29:22 UTC (rev 360) +++ trunk/server/pxcqtassy/qtvideo.h 2006-07-06 05:03:11 UTC (rev 361) @@ -6,9 +6,10 @@ #if !defined(QTASSY_QTVIDEO_H) #define QTASSY_QTVIDEO_H -#include <Cocoa/Cocoa.h> +#include <QTKit/QTKit.h> -BOOL CreateVideoTrack(NSString* movieFileName, NSString* fileSpec); +BOOL CreateVideoTrack(QTMovie** ppMovie, NSString* movieFileName, + NSString* fileSpec); BOOL CloseMovie(); #endif // !defined(QTASSY_QTVIDEO_H) \ No newline at end of file Modified: trunk/server/pxcqtassy/qtvideo.m =================================================================== --- trunk/server/pxcqtassy/qtvideo.m 2006-07-04 21:29:22 UTC (rev 360) +++ trunk/server/pxcqtassy/qtvideo.m 2006-07-06 05:03:11 UTC (rev 361) @@ -19,7 +19,6 @@ #include <AppKit/AppKit.h> #include <CoreFoundation/CoreFoundation.h> -#include <QTKit/QTKit.h> #include <unistd.h> #include <glob.h> @@ -187,14 +186,14 @@ // Call the above functions in the appropriate order. BOOL -CreateVideoTrack(NSString* movieFileName, NSString* fileSpec) +CreateVideoTrack(QTMovie** ppMovie, NSString* movieFileName, + NSString* fileSpec) { NSDictionary* encParms; - QTMovie* movie; return CreateTemporaryMovieFile() && CreateEncodingParameters(&encParms) && - CreateMovieObject(&movie, &gOutDataHandler) && - AddImages(movie, fileSpec, encParms) && - WriteMovieFile(movie, movieFileName, encParms); + CreateMovieObject(ppMovie, &gOutDataHandler) && + AddImages(*ppMovie, fileSpec, encParms) && + WriteMovieFile(*ppMovie, movieFileName, encParms); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |