1

以下は、3 つのデバイス オプションを表示するポップアップを介して、固定された Apple デバイス フォーマットにエクスポートするドキュメント ベースの QTKit アプリのコードです。[NSNumberWithLong:mpg4'] オプションも正常に機能しますが、カスタム出力設定がありません。ユーザーが mpeg-4 出力オプションをカスタマイズできるように、使い慣れた QT MPEG-4 エクスポート コンポーネント ダイアログを統合したいと考えています。

誰かがこれを行う方法を説明できますか?

ありがとう。

-ポール。

- (void)exportPanelDidEnd:(NSSavePanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
int which = [mExportTypePopUpButton indexOfSelectedItem];
int                 selectedItem;
NSMutableDictionary *settings = nil;
static NSArray      *exportTypes = nil;

// init
if (exportTypes == nil)
{
    exportTypes = [[NSArray arrayWithObjects:

                    //[NSNumber numberWithLong:'mpg4'],   ///MPEG-4

                    [NSNumber numberWithLong:'M4VH'],   ///Apple Tv
                    [NSNumber numberWithLong:'M4VP'],   ///iPhone
                    [NSNumber numberWithLong:'M4V '],   ///iPod

                    nil] retain];
}





if (returnCode == NSOKButton)
{
    // init
    selectedItem = [mExportTypePopUpButton indexOfSelectedItem];
    settings = [NSMutableDictionary dictionaryWithCapacity:2];
    [settings setObject:[NSNumber numberWithBool:YES] forKey:QTMovieExport];



    if ((selectedItem >= 0) && (selectedItem < [exportTypes count]))
        [settings setObject:[exportTypes objectAtIndex:selectedItem] forKey:QTMovieExportType];

    if (which==0)

        [mReceiver setStringValue:@"Apple Tv"];


    if (which==1)

        [mReceiver setStringValue:@"iPhone"];


    if (which==2)

        [mReceiver setStringValue:@"iPod"];





    /
    if (![mMovie writeToFile:[sheet filename] withAttributes:settings])
        NSRunAlertPanel(@"Cancel", @"Export terminated.", nil, nil, nil);



}

}

4

1 に答える 1

0

以下は、これから使用する標準の Quicktime コンポーネントのエクスポート設定ダイアログです。

ここに画像の説明を入力

このダイアログは Quicktime フレームワーク (QTKit と混同しないでください) でのみ使用できるため、次の制限があります。

  1. 32 ビット ビルドのみ
  2. iOS との統合は一切ありません。

最初に行う必要があるのは、アプリケーションを Quiktime フレームワークにリンクすることです。アプリケーションを 32 ビット Intel アーキテクチャでビルドし、Build Active Architecture Only 設定がオンになっていることを確認してください。

目標は、ダイアログを開き、必要なエクスポート設定を設定し、それらを使用してムービーをエクスポートすることです。

実際のダイアログ呼び出しから始まり、必要な構造の使用に戻るコード片を逆の順序で提供します。多くのコードを使用する必要があるため、ある程度の忍耐が必要です。

ダイアログには Quicktime コンポーネントが必要です。この例では、MPEG4 コンポーネントを使用します。コンポーネント、以前に保存された設定を提供し、ダイアログを開きます。

#import <QuickTime/QuickTimeComponents.h>

- (void)editExportSetting:(JSMovieExportSetting*)setting
{
    MovieExportComponent exporter = OpenComponent(_MPEG4Component.component);
    Boolean canceled;
    [self updateMovieExportComponent:exporter withExportSetting:setting];
    ComponentResult err = MovieExportDoUserDialog(exporter, NULL, NULL, 0, 0, &canceled);
    if (!canceled)
    {
        if (err == 0)
        {
            [self updateExportSetting:setting withMovieExportComponent:exporter];
        }
    }
    CloseComponent(exporter);   
}

ユーザーが編集を終了して [OK] ボタンをクリックすると、後で使用できるように設定が保存されます。OpenComponent関数にはデータ型が必要ですComponent。そのための便利なクラス ラッパーを作成しました。以下のリストを参照してください。

次に、MPEG4 コンポーネントを取得する必要があります。

- (JSQTComponent*)MPEG4Component
{
    /*
     MPEG-4
     */
    ComponentDescription description;
    description.componentType = 1936746868;
    description.componentSubType = 1836082996;
    description.componentManufacturer = 1634758764;
    description.componentFlags = 269058096;
    description.componentFlagsMask = 66207;

    return [self componentWithDescription:description];
}

- (JSQTComponent*)componentWithDescription:(ComponentDescription)description
{
    JSQTComponent* result = nil;
    for (JSQTComponent* component in [self components])
    {
        if ([component isEqualToComponentDescription:description])
        {
            result = component;
            break;
        }
    }
    return result;
}

- (NSArray*)components
{
    if (_components == nil)
    {
        _components = [NSMutableArray new];
        QTAtomContainer resources = NULL;
        OSErr err = GetComponentPublicResourceList(kQTPresetsListResourceType, 1, 0, &_componentDescription, nil, nil, &resources);

        if (err != noErr)
        {
            NSLog(@"JSQTComponentDataModel error: %d", err);
        }
        else if (resources != NULL)
        {
            QTAtom currChild = 0;
            QTAtom nextChild = 0;
            OSErr err;
            unsigned atomsCount = QTCountChildrenOfType(resources, kParentAtomIsContainer, 0);
            for (UInt16 i=0; i < atomsCount; i++)
            {
                QTAtom compAtomId = 0;
                if (QTFindChildByIndex(resources, kParentAtomIsContainer, kQTMetaDataCommonKeyComposer, i+1, &compAtomId))
                {
                    Component component = (Component)compAtomId;
                    err = QTNextChildAnyType(resources, kParentAtomIsContainer, currChild, &nextChild);
                    if (err == noErr && nextChild)
                    {
                        [_components addObject:[[[JSQTComponent alloc] initWithComponent:component] autorelease]];
                    } 
                    else
                    {
                        NSLog(@"Error %d getting item %d\n", err, i);
                    }
                    currChild = nextChild;
                }
            }
            QTDisposeAtomContainer(resources);
        }
    }
    return _components;
}

基本的に、リストで必要な説明を含むコンポーネントを探します。リストは、特定のタイプのコンポーネントを取得するために作成されました。

ムービーのエクスポート用に一度作成されたものだけに関心があります。

ComponentDescription _componentDescription;

_componentDescription.componentType = MovieExportType;
_componentDescription.componentSubType = kAnyComponentSubType;
_componentDescription.componentManufacturer = kAnyComponentManufacturer;
_componentDescription.componentFlags = canMovieExportFiles;
_componentDescription.componentFlagsMask = canMovieExportFiles;

リストはさらに使用するためにキャッシュされます。dealloc で解放することを忘れないでください。

これまでのところ順調に進んでいます。MPEG4 コンポーネント オブジェクトを取得Componentし、そこから構造を取得しました。次に、前回保存した設定をコンポーネントに適用する必要があります。

- (void)updateMovieExportComponent:(MovieExportComponent)component withExportSetting:(JSMovieExportSetting*)movieExportSetting
{
    NSData* presetSettings = movieExportSetting.exportSettings;
    Handle settings = NewHandleClear([presetSettings length]);
    if (settings)
    {
        memcpy(*settings, [presetSettings bytes], GetHandleSize(settings));
        // Set movie export settings from the settings QTAtomContainer
        MovieExportSetSettingsFromAtomContainer(component, (QTAtomContainer)settings);
        DisposeHandle(settings);
    }
}

何も設定せずに初めてコンポーネントを使用する場合、ダイアログにはデフォルトが 1 回表示されます。

ユーザーが編集を終了して [OK] を押した後、設定を保存する必要があります。

- (void)updateExportSetting:(JSMovieExportSetting*)movieExportSetting withMovieExportComponent:(MovieExportComponent)component
{
    QTAtomContainer settings;
    ComponentResult err = MovieExportGetSettingsAsAtomContainer(component, &settings);
    if (err == 0)
    {
        NSData* exportSettings = [NSData dataWithBytes:*settings length:GetHandleSize(settings)];
        movieExportSetting.exportSettings = exportSettings;
    }
}

JSMovieExportSettingはラッパーです。以下のリストを参照してください。ファイルにシリアル化して設定を保存するのは簡単です。

最後のステップは、ムービー変換用に取得した設定を使用することです。良いニュースは、Quicktime を使用する必要がなくなったことです。QTKit メソッドを使用できます。

QTMovie* movie = [QTMovie movieWithFile:sourceFilePath error:outError];

NSDictionary* settings = [movieExportSetting movieAttributes];

[movie writeToFile:outputFilePath withAttributes:settings error:outError]

ムービー デリゲートと実装movie: shouldContinueOperation: withPhase: atPercent: withAttributes:を設定して、必要に応じて進行状況を確認します。

以下に、使用されているクラスのリストを示します。これが役立つことを願っています。

JSQTコンポーネント

@interface JSQTComponent : NSObject
{
    Component _component;
    ComponentDescription _componentDescription;
    NSString* _name;
    NSString* _info;
    NSString* _icon;
}

- (id)initWithComponent:(Component)component;

@property (nonatomic, readonly) Component component;
@property (nonatomic, readonly) ComponentDescription componentDescription;
@property (nonatomic, retain) NSString* name;
@property (nonatomic, retain) NSString* info;
@property (nonatomic, retain) NSString* icon;

- (BOOL)isEqualToComponentDescription:(ComponentDescription)anotherComponentDescription;

@end

@implementation JSQTComponent

@synthesize コンポーネント = _component; @synthesize componentDescription = _componentDescription; @synthesize name = _name; @synthesize info = _info; @synthesize アイコン = _icon;

  • (id)initWithComponent:(Component)component { 自己 = [スーパー初期化]; if (self != nil) { _component = コンポーネント; [自己 getDescription]; 自己を返します。}

  • (void)dealloc { [_name release]; [_info リリース]; [_アイコン解除]; [スーパーdealloc]; }

  • (void)getDescription { OSErr err; ハンドル aName = NewHandleClear(255); ハンドル anInfo = NewHandleClear(255); ハンドル anIcon = NewHandleClear(255); iconSuite = NULL を処理します。

    err = GetComponentInfo(_component, &_componentDescription, aName, anInfo, anIcon); if (err == 0) { self.name = [NSString stringWithPStringHandle:aName]; self.info = [NSString stringWithPStringHandle:anInfo]; self.icon = [NSString stringWithPStringHandle:anIcon];
    //err = GetComponentIconSuite(aComponent, &iconSuite); DisposeHandle(名前); DisposeHandle(anInfo); DisposeHandle(アイコン); DisposeHandle(iconSuite); }

  • (BOOL)isEqualToComponentDescription:(ComponentDescription)anotherComponentDescription { return (_componentDescription.componentType == anotherComponentDescription.componentType) && (_componentDescription.componentSubType == anotherComponentDescription.componentSubType) && (_componentDescription.componentManufacturer == anotherComponentDescription.componentManufacturer); }

@終わり

JSMovieExportSetting

@interface JSMovieExportSetting : NSObject <NSCoding>
{
    NSString* _name;
    NSNumber* _componentSubType;
    NSNumber* _componentManufacturer;
    NSData* _exportSettings;

    NSDictionary* _movieAttributes;
}

- (id)initWithName:(NSString*)name attributes:(NSDictionary*)attributes;

@property (nonatomic, retain) NSString* name;
@property (nonatomic, retain) NSNumber* componentSubType;
@property (nonatomic, retain) NSNumber* componentManufacturer;
@property (nonatomic, retain) NSData* exportSettings;
@property (nonatomic, readonly) NSDictionary* movieAttributes;

@end


@implementation JSMovieExportSetting

...

- (NSDictionary*)movieAttributes
{
    if (_movieAttributes == nil)
        _movieAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:
                            [NSNumber numberWithBool:YES], QTMovieExport,
                            _componentSubType, QTMovieExportType,
                            _componentManufacturer, QTMovieExportManufacturer,
                            _exportSettings, QTMovieExportSettings, nil] retain];
    return _movieAttributes;
}

- (void)setExportSettings:(NSData*)exportSettings
{
    if (_exportSettings != exportSettings)
    {
        [_exportSettings release];
        _exportSettings = [exportSettings retain];

        [_movieAttributes release];
        _movieAttributes = nil;
    }
}

...

@end
于 2013-01-08T00:23:22.343 に答える