下面是我的一个基于文档的QTKit应用程序的代码,它通过显示三个设备选项的popUp导出到固定的苹果设备格式。NSNumberWithLong:mpg4‘选项也工作得很好,但它缺乏自定义输出设置。我想集成熟悉的QT 4导出组件对话框,以便用户可以自定义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);
}}
发布于 2013-01-08 08:23:22
下面是我们将要使用的标准Quicktime组件导出设置对话框:

该对话框仅在Quicktime框架中可用(不要与QTKit混淆),因此存在以下限制:
仅限
您需要做的第一件事是将您的应用程序链接到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);
}当用户完成编辑并单击“确定”按钮时,我们将存储设置以供以后使用。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);
}
}如果您在没有任何设置的情况下第一次使用该组件,该对话框将显示一次默认值。
在用户完成编辑并按下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:来查看进度。
您可以在下面找到所使用的类的列表。我希望这能帮到你。
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@实现JSQTComponent
@合成组件= _component;@合成图标= _componentDescription;@合成名称= _name;@合成信息= _info;@合成图标= _icon;
@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;
}
}
...
@endhttps://stackoverflow.com/questions/2032243
复制相似问题