Memory problems with [AVAssetWriterInput requestMediaDataWhenReadyOnQueue:usingBlock:]

后端 未结 2 1534
执念已碎
执念已碎 2021-01-14 09:21

I’m writing a library to export assets to a file using AVFoundation. I create a reader, a writer, connect the inputs and outputs to these and then call the requestMedi

相关标签:
2条回答
  • 2021-01-14 09:46

    Seeing the same (similar) issue. iOS5 happy, iOS4.3.5, not happy. Interested to learn what you ultimately find.

    Got around it by explicitly retaining writer, writer input, reader, reader output before the requestMedatWhenReadyOnQueue block and explicitly releasing all four at the very end of the else clause.

    The doc does say that after marking finished, "The block should then exit." Maybe they are not kidding. If you do anything other than exit, it is an error. The above workaround seems to work though.

    UPDATE: I still found that it occasionally crashed even after retaining and releasing all of the asset objects. As your question observes, it crashes shortly after you mark the writer input as finished it is as if the block itself is being deallocated. Rather than just pass the block as part of the function. I create a copied block property that is part of a long lived object. I initialize it with Block_copy and only release it in the destructor of the long lived object. This seems to do the trick. I haven't seen any 4.3.5 crashes since.

    0 讨论(0)
  • 2021-01-14 10:02

    Try [self retain] as the first line of the block and [self release] as the last line.

    Another critical issue is that if the App is suspended (enters background) using requestMediaDataWhenReadyOnQueue you need to explicitly cover all of the [reader status] values as it will fail when the app restarts. In some cases I found the block ran more than once with a fail status flag. In other posts with similar code there's a lot of [retain]ing of the AV variables, which are then released at the end of the block. Because the block can run more than once this approach doesn't work in cases when the app enters the background state.

    I found the following to work well in the "switch" (above):

                    case AVAssetReaderStatusReading:
                        break;
    
                    case AVAssetReaderStatusCompleted:
                        [videoWriterInput markAsFinished];
                        //do something else, like add an audio stream
                        [videoWriter finishWriting];
                        break;
    
                    case AVAssetReaderStatusFailed:
                        [videoWriterInput markAsFinished];
                        [videoWriter finishWriting];
                        break;
    
                    case AVAssetReaderStatusCancelled:
                    case AVAssetReaderStatusUnknown:
                        [videoWriterInput markAsFinished];
                        [videoWriter cancelWriting];
                        break;
                }
    
                dispatch_sync(dispatch_get_main_queue(), ^{
                  //hide any progress indicators
                });
    
                break;
    

    other than "self", nothing is retained. The block should retain the variables automatically if they are required.

    0 讨论(0)
提交回复
热议问题