Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS/AVFoundation:将图像阵列转换为曲目,然后转换为单个视频时,异步处理程序的设计模式?_Ios_Objective C_Design Patterns_Avfoundation - Fatal编程技术网

iOS/AVFoundation:将图像阵列转换为曲目,然后转换为单个视频时,异步处理程序的设计模式?

iOS/AVFoundation:将图像阵列转换为曲目,然后转换为单个视频时,异步处理程序的设计模式?,ios,objective-c,design-patterns,avfoundation,Ios,Objective C,Design Patterns,Avfoundation,你能告诉我设计模式指南,使我的风格适应AVFoundation的异步方法吗 在应用程序中创建图像并将音频放置到热点上。我正在实现导出到一部电影,该电影是在音频下播放的带有效果(热点的辉光)的图像 我能可靠地创建视频和音频曲目,并能正确地将音频转换成AVMUTABLE合成并播放。问题在于视频。我已经把范围缩小到我已经为一个需要使用AVFoundation异步编写方法的问题编写了一个同步解决方案 当前方法及其失败之处(每个步骤都是自己的方法): 创建字典数组。字典中有2个对象。一个字典对象是表示关键

你能告诉我设计模式指南,使我的风格适应AVFoundation的异步方法吗

在应用程序中创建图像并将音频放置到热点上。我正在实现导出到一部电影,该电影是在音频下播放的带有效果(热点的辉光)的图像

我能可靠地创建视频和音频曲目,并能正确地将音频转换成AVMUTABLE合成并播放。问题在于视频。我已经把范围缩小到我已经为一个需要使用AVFoundation异步编写方法的问题编写了一个同步解决方案

当前方法及其失败之处(每个步骤都是自己的方法):

  • 创建字典数组。字典中有2个对象。一个字典对象是表示关键帧的图像,另一个对象是结束于该关键帧的音频URL。第一个字典有开始关键帧,但没有音频URL

  • 对于数组中的每个字典,将UIImage替换为“开始图像->动画-中间图像->结束状态图像”数组,并具有适当的FPS计数和音频持续时间

  • 对于数组中的每个字典,将图像数组转换为无声mp4并使用[AVAssetWriter finishWritingWithCompletionHandler]保存,然后将字典中的图像数组替换为mp4的URL。mp4和音频URL的每个字典表示最终电影的一段,其中数组中字典的顺序指示最终电影的插入顺序

  • --所有以上的工作,东西得到正确的制作和订购,视频和音频播放--

  • 对于每个带有mp4和音频URL的词典,将其加载到AVAssets并插入AVMutableComposition曲目,一个曲目用于音频,一个曲目用于视频。音频加载和插入工作,播放。但是视频失败并且似乎失败了,因为步骤4在步骤3的AVAssetWriter完成所有MP4曲目的WritingWithCompletionHandler完成之前开始
  • 一种方法是通过while循环暂停,等待AVAssetWriter上的状态为done。这有点违反框架的味道。在实践中,它也会导致丑陋的、有时看起来是无限的等待循环结束

    但是简单地将步骤4设置为finishWritingWithCompletionHandler的完成处理程序是非常重要的,因为我正在编写多个曲目,但我希望步骤4仅在最后一个曲目写入之后启动。因为第3步基本上是每个处理器的一个步骤,所以我认为所有的完成处理程序都应该是相同的。我想我可以使用布尔或计数器来更改完成处理程序,但这感觉就像一个傻瓜

    如果以上任何一条都有意义,有人能给我/指一下异步处理的设计模式入门吗?TIA。

    你可以为这类问题解决。
    从文档中:

    分组块允许聚合同步。你的申请 可以在全部完成时提交多个区块并跟踪,甚至 尽管它们可能在不同的队列上运行。这种行为可以是 在完成所有指定任务后才能取得进展时,此功能非常有用 这些都是完整的

    基本思想是,为每个异步任务调用。在任务的完成处理程序中,调用

    调度组的工作类似于计算信号量。启动任务时递增计数器(使用dipsatch_group_wait),任务完成时递减计数器。 用于为组安装完成处理程序块。当计数器达到0时,执行此块


    这篇博文提供了一个很好的概述和完整的代码示例:

    @weichsel非常感谢。这似乎应该行得通。但是,我正在使用dispatch_group_wait,它似乎没有等待。自从你第一次回复以来,我一直在敲它好几个小时,但现在运气好了。以下是我所做的:

    • 添加了一个属性,该属性是一个调度组,称为videoDispatchGroup,并在执行视频处理的类的init中调用dispatch_group_create

    • 在创建视频曲目的方法中,使用dispatch_group_async(VideoDispatch group,dispatch_get_global_queue(dispatch_queue_PRIORITY_DEFAULT,0))^{[videoWriter finishWritingWithCompletionHandler:^{

    • 视频曲目写入方法是从一个链接各个步骤的方法调用的。在该方法中,在调用写入曲目后,我调用dispatch_group_wait(videoProcessingGroup,dispatch_TIME_FOREVER)

    • 在dealloc中,调用dispatch_release(videoDispatchGroup)

    这都略去了一点,但本质上,调用dispatch\u group\u wait似乎没有等待。我猜这与dispatch\u group\u asyn调用有关,但我不确定具体是什么

    我找到了另一种方法来处理这个问题,在finishWritingWithCompletion处理程序上通过异步处理程序使用我自己的整数计数/减量。但是我真的希望通过更好地理解GCD来提高我的技能


    下面是代码——dispatch_group_wait似乎从未启动过,但电影本身是制作的。为了简洁起见,代码略去了一点,但没有删除任何在没有GCD代码的情况下不起作用的代码

    @implementation MovieMaker 
    
    // This is the dispatch group
    @synthesize videoProcessingGroup = _videoProcessingGroup;
    
    -(id)init {
      self = [super init];
    
      if (self) {
         _videoProcessingGroup = dispatch_group_create();
      }
    
      return self;
    }
    
    -(void)dealloc {
      dispatch_release(self.videoProcessingGroup);
    }
    
    -(id)convert:(MTCanvasElementViewController *)sourceObject {
      // code fails in same way with or without this line
      dispatch_group_enter(self.videoProcessingGroup);
    
      // This method works its way down to writeImageArrayToMovie
      _tracksData = [self collectTracks:sourceObject];
    
      NSString *fileName = @"";
    
      // The following seems to never stop waiting, the movies themselves get made though
      // Wait until dispatch group finishes processing temp tracks
      dispatch_group_wait(self.videoProcessingGroup, DISPATCH_TIME_FOREVER);
    
      // never gets to here
      fileName = [self writeTracksToMovie:_tracksData];
    
      // Wait until dispatch group finishes processing final track
      dispatch_group_wait(self.videoProcessingGroup, DISPATCH_TIME_FOREVER);
    
      return fileName;
    }
    
    
    // @param videoFrames should be NSArray of UIImage, all of same size
    // @return path to temp file
    -(NSString *)writeImageArrayToMovie:(NSArray *)videoFrames usingDispatchGroup:(dispatch_group_t)dispatchGroup {
    // elided a bunch of stuff, but it all works
    
      AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:result]
                                                         fileType:AVFileTypeMPEG4
                                                            error:&error];
    
    //elided stuff
    
      //Finish the session:
      [writerInput markAsFinished];
    
    
      dispatch_group_async(dispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [videoWriter finishWritingWithCompletionHandler:^{
          dispatch_group_leave(dispatchGroup);
    
    // not sure I ever get here? NSLogs don't write out.
          CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
        }];
      });
    
      return result;
    }
    

    非常感谢您的帮助。但我无法让dispatch\u group\u wait实际等待。由于此评论部分的格式问题,我在下面的新答案中添加了一个说明。Hi Rod-很抱歉回复太晚:)我没有看到您的答案,因为我只收到评论通知。您似乎从未呼叫dispatch\u group\u enter-这非常重要,因为它会增加等待计数器。如果您从未“输入”组,dispatch\u group\u wait将不起作用。我不确定您的dispatch\u group\u wait呼叫是否位于正确的位置。或许您可以更新您的答案(或原问题)带代码。