0

現在、いくつかのコードをデバッグしています。ムービー ファイルをフレーム配列に読み込み、フレームにいくつかの変換を適用し、すべてをコンパイルしてビデオ ファイルに戻します。自分で呼び出したすべてのメモリ リークを修正しましたが、残りの 1 つはかなり深刻です。プロセス後、約 400 MB のメモリが残ります。これがリークのスクリーンショットです。

CVPixelBufferPoolCreatePixelBuffer でのメモリ リーク

ご覧のとおり、より高いレベルの呼び出しは VideoToolbox ライブラリにのみあります。しかし、私はこのライブラリをプロジェクトに含めていません。このリークが Apple のライブラリに付属しているとは思えず、私にできることは何もありません。

これは、コール ツリーで言及された h264 とデコードに関連するものを使用する唯一のコードです。

-(void)writeImageAsMovie:(NSArray *)array toPath:(NSString*)path size:(CGSize)size
{

if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
    [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}

NSError *error = nil;

// FIRST, start up an AVAssetWriter instance to write your video
// Give it a destination path (for us: tmp/temp.mov)
AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
                                                       fileType:AVFileTypeQuickTimeMovie
                                                          error:&error];


NSParameterAssert(videoWriter);

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               [NSNumber numberWithInt:size.width], AVVideoWidthKey,
                               [NSNumber numberWithInt:size.height], AVVideoHeightKey,
                               nil];

AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                                     outputSettings:videoSettings];

AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
                                                                                                                 sourcePixelBufferAttributes:nil];
NSParameterAssert(writerInput);
NSParameterAssert([videoWriter canAddInput:writerInput]);
[videoWriter addInput:writerInput];
//Start a SESSION of writing.
// After you start a session, you will keep adding image frames
// until you are complete - then you will tell it you are done.
[videoWriter startWriting];
// This starts your video at time = 0
[videoWriter startSessionAtSourceTime:kCMTimeZero];

CVPixelBufferRef buffer = NULL;


//int frameDuration = (1/fps)*600.0;
//NSLog(@"FRAME DURATION: %d",frameDuration);
int i = 0;
while (1)
{
    // Check if the writer is ready for more data, if not, just wait
    if(writerInput.readyForMoreMediaData){

        CMTime frameTime = CMTimeMake(1, fps);
        // CMTime = Value and Timescale.
        // Timescale = the number of tics per second you want
        // Value is the number of tics
        // For us - each frame we add will be 1/4th of a second
        // Apple recommend 600 tics per second for video because it is a
        // multiple of the standard video rates 24, 30, 60 fps etc.
        CMTime lastTime=CMTimeMake(i, fps);
        CMTime presentTime=CMTimeAdd(lastTime, frameTime);

        if (i == 0) {presentTime = CMTimeMake(0, 600);}
        // This ensures the first frame starts at 0.


        if (i >= [array count])
        {
            buffer = NULL;
        }
        else
        {
            // This command grabs the next UIImage and converts it to a CGImage

            CVPixelBufferRef tempBuffer = buffer;

            CVPixelBufferRelease(tempBuffer);

            buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:i] CGImage]andSize:size];
        }


        if (buffer)
        {
            // Give the CGImage to the AVAssetWriter to add to your video
            [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
            i++;
        }
        else
        {
            //Finish the session:
            // This is important to be done exactly in this order
            [writerInput markAsFinished];
            // WARNING: finishWriting in the solution above is deprecated.
            // You now need to give a completion handler.
            [videoWriter finishWritingWithCompletionHandler:^{
                NSLog(@"Finished writing...checking completion status...");
                if (videoWriter.status != AVAssetWriterStatusFailed && videoWriter.status == AVAssetWriterStatusCompleted)
                {
                    NSLog(@"Video writing succeeded.");

                    // Move video to camera roll
                    // NOTE: You cannot write directly to the camera roll.
                    // You must first write to an iOS director then move it!
                    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
                    NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder

                    NSString *audioTemp = [documentsDirectory stringByAppendingPathComponent:@"/temp-audio.m4a"];
                    NSString *finalTemp = [documentsDirectory stringByAppendingPathComponent:@"/temp.mov"];

                    [self mergeVideoFromPath:[NSURL fileURLWithPath:path] withAudioFromPath:[NSURL fileURLWithPath:audioTemp] atPath:[NSURL fileURLWithPath:finalTemp]];

                } else
                {
                    NSLog(@"Video writing failed: %@", videoWriter.error);
                }

            }]; // end videoWriter finishWriting Block


            CVPixelBufferRelease(buffer);

            CVPixelBufferPoolRelease(adaptor.pixelBufferPool);

            NSLog (@"Done");
            break;
        }
    }
}
}
4

0 に答える 0