2011-01-20 10 views
9

Pracuję nad aplikacją na iPhone'a, którą niedługo będę prezentować publiczności na żywo.Pomoc demo na iPhone'a: ​​każdy wie o szybszym przechwytywaniu ekranu zamiast UIGetScreenImage()?

Chciałbym pokazać wersję demonstracyjną aplikacji na żywo zamiast VGA, zamiast wyświetlać zrzuty ekranu.

Kupiłem adapter VGA dla iPhone'a i dostosowałem Rob Terrell's TVOutManager do moich potrzeb. Niestety, liczba klatek na sekundę po przetestowaniu na moim telewizorze w domu po prostu nie jest dobra - nawet na iPhone 4 (może 4-5 klatek na sekundę, zmienia się).

Uważam, że powodem tego powolności jest to, że główną procedurą używaną do przechwytywania ekranu urządzenia (które jest następnie wyświetlane na zewnętrznym wyświetlaczu) jest UIGetScreenImage(). Ta procedura, która nie może już być częścią aplikacji do wysyłki, jest dość powolna. Oto kod używam do przechwytywania ekranu (FYI mirrorView jest UIImageView):

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

Czy istnieje szybszy sposób mogę wykorzystać do przechwytywania ekranu iPhone i osiągnąć lepszą szybkość klatek (Strzelanie dla 20+ fps)? Nie trzeba przesyłać recenzji aplikacji Apple - ten kod demonstracyjny nie będzie dostępny w aplikacji do wysyłki. Jeśli ktokolwiek wie o szybszych prywatnych interfejsach API, byłbym wdzięczny za pomoc!

Ponadto, powyższy kod jest wykonywany przy użyciu powtarzającego się NSTimer, który odpala co każdesekund (obecnie co 0,1 sekundy). Zastanawiam się, czy zamiast tego zawijanie tych wywołań w bloku i używanie GCD lub NSOperationQueue może być bardziej wydajne, niż gdybym miał NSTimer wywoływać moją metodę 01:obj-c, która obecnie zawiera te wywołania. Byłby wdzięczny za niektóre dane wejściowe - niektóre wyszukiwania wydają się wskazywać, że wysyłanie wiadomości obj-c jest nieco powolne w porównaniu do innych operacji.

Wreszcie, jak widać powyżej, CGImageRef że UIGetScreenImage() powraca jest przekształcony w UIImage i wtedy UIImage jest przekazywany do UIImageView, która jest prawdopodobnie zmiana rozmiaru obrazu w locie. Zastanawiam się, czy zmiana rozmiaru może spowolnić jeszcze bardziej. Pomysły, jak to zrobić szybciej?

Odpowiedz

5

Czy obejrzałeś zalecane przez Apple alternatywy dla UIGetScreenImage? Z „Notice regarding UIGetScreenImage()” wątku:

Aplikacje wykorzystujące UIGetScreenImage() do przechwytywania obrazu z kamery powinien zamiast używać AVCaptureSession i pokrewne zajęcia w AV Framework Foundation. Na przykład patrz: Technical Q&A QA1702, "Jak przechwytywać klatki wideo z aparatu jako obrazy za pomocą AV Foundation". Zwróć uwagę, że użycie AVCaptureSession jest obsługiwane tylko w systemie iOS4 i nowszych wersjach.

Aplikacje używające UIGetScreenImage() do przechwytywania zawartości widoków interfejsu i warstw powinny zamiast tego używać metody -renderInContext: CALayer w strukturze QuartzCore. Na przykład, zobacz Technical Q&A QA1703, "Zrzut ekranu w aplikacjach UIKit".

Aplikacje używające UIGetScreenImage() do przechwytywania zawartości widoków i warstw opartych na OpenGL ES powinny zamiast tego używać funkcji glReadPixels() w celu uzyskania danych pikseli. Na przykład zobacz Technical Q&A QA1704, "Widok migawki OpenGL ES".

+1

Witaj Jonah, dzięki za twoją sugestię. Jak się okazało, spróbowałem użyć metody renderInContext: CALayer. Jest jeszcze wolniej. AVFoundation nie pomoże mi w tym przypadku, ponieważ nie przechwytywam z kamery lub innego źródła AV - próbuję uchwycić sam ekran. Apple zaleca alternatywy dla UIGetScreenImage, ponieważ nie pozwalają na to więcej, ale ten kod nie jest przeznaczony do przesyłania do App Store, tylko do wersji demo. –

0

Nie mam odpowiedniego rozwiązania (symulowanie dublowania wideo), ale możesz przenieść swoje widoki na zewnętrzny wyświetlacz.To jest to, co robię i nie ma zauważalnego wpływu na liczbę klatek na sekundę. Oczywiście, ponieważ widok nie jest już wyświetlany na ekranie urządzenia, nie można już bezpośrednio z nim korzystać ani go oglądać. Jeśli masz coś w rodzaju gry kontrolowanej za pomocą akcelerometru, nie powinno to stanowić problemu, jednak w przypadku niektórych czynności związanych z dotykiem wymagana będzie pewna praca. To, co robię, to alternatywny widok na urządzenie, gdy widok główny jest zewnętrzny. Dla mnie jest to widok kontrolny 2D do "polecenia" normalnego widoku 3D. Jeśli masz grę, możesz utworzyć alternatywny widok wejściowy, aby sterować grą za pomocą (wirtualnych przycisków/joysticka itp.) Naprawdę zależy od tego, co masz, jak najlepiej je obejść.

Nie mam jailbreak sam siebie nie mogę powiedzieć na pewno, ale mam wrażenie, że urządzenie z jailbreak może zasadniczo umożliwić dublowanie wideo (jak używają na dema jabłek ...). Jeśli jest to prawda, to najprawdopodobniej najłatwiejsza trasa, jeśli chcesz tylko demo.

1

nie wiem jak szybko jest to, ale warto spróbować;)

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

gdzie _createDefaultImageSnapshot jest prywatną API. (Ponieważ jest dla demo ... jego ok, przypuszczam) i myVGAView jest normalnym UIView. Jeśli otrzymasz CGImageRefs, po prostu przenieś je do zawartości warstwy, która jest lżejsza i powinna być nieco szybsza (ale tylko odrobinę;))

2

Nowe rozwiązanie: kup iPada 2 i odzwierciedlić wyjście! :)

Powiązane problemy