Предупреждение памяти при использовании dispatch_async в iOS - PullRequest
3 голосов
/ 04 апреля 2011

У меня есть код ниже, который захватывает JPEG-кадры со скоростью 30 кадров в секунду и записывает видео в формате mp4.Я пытаюсь обернуть метод processFrame в вызов dispatch_async, чтобы процесс записи не блокировал проигрыватель видео.Проблема с этим заключается в том, что я получаю Memory Warning level 2, и приложение в конечном итоге вылетает через несколько секунд.Я вижу, что метод dispatch_async загружает очередь в память, когда он пытается добавить каждый кадр в записанный видеовыход, и на скорости 30 кадров в секунду у него не хватает времени для обработки кадра и освобождения использованной памяти.Я попытался использовать dispatch_after, чтобы отложить выполнение processFrame, но это не помогло.Есть идеи?Должен ли я делать это по-другому?

Этот метод вызывается примерно 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 );
        }
    }

}

1 Ответ

3 голосов
/ 06 апреля 2011

Решено! Я обнаружил, что могу использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...