Команда Vuforia опубликовала инструкцию по увеличению частоты кадров в потоковом видео на iOS 8

Бравые разработчики инструментариев дополненной реальности Qualcomm Vuforia знают о проблеме снижения частоты кадров потокового видео ...

Бравые разработчики инструментариев дополненной реальности Qualcomm Vuforia знают о проблеме снижения частоты кадров потокового видео в ваших AR-приложениях на iOS 8 и уже приготовили решение. По их словам, проблема коренится именно в новой операционной системе Apple и была определена как проблема с частотой, с которой обновление видеотаймера события срабатывает в образце (смотрите переменную frameTimer в классе VideoPlayerHelper).

Вы можете восстановить правильную частоту кадров и работать с плавным видео на всех версиях iOS, выполнив следующие действия.

Класс SimpleTimer

Для начала создайте класс под названием «SimpleTimer», который предполагает простую реализацию таймера с возможностью планировать повторяющиеся действия с заданной скоростью. Вы можете использовать следующий код для части объявления класса (заголовок SimpleTimer.h):

#pragma mark — SimpleTimer

@protocol SimpleTimerDelegate <NSObject>

@required

-(void)timerDidTick;

@end

@interface SimpleTimer : NSObject

{

    pthread_t timerThread;

    BOOL running;

}

@property (nonatomic, assign) id <SimpleTimerDelegate> delegate;

@property (atomic, readwrite) int exitRequested;

@property (nonatomic, readonly) double interval;

-(id)initWithInterval:(double) interval andDelegate:(id<SimpleTimerDelegate>)delegate;

-(void)start;

-(void)stop;

@end

Затем добавьте следующий код фактического выполнения класса (файл SimpleTimer.m):

#import «SimpleTimer.h»

static void* timerThreadRoutine(void* p)

{

    SimpleTimer* self = (SimpleTimer*)p;

    useconds_t sleepTime = self.interval * USEC_PER_SEC;

    while (!self.exitRequested) {

        usleep(sleepTime);

        // Create an autorelease pool so the delegate method will not leak

        // autoreleased objects

        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        [self.delegate timerDidTick];

        [pool release];

    }

    [self release];

    return NULL;

}

@implementation SimpleTimer

-(id)initWithInterval:(double) interval andDelegate:(id<SimpleTimerDelegate>)delegate

{

    self = [super init];

    if (self) {

        _interval = interval;

        _delegate = delegate;

        running = NO;

    }

    return self;

}

-(void)start

{

    if (!running) {

        // Ensure we cannot be destroyed while our thread is running

        [self retain];

        [self setExitRequested:0];

 

        // We will not attempt to join the timer thread, which means the stop

        // method can be safely called on it

        pthread_attr_t atts;

        pthread_attr_init(&atts);

        pthread_attr_setdetachstate(&atts, PTHREAD_CREATE_DETACHED);

 

        if (0 == pthread_create(&timerThread, &atts, timerThreadRoutine, self)) {

            running = YES;

        }

        else {

            [self release];

        }

    }

}

-(void)stop

{

    if (running) {

        [self setExitRequested:1];

        running = NO;

    }

}

@end

Как только класс SimpleTimer был определён, убедитесь в том, что добавили SimpleTimer.h и SimpleTimer.m к образцу VideoPlayback в Xcode (эти файлы можно добавить в фолдер /VideoPlayback/Classes/apps/VideoPlayback/)

Изменения кода в VideoPlayerHelper.h

Отредактируйте файл VideoPlayerHelper.h (адрес — VideoPlayback/Classes/apps/VideoPlayback/), добавив следующий оператор импорта:

#import «SimpleTimer.h»

Добавьте следующее объявление членов в список @private:

SimpleTimer * simpleFrameTimer;

Кроме того измените объявление @interface в VideoPlayerHelper, добавив протокол <SimpleTimerDelegate>, то есть заменив эту строку:

@interface VideoPlayerHelper : NSObject {

на эту:

@interface VideoPlayerHelper : NSObject <SimpleTimerDelegate> {

Изменения в VideoPlayerHelper.mm

Добавьте этот метод, реализующий протокол SimpleTimerDelegate:

// implement timerDidTick method of <SimpleTimerDelegate> protocol

— (void)timerDidTick

{

    [self getNextVideoFrame];

}

И также этот метод:

— (void)stopFrameTimer

{

    // Stop the SimpleTimer

    [simpleFrameTimer stop];

    [simpleFrameTimer release];

    simpleFrameTimer = nil;

 

    // Make sure we do not leak a sample buffer

    [latestSampleBufferLock lock];

 

    if (NULL != latestSampleBuffer) {

        // Release the latest sample buffer

        CFRelease(latestSampleBuffer);

        latestSampleBuffer = NULL;

    }

 

    [latestSampleBufferLock unlock];

}

Далее в методе play:fromPosition: замените это:

[self performSelectorInBackground:@selector(createFrameTimer) withObject:nil];

на это:

[self createFrameTimer];

В методе pause замените это:

[self waitForFrameTimerThreadToEnd];

на это:

[self stopFrameTimer];

В методе stop это:

[self waitForFrameTimerThreadToEnd];

на это:

[self stopFrameTimer];

В методе getNextVideoFrame это:

[frameTimer invalidate];

на это:

[self stopFrameTimer];

Наконец, в методе createFrameTimer замените весь код реализации метода на эти две строки:

simpleFrameTimer = [[SimpleTimer alloc] initWithInterval:(1 / videoFrameRate) andDelegate:self];

[simpleFrameTimer start];

По материалам Vuforia

Если вы нашли ошибку, пожалуйста, сообщите нам, выделив текст и нажав клавиши Shift + E или кликнув сюда.

Раздел
Новости

Другие статьи