3

30 fps で jpeg フレームをキャプチャし、ビデオを mp4 形式で記録するコードを以下に示します。processFrame メソッドを dispatch_async 呼び出しでラップして、記録プロセスがビデオ プレーヤーをロックアップしないようにしようとしています。これに関する問題は、メモリ警告レベル 2 が表示され、数秒後にアプリが最終的にクラッシュすることです。記録されたビデオ出力に各フレームを追加しようとすると、dispatch_async メソッドがキューをメモリにロードし、30fps では、フレームを処理して使用済みメモリを解放するのに十分な時間がないことがわかります。processFrame の実行を遅らせるために dispatch_after を使用しようとしましたが、役に立ちません。何か案は?これを別の方法で行う必要がありますか?

このメソッドは、毎秒約 30 回呼び出されます。

//Process the data sent by the server and send follow-up commands if needed
-(void)processServerData:(NSData *)data{    

    //render the video in the UIImage control 
    UIImage *image =[UIImage imageWithData:data];
    imageCtrl.image = image;


        //record the frame in the background
        dispatch_async(recordingQueue,^{[self processFrame:image];});
    }
}

processFrame メソッド

//function for processing each frame for recording
-(void) processFrame:(UIImage *) image {

    if (myRecorder.frameCounter < myRecorder.maxFrames)
    {
        if([myRecorder.writerInput isReadyForMoreMediaData])
        {
            CMTime frameTime = CMTimeMake(1, myRecorder.timeScale);
            CMTime lastTime=CMTimeMake(myRecorder.frameCounter, myRecorder.timeScale); 
            CMTime presentTime=CMTimeAdd(lastTime, frameTime);

            buffer = [Recorder pixelBufferFromCGImage:image.CGImage size:myRecorder.imageSize];

            if(buffer)
            {
                [myRecorder.adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];

                myRecorder.frameCounter++;

                CVBufferRelease(buffer);

                if (myRecorder.frameCounter==myRecorder.maxFrames)
                {
                    [myRecorder finishSession];

                    myRecorder.frameCounter=0;
                    myRecorder.isRecording = NO;
                }
            }
            else
            {
                NSLog(@"Buffer is empty");
            }
        }
        else
        {
            NSLog(@"adaptor not ready frameCounter=%d ",myRecorder.frameCounter );
        }
    }

}
4

1 に答える 1

3

解決しました!私は、dispatch_async_semaphore を使用して、割り当てられたリソースを解放するのに十分な時間がないという要求が多すぎてキューが過負荷になるのを防ぐことができることを発見しました。

更新されたコードは次のとおりです。

    long success = dispatch_semaphore_wait(recordingSemaphore, DISPATCH_TIME_FOREVER);

    if (success != 0 )
    {
        NSLog(@"Frame skipped");
    }
    else
    {
        dispatch_async(recordingQueue,^{
            dispatch_semaphore_signal(recordingSemaphore);
            [self processFrame:image];
        });

    }

私のコードのどこかに作成されたdispatch_semaphore。ここでは、セマフォに、最初に最大 50 個の要求のみを受け入れ、それ以上の要求を受け入れる前に処理を終了するように指示しました。

dispatch_semaphore_t recordingSemaphore =  dispatch_semaphore_create((long) 50); //so far stable at 50
于 2011-04-05T23:18:41.240 に答える