2007-06-10 21:34:20 +00:00
|
|
|
//
|
|
|
|
// QuicktimeDecoder.m
|
|
|
|
// Quicktime
|
|
|
|
//
|
|
|
|
// Created by Vincent Spader on 6/10/07.
|
|
|
|
// Copyright 2007 __MyCompanyName__. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "QuicktimeDecoder.h"
|
2007-06-10 22:05:49 +00:00
|
|
|
#import "Quicktime/QuicktimeComponents.h"
|
2007-06-10 21:34:20 +00:00
|
|
|
|
|
|
|
@implementation QuicktimeDecoder
|
|
|
|
|
|
|
|
- (BOOL)open:(id<CogSource>)source
|
|
|
|
{
|
|
|
|
NSLog(@"Opening!");
|
|
|
|
|
|
|
|
NSURL *url = [source url];
|
|
|
|
OSErr error;
|
|
|
|
Handle dataRef;
|
|
|
|
OSType dataRefType;
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"EnterMovies...");
|
|
|
|
EnterMovies();
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"Creating new data reference...");
|
|
|
|
error = QTNewDataReferenceFromCFURL((CFURLRef)url, 0, &dataRef, &dataRefType);
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
|
|
|
|
NSLog(@"Creating new movie...");
|
|
|
|
short fileID = movieInDataForkResID;
|
2007-07-04 15:26:11 +00:00
|
|
|
short flags = 0; //newMovieDontResolveDataRefs | newMovieDontAskUnresolvedDataRefs;
|
2007-06-10 22:21:50 +00:00
|
|
|
error = NewMovieFromDataRef(&_movie, flags, &fileID, dataRef, dataRefType);
|
2007-07-04 14:46:33 +00:00
|
|
|
if (error != noErr) {
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"Setting movie active...");
|
2007-06-10 22:21:50 +00:00
|
|
|
SetMovieActive(_movie, TRUE);
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"Beginning extraction session...");
|
2007-06-10 22:21:50 +00:00
|
|
|
error = MovieAudioExtractionBegin(_movie, 0, &_extractionSessionRef);
|
2007-07-04 14:46:33 +00:00
|
|
|
if (error != noErr) {
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@" %d",error);
|
2007-07-04 14:46:33 +00:00
|
|
|
return NO;
|
2007-06-10 21:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NSLog(@"Getting audio stream basic description (absd)...");
|
|
|
|
error = MovieAudioExtractionGetProperty(_extractionSessionRef,
|
2007-07-04 14:46:33 +00:00
|
|
|
kQTPropertyClass_MovieAudioExtraction_Audio,
|
|
|
|
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
|
|
|
sizeof (_asbd), &_asbd, nil);
|
|
|
|
if (error != noErr) {
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
return NO;
|
2007-06-10 21:34:20 +00:00
|
|
|
}
|
2007-07-04 15:26:11 +00:00
|
|
|
|
2007-07-04 14:46:33 +00:00
|
|
|
NSLog(@"bits per sample: %i", _asbd.mBitsPerChannel);
|
2007-06-10 21:34:20 +00:00
|
|
|
_asbd.mFormatID = kAudioFormatLinearPCM;
|
|
|
|
_asbd.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian;
|
2007-07-04 14:46:33 +00:00
|
|
|
// _asbd.mBitsPerChannel = 8*sizeof(int);
|
2007-06-10 21:34:20 +00:00
|
|
|
_asbd.mBytesPerFrame = (_asbd.mBitsPerChannel/8) * _asbd.mChannelsPerFrame;
|
|
|
|
_asbd.mBytesPerPacket = _asbd.mBytesPerFrame;
|
|
|
|
_asbd.mFramesPerPacket = 1;
|
|
|
|
|
|
|
|
NSLog(@"Setting new _asbd...");
|
|
|
|
error = MovieAudioExtractionSetProperty(_extractionSessionRef,
|
2007-07-04 14:46:33 +00:00
|
|
|
kQTPropertyClass_MovieAudioExtraction_Audio,
|
|
|
|
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
|
|
|
sizeof (_asbd), &_asbd);
|
|
|
|
if (error != noErr) {
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
/* THIS IS BROKEN
|
|
|
|
error = MovieAudioExtractionGetProperty(_extractionSessionRef,
|
|
|
|
kQTPropertyClass_SoundDescription,
|
|
|
|
kQTSoundDescriptionPropertyID_BitRate,
|
|
|
|
sizeof(_bitrate),&_bitrate,nil);
|
|
|
|
if (error != noErr) {
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
_bitrate = 0;
|
|
|
|
}
|
|
|
|
*/
|
2007-06-10 21:34:20 +00:00
|
|
|
|
2007-06-10 22:21:50 +00:00
|
|
|
_totalFrames = _asbd.mSampleRate * ((float) GetMovieDuration(_movie) / (float) GetMovieTimeScale(_movie));
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
[self willChangeValueForKey:@"properties"];
|
|
|
|
[self didChangeValueForKey:@"properties"];
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) fillBuffer:(void *)buf ofSize:(UInt32)size
|
|
|
|
{
|
|
|
|
OSErr error;
|
|
|
|
UInt32 extractionFlags = 0;
|
|
|
|
AudioBufferList buffer;
|
|
|
|
UInt32 numFrames = size / _asbd.mBytesPerFrame;
|
|
|
|
|
|
|
|
buffer.mNumberBuffers = 1;
|
|
|
|
buffer.mBuffers[0].mNumberChannels = _asbd.mChannelsPerFrame;
|
|
|
|
buffer.mBuffers[0].mDataByteSize = size;
|
|
|
|
|
|
|
|
buffer.mBuffers[0].mData = buf;
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
error = MovieAudioExtractionFillBuffer(_extractionSessionRef, &numFrames, &buffer, &extractionFlags);
|
|
|
|
if (error) {
|
|
|
|
NSLog(@" %d",error);
|
|
|
|
NSLog(@" Extraction flags = %d (complete? %d)",extractionFlags,kQTMovieAudioExtractionComplete);
|
|
|
|
}
|
|
|
|
|
|
|
|
return numFrames * _asbd.mBytesPerFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)close
|
|
|
|
{
|
|
|
|
OSErr error;
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"Ending extraction session...");
|
|
|
|
error = MovieAudioExtractionEnd(_extractionSessionRef);
|
|
|
|
NSLog(@" %d",error);
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
NSLog(@"ExitMovies...");
|
|
|
|
ExitMovies();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (double) seekToTime:(double)milliseconds
|
|
|
|
{
|
2007-06-10 22:21:50 +00:00
|
|
|
OSErr error;
|
|
|
|
TimeRecord timeRec;
|
|
|
|
|
|
|
|
timeRec.scale = GetMovieTimeScale(_movie);
|
|
|
|
timeRec.base = NULL;
|
|
|
|
timeRec.value.hi = 0;
|
|
|
|
timeRec.value.lo = (milliseconds/1000.0) * timeRec.scale;
|
|
|
|
|
|
|
|
error = MovieAudioExtractionSetProperty(_extractionSessionRef, kQTPropertyClass_MovieAudioExtraction_Movie, kQTMovieAudioExtractionMoviePropertyID_CurrentTime, sizeof(timeRec), &timeRec);
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
NSLog(@"Error seeking! %i", error);
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return milliseconds;
|
2007-06-10 21:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray *)fileTypes
|
|
|
|
{
|
2007-06-10 22:05:49 +00:00
|
|
|
NSMutableArray *extensions = [NSMutableArray array];
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
Component component = NULL;
|
|
|
|
ComponentDescription looking;
|
|
|
|
NSCharacterSet *spaceSet = [NSCharacterSet characterSetWithCharactersInString:@" '"];
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
looking.componentType = MovieImportType;
|
|
|
|
looking.componentSubType = 0; // Any subtype is OK
|
|
|
|
looking.componentManufacturer = 0; // Any manufacturer is OK
|
|
|
|
looking.componentFlags = movieImportSubTypeIsFileExtension;
|
|
|
|
looking.componentFlagsMask = movieImportSubTypeIsFileExtension;
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
while (component = FindNextComponent(component, &looking)) {
|
|
|
|
ComponentDescription description;
|
|
|
|
|
|
|
|
if (GetComponentInfo(component, &description, NULL, NULL, NULL) == noErr) {
|
|
|
|
|
|
|
|
NSString *HFSType = NSFileTypeForHFSTypeCode(description.componentSubType);
|
|
|
|
|
|
|
|
NSLog(@"Extension?: %@", HFSType);
|
|
|
|
[extensions addObject:[HFSType stringByTrimmingCharactersInSet:spaceSet]];
|
|
|
|
|
|
|
|
// the extension is present in the description.componentSubType field, which really holds
|
|
|
|
// a 32-bit number. you need to convert that to a string, and trim off any trailing spaces.
|
|
|
|
// here's a quickie...
|
|
|
|
char ext[5] = {0};
|
|
|
|
NSString *extension;
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
bcopy(&description.componentSubType, ext, 4);
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
extension = [[NSString stringWithCString:ext] stringByTrimmingCharactersInSet:spaceSet];
|
2007-07-04 14:46:33 +00:00
|
|
|
|
2007-06-10 22:05:49 +00:00
|
|
|
// do something with extension here ...
|
|
|
|
[extensions addObject:extension];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return extensions;
|
2007-06-10 21:34:20 +00:00
|
|
|
}
|
|
|
|
|
2007-10-14 18:39:58 +00:00
|
|
|
+ (NSArray *)mimeTypes
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2007-06-10 21:34:20 +00:00
|
|
|
- (NSDictionary *)properties
|
|
|
|
{
|
|
|
|
return [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
[NSNumber numberWithInt:_asbd.mChannelsPerFrame],@"channels",
|
|
|
|
[NSNumber numberWithInt:_asbd.mBitsPerChannel],@"bitsPerSample",
|
2007-07-04 14:46:33 +00:00
|
|
|
[NSNumber numberWithInt:0/*_bitrate*/],@"bitrate",
|
2007-06-10 21:34:20 +00:00
|
|
|
[NSNumber numberWithFloat:_asbd.mSampleRate],@"sampleRate",
|
|
|
|
[NSNumber numberWithDouble:_totalFrames/(_asbd.mSampleRate/1000.0)],@"length",
|
2007-06-10 22:21:50 +00:00
|
|
|
[NSNumber numberWithBool:YES], @"seekable",
|
2007-06-10 21:34:20 +00:00
|
|
|
@"big", @"endian",
|
|
|
|
nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@end
|