2010-01-09 5 views
1

Ниже приведен мой код для приложения QTKit, основанного на doc, которое экспортируется в фиксированные форматы устройств Apple посредством popUp, который отображает три параметра устройства. Опция [NSNumberWithLong: mpg4] работает отлично, но в ней отсутствуют настройки пользовательского вывода. Я хочу интегрировать знакомый диалог экспорта компонентов QT MPEG-4, чтобы пользователь мог настроить параметры вывода mpeg-4.Дисплей Component Dialog MPEG-4

Может кто-нибудь объяснить, как это сделать?

спасибо.

-paul.

- (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); 



} 

}

+0

Вы все еще заинтересованы или слишком поздно, чтобы ответить на этот вопрос? – Davyd

ответ

0

Здесь стандартное диалоговое окно настройки экспорта Quicktime компонентов мы будем использовать:

enter image description here

Диалог доступен только в рамках Quicktime (не следует путать с QTKit), следовательно, ограничения:

  1. 32-битный buil d только
  2. Нет интеграции iOS вообще.

Первое, что вам нужно сделать, это связать ваше приложение с каркасом Quiktime, убедитесь, что вы его построили в 32-разрядной архитектуре Intel и Build Active Architecture.

Целью является открыть диалог, установить необходимые параметры экспорта и использовать их для экспорта фильма.

Я приведу фрагменты кода в обратном порядке, начиная с фактического диалога, возвращаясь к использованию требуемых структур. Мы должны использовать много кода, поэтому необходимо некоторое терпение.

Диалог требует компонента 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; 
} 

В основном мы смотрим на компоненты с описанием нам нужно в списке. Список был создан для получения компонентов определенного типа, потому что Quicktime имеет несколько разных раз.

Мы заинтересованы только в тех, которые были созданы для экспорта фильмов.

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); 
    } 
} 

Если вы используете компонент впервые без каких-либо настроек, диалоговое окно будет отображаться по умолчанию один раз.

После пользователь закончил с редактированием и нажал ОК, мы должны сохранить настройки:

- (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:, чтобы увидеть прогресс, если это необходимо.

Ниже вы можете найти список использованных классов. Надеюсь, это поможет.

JSQTComponent

@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 = _icon;

  • (ID) initWithComponent: (Компонент) Компонент { самостоятельно = [супер INIT]; if (self! = Nil) { _компонент = компонент; [self getDescription]; } return self; }

  • (пустоты) dealloc { [_name релиз]; [_info release]; [_icon release]; [super dealloc]; }

  • (пустоты) 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 (aName); DisposeHandle (anInfo); DisposeHandle (anIcon); DisposeHandle (iconSuite); }

  • (BOOL) isEqualToComponentDescription: (ComponentDescription) anotherComponentDescription { возврата (_componentDescription.componentType == anotherComponentDescription.componentType) & & (_componentDescription.componentSubType == anotherComponentDescription.componentSubType) & & (_componentDescription.componentManufacturer == anotherComponentDescription.componentManufacturer); }

@end

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