Демо-справка для iPhone: кто-нибудь знает о более быстрой альтернативе захвата экрана UIGetScreenImage ()? - PullRequest
9 голосов
/ 20 января 2011

Я работаю над приложением для iPhone, которое скоро собираюсь продемонстрировать живой аудитории.

Я бы очень хотел продемонстрировать приложение в режиме реального времени через VGA на проектор, а не показывать скриншоты.

Я купил VGA-адаптер для iPhone и адаптировал TVOutManager Роба Террелла для своих нужд. К сожалению, частота кадров после тестирования на моем домашнем телевизоре просто не так хороша - даже на iPhone 4 (возможно, 4-5 кадров в секунду, это варьируется).

Я полагаю, что причина этой медлительности в том, что основной программой, которую я использую для захвата экрана устройства (который затем отображается на внешнем дисплее), является UIGetScreenImage(). Эта процедура, которая больше не может быть частью доставки приложений, на самом деле довольно медленная. Вот код, который я использую для захвата экрана (FYI mirrorView - это UIImageView):

CGImageRef cgScreen = UIGetScreenImage();
self.mirrorView.image = [UIImage imageWithCGImage:cgScreen];
CGImageRelease(cgScreen);

Есть ли более быстрый способ, который я могу использовать для захвата экрана iPhone и достижения лучшей частоты кадров (съемка со скоростью 20+ кадров в секунду)? Не нужно проходить проверку приложения Apple - этого демонстрационного кода не будет в приложении доставки. Если кто-нибудь знает какие-либо более быстрые частные API, я буду очень признателен за помощь!

Кроме того, приведенный выше код выполняется с использованием повторяющегося NSTimer, который срабатывает каждые 1.0/desiredFrameRate секунд (в настоящее время каждые 0,1 секунды). Я задаюсь вопросом, может ли вместо этого обернуть эти вызовы в блок и использовать GCD или NSOperationQueue более эффективно, чем NSTimer вызывать мой updateTVOut метод obj-c, который в настоящее время содержит эти вызовы. Буду признателен также за некоторые сведения об этом - некоторые поиски показывают, что отправка сообщений obj-c несколько медленнее, чем другие операции.

Наконец, как вы можете видеть выше, CGImageRef, возвращаемый UIGetScreenImage(), превращается в UIImage, а затем UIImage передается в UIImageView, что, вероятно, изменяет размер изображения на муха. Мне интересно, может ли изменение размеров замедлить ситуацию еще больше. Идеи, как сделать это быстрее?

Ответы [ 4 ]

5 голосов
/ 20 января 2011

Вы смотрели на рекомендованные Apple альтернативы UIGetScreenImage? Из потока " Уведомление относительно UIGetScreenImage () ":

Приложения, использующие UIGetScreenImage () для захвата изображений с камеры, должны вместо этого использовать AVCaptureSession и связанные классы в AV Foundation Framework. Для примера см. Технические вопросы и ответы QA1702 , «Как захватывать видеокадры с камеры в виде изображений с использованием AV Foundation». Обратите внимание, что использование AVCaptureSession поддерживается только в iOS4 и выше.

Приложения, использующие UIGetScreenImage () для захвата содержимого представлений и слоев интерфейса, должны вместо этого использовать -renderInContext: метод CALayer в платформе QuartzCore. Для примера см. Технические вопросы и ответы QA1703 , «Снимок экрана в приложениях UIKit».

Приложения, использующие UIGetScreenImage () для захвата содержимого представлений и слоев на основе OpenGL ES, должны вместо этого использовать функцию glReadPixels () для получения данных пикселей. Для примера см. Технические вопросы и ответы QA1704 , «OpenGL ES View Snapshot».

2 голосов
/ 23 апреля 2011

Новое решение: достань iPad 2 и отрази выход! :)

1 голос
/ 28 января 2011

Я не знаю, как быстро это, но стоит попробовать;)

CGImageRef screenshot = [[UIApplication sharedApplication] _createDefaultImageSnapshot];
[myVGAView.layer setContents:(id)screenshot];

где _createDefaultImageSnapshot - частный API. (Так как это для демо ... это нормально, я полагаю) и myVGAView - это обычный UIView. Если вы получаете CGImageRefs, просто передайте их содержимому слоя, оно будет светлее и должно быть немного быстрее (но немного;))

0 голосов
/ 28 января 2011

У меня нет решения, которое вам нужно (имитация зеркального отображения), но вы можете переместить ваши представления на внешний дисплей.Это то, что я делаю, и не оказывает заметного влияния на частоту кадров.Однако, очевидно, поскольку представление больше не отображается на экране устройства, вы больше не можете напрямую взаимодействовать с ним или видеть его.Если у вас есть что-то вроде игры, управляемой с помощью акселерометра, это не должно быть проблемой, однако что-то на основе касания потребует некоторой работы.То, что я делаю, - это альтернативный вид устройства, когда основной вид является внешним.Для меня это двухмерный вид управления, чтобы «командовать» обычным трехмерным видом.Если у вас есть игра, вы, возможно, могли бы создать альтернативный вид ввода для управления игрой (виртуальные кнопки / джойстик и т. Д.), Действительно зависит от того, что у вас есть, и как лучше всего обойти ее.Сам я не могу сказать наверняка, но у меня сложилось впечатление, что взломанное устройство может по существу включить зеркальное отображение видео (как они используют на демонстрациях Apple ...).Если это правда, то это, вероятно, ваш самый простой маршрут, если вам нужна только демонстрация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...