サウンドファイルを再生しようとしても何も起こらないQ: QTKitを使用してサウンドファイルを開き、再生しようとしましたが、何も起こりません。 まったく何の音も聞こえません。 しかし、
QTMovie *aMovie;
QTMovieView *aMovieView;
aMovie = [QTMovie movieWithFile:s error:nil];
[aMovie setVolume: volumeVal];
// [aMovieView setMovie:aMovie]; // これをすると正常に機能する!
[aMovie play];
A: 次のコード行で、自動解放(
aMovie = [QTMovie movieWithFile:s error:nil];
実行ループに再び入ると、オブジェクトが破棄されます。これがオブジェクトを再び使用しようとしても何も起こらない理由です。
自動解放プールに置かれないように、代わりに
QTMovie* aMovie;
aMovie = [[QTMovie alloc] initWithFile:s error:nil];
[aMovie setVolume: volumeVal];
[aMovie play];
... /* ここ何かする */
[aMovie release]; // 用済みになったらオブジェクトを解放する
あるいは、元のコードのように
QTMovie* aMovie;
aMovie = [QTMovie movieWithFile:s error:nil];
[aMovie retain]; // オブジェクトを保持する
[aMovie setVolume: volumeVal];
[aMovie play];
... /* ここ何かする */
[aMovie release]; // 用済みになったらオブジェクトを解放する
QTMovieにQTTrackを追加するにはQ: A: 現在のところ、 それまでは、標準のQuickTime API(すなわち、 そのために実行する必要があることの概略は以下のとおりです。
以下のコードにその方法を示します。 リスト1: QTMovieへのQTTrackの追加
@implementation QTMovie (QTMovieExtensions)
-(BOOL)isEditable
{
NSDictionary *movieDict = [self movieAttributes];
NSNumber *isEditable = [movieDict objectForKey:QTMovieEditableAttribute];
return [isEditable boolValue];
}
- (QTTrack *) addVideoTrackWithSize:(NSSize) aSize
{
QTTrack *newTrack = nil;
require( [self isEditable] == YES, NOT_EDITABLE);
Track videoTrack = NewMovieTrack ([self quickTimeMovie],
FixRatio (aSize.width, 1),
FixRatio(aSize.height, 1),
kFullVolume);
require (GetMoviesError() == noErr, NEWTRACK_ERROR);
Handle dataRef = NULL;
Handle hMovieData = NewHandle (0);
require (hMovieData != nil, NEWHANDLE_ERR);
OSErr osErr = PtrToHand (&hMovieData, &dataRef, sizeof(Handle));
require (osErr == noErr, PTRTOHAND_ERROR);
Media videoMedia = NewTrackMedia (videoTrack,
VideoMediaType,
[[self timeScale] longValue],
dataRef,
HandleDataHandlerSubType);
require (GetMoviesError() == noErr, TRACKMEDIA_ERROR);
QTTime movieDuration = [self duration];
InsertMediaIntoTrack (videoTrack, 0, 0, movieDuration.timeValue, fixed1);
require (GetMoviesError() == noErr, INSERTMEDIA_ERROR);
newTrack = [QTTrack trackWithQuickTimeTrack: videoTrack error:nil];
return newTrack;
INSERTMEDIA_ERROR:
DisposeTrackMedia(videoMedia);
TRACKMEDIA_ERROR:
PTRTOHAND_ERROR:
DisposeHandle(hMovieData);
NEWHANDLE_ERR:
DisposeMovieTrack (videoTrack);
NEWTRACK_ERROR:
NOT_EDITABLE:
return nil;
}
@end
QTMovieTimeDidChangeNotification通知はいつ発行されるかQ: A: たとえば、ユーザがムービーコントローラバーをクリックしてムービー時間を変えたときや、ワイヤードアクションによってムービー時間が変わったときに発行されます。 代わりに、 空のムービーを作成して画像を追加するにはQ: 1つの A: はい、そのとおりです。 今後のバージョンのQTKitには、画像を追加できる「空の」ムービー(書き込み可能なデータ参照付きのムービー)を作成する簡単なメソッドが含まれる見込みです。 それまでの間は、2つの対処法があります。 まず、QuickTimeのネイティブAPIである 第二に、 リスト2: NSImageからQTMovieを初期化する
// 画像のためのNSImageオブジェクトをインスタンス化する
NSImage *image = [NSImage imageNamed:@"some_image"];
if (image)
{
// すべての表現についてTIFFを含んだデータオブジェクトを返す
NSData *data = [image TIFFRepresentation];
QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToData:data
name:@"some_image.tiff" MIMEType:nil];
// NSImageからQTMovieを作成する
QTMovie *movie = [QTMovie movieWithDataReference:dataRef error:nil];
// ムービーを編集可能にする
[movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
// 再生時間を10秒に設定する
QTTimeRange range = QTMakeTimeRange(QTZeroTime, [movie duration]);
[movie scaleSegment:range newDuration:QTMakeTime(10, 1)];
// 3GPPファイルとしてエクスポートするか、既存のエクスポートコードを使用する....
// ディクショナリに適切なエクスポート属性をセットアップする
NSDictionary *dict= [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], QTMovieExport,
[NSNumber numberWithLong:kQTFileType3GPP], QTMovieExportType, nil];
// QTMovieを3GPPムービーファイルとしてディスクに書き出す
[movie writeToFile:@"/tmp/my3GP.mov" withAttributes:dict];
}
QTMovieをディスク上の新規ファイルにエクスポートするにはQ: ハードディスクに書き出したい 自作のコードを以下に示します。
// マイムービー
QTMovie *movie = [qtPlayer movie];
// コーデックディクショナリ
NSDictionary *codecDictionary =
[NSDictionary dictionaryWithObjectsAndKeys: @"jpeg",
QTAddImageCodecType, [NSNumber numberWithInt: codecNormalQuality],
QTAddImageCodecQuality, nil];
// moviePathも正しい
[movie writeToFile: moviePath withAttributes: codecDictionary];
A:
// writeToFile: 属性ディクショナリキー
QTKIT_EXTERN NSString *QTMovieExport
AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // NSNumber (BOOL)
QTKIT_EXTERN NSString *QTMovieExportType
AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // NSNumber (long)
QTKIT_EXTERN NSString *QTMovieFlatten
AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // NSNumber (BOOL)
QTKIT_EXTERN NSString *QTMovieExportSettings
AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // NSData (QTAtomContainer)
QTKIT_EXTERN NSString *QTMovieExportManufacturer
AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; // NSNumber (long)
次のサンプルは、エクスポート操作の実行方法を示します。 サンプルコードプロジェクト「QTKitCreateMovie」、サンプルコードプロジェクト「QTKitProgressTester」、およびサンプルコードプロジェクト「QTKitCommandLine」。 QuickTimeでサポートしているファイルタイプまたは拡張のリストを取得するにはQ: QuickTimeで扱えるファイルタイプまたは拡張のリストを取得するには、どうすればよいでしょうか。 A: これは問題なく機能します。また、 ただし、もっと簡単な方法もあります。それは
- (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename
{
BOOL isDir = NO;
[[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isDir];
return isDir ? YES : [QTMovie canInitWithFile:filename];
}
この方法は、 QTMakeTimeFromString/QTTimeFromString関数がどのように機能するかQ: 現在のドキュメントでは、この関数が QTTime oldTime = [qtMovie currentTime]; QTTime incTime = QTTimeFromString( @"00:02:00.00" ); QTTime newTime = QTTimeIncrement( oldTime, incTime ); NSLog( QTStringFromTime( oldTime ) ); NSLog( QTStringFromTime( incTime ) ); NSLog( QTStringFromTime( newtime ) ); 次のような結果になります。 0:00:00:00.00/48000 0:00:00:00.00/1000000 0:00:00:00.00/1000000 また、時間文字列を 何が間違っているのでしょうか。 A: QTTime.hにある次のコメントに注目してください。 // ,,,dd:hh:mm:ss.ff/ts これは次のような意味になります。 日:時間:分:秒:フレーム/タイムスケール したがって、次のような文字列を使うようにします。 QTTime incTime = QTTimeFromString( @"00:00:02:00.00/600" ); NSLog( QTStringFromTime( incTime ) ); これでうまく機能するはずです。 現在のドキュメントは正しくありません。 QTMovieオブジェクトの形成は完全かQ: 自作のアプリケーションで
A:
これを防ぐには、初期化呼び出しを同期的に行います。 そのためには、
NSSize movieSize;
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(id)url, QTMovieURLAttribute,
[NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
nil];
QTMovie *movie = [QTMovie movieWithAttributes:attrs error:nil];
movieSize = [[movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
[movie play];
...
もう1つの選択肢は、
// QTMovieLoadStateDidChangeNotificationの通知ハンドラをインストールする
QTMovie *movie = [QTMovie movieWithURL:url error:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadStateChanged:) name:QTMovieLoadStateDidChangeNotification object:movie];
.
.
.
// ロード状態の変化をチェックする
-(void)loadStateChanged:(QTMovie *)movie
{
long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
if (loadState >= 20000)
{
// 20000はkMovieLoadStatePlaythroughOK
[movie play];
}
else if (loadState >= 10000)
{
// 10000はkMovieLoadStatePlayable
NSSize movieSize;
movieSize = [[movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
/* ... */
}
else if (loadState == -1)
{
/* エラーが発生、エラーを処理 */
}
}
最終ムービーフレームを見つけるにはQ: ムービーの最終フレームに達したかどうかを判断するには、どうしたらよいのでしょうか。
A: ムービーの最後に達しても、 1つの選択肢は、これらの操作に対して以下に示すような新しいメソッドを持つ独自の
@implementation QTMovie (MyQTMovieExtension)
- (BOOL)rt_stepForward
{
QTTime curTime, newTime;
curTime = [self currentTime];
[self stepForward];
newTime = [self currentTime];
return (QTTimeCompare(curTime, newTime) != NSOrderedSame);
}
- (BOOL)rt_stepBackward
{
QTTime curTime, newTime;
curTime = [self currentTime];
[self stepBackward];
newTime = [self currentTime];
return (QTTimeCompare(curTime, newTime) != NSOrderedSame);
}
@end
バックグラウンドスレッドでQTMovieオブジェクトを使用するにはQ: テクニカルノートTN2125「QuickTimeにおけるスレッドセーフなプログラミング」を読んだばかりなのですが、QTKitについて何も述べられていません。バックグラウンドスレッドで A: バックグラウンドスレッドで (1) この理由はまったく単純なものです。 (2) 異なるスレッドで (3) 二次スレッドで他のQuickTime呼び出しまたはQTKit呼び出しを行う前に、 (4) QuickTime呼び出しを行ったスレッドを終了する前に、 (5) これらの呼び出しのいずれかによるエラーを処理する用意をします。二次スレッドに移動できないムービーもあります(これはコーデックによります)。 QTKitは上記のどれも自動的に実行してくれませんが、アップルでは、このプロセスを簡単にする(少なくともCocoaに似たプロセス)にするいくつかの新しいAPIに取り組んでいます。 以下の短いコードは、バックグラウンドスレッドでムービーのエクスポートを実行する方法を示します。
- (void)doExportOnThread:(QTMovie *)movie
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
EnterMoviesOnThread(0);
AttachMovieToCurrentThread([movie quickTimeMovie]);
// QTKitのバグを回避するために、privateメソッドのsetIdling:を呼び出して、
// ムービーがバックグラウンドスレッドで操作されないようにする
// 必要がある
if ([movie respondsToSelector:@selector(setIdling:)])
[movie setIdling:NO];
// エクスポートを実行する
[movie writeToFile:....];
DetachMovieFromCurrentThread([movie quickTimeMovie]);
ExitMoviesOnThread();
[pool release];
}
QTMovieViewをサブクラス化するにはQ:
A: これはQTKit 1.0の QTMovieがなぜか画面の左上部に描画されるQ: Movie ToolboxのC API A: この問題は、QuickTime Carbon APIとQTKitを併用しているときに発生する可能性のあるものです。 CarbonのネイティブQuickTime APIを使ってムービーを作成するときには、ムービーが表示する位置を認識するように、あらかじめ有効なポートを設定する必要があります。 これについては、次のQ&Aを参照してください。 QA1345「The QuickTime Movie Toolbox requires a valid graphics port for all movies」 この事例で何が起きているかというと、 これを回避するには、
GWorldPtr gworld = NULL;
Rect rect = {0, 0, 1, 1};
NewGWorld(&gworld, 32, &rect, NULL, NULL, 0);
SetMovieGWorld(qtMovie, gworld, NULL);
以降、ムービーは「ダミー」のgworldに描画されるようになります。 ドキュメント改訂履歴
掲載日: 2006-09-25 |
|