Видеопоток в AVSampleBufferDisplayLayer не отображается на скриншоте

Я использовал новые методы Video Toolbox, чтобы взять видеопоток H.264 и отобразить его в контроллере вида, используя AVSampleBufferDisplayLayer, Это все работает, как задумано, и поток выглядит великолепно. Однако, когда я пытаюсь сделать скриншот всего представления, содержимое AVSampleBufferDisplayLayer (то есть распакованный видеопоток) не отображаются на снимке. Снимок показывает все другие кнопки пользовательского интерфейса / метки / и т.д. но скриншот показывает только цвет фона AVSampleBufferDisplayLayer (который я установил на ярко-синий), а не в прямом эфире видео.

В методе ниже (вдохновленный этим постом) я беру SampleBuffer из моего потока и поставить его в очередь для отображения на AVSampleBufferDisplayLayer, Затем я вызываю мой метод imageFromLayer: чтобы получить снимок как UIImage, (Затем я либо отображаю этот UIImage в UIImageView imageDisplay, либо сохраняю его в локальном списке камеры устройства, чтобы проверить, что UIImage похоже. Оба метода дают одинаковый результат.)

-(void) h264VideoFrame:(CMSampleBufferRef)sample
{
    [self.AVSampleDisplayLayer enqueueSampleBuffer:sample];

    dispatch_sync(dispatch_get_main_queue(), ^(void) {
        UIImage* snapshot = [self imageFromLayer:self.AVSampleDisplayLayer];
        [self.imageDisplay setImage:snapshot];
    });
}

Здесь я просто беру содержимое AVSampleBufferDisplayLayer и попытаться преобразовать его в UIImage, Если я передам весь экран в этот метод в качестве слоя, будут отображаться все другие элементы пользовательского интерфейса, такие как ярлыки / кнопки / изображения, кроме AVDisplayLayer, Если я пройду только AVDisplayLayer, Я получаю сплошное синее изображение (так как цвет фона синий).

- (UIImage *)imageFromLayer:(CALayer *)layer
{
    UIGraphicsBeginImageContextWithOptions([layer frame].size, YES, 1.0);

    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

    //UIImageWriteToSavedPhotosAlbum(outputImage, self, nil, nil);

    UIGraphicsEndImageContext();

    return outputImage;
}

Я пытался использовать UIImage snapshot = [self imageFromLayer: self.AVSampleDisplayLayer.presentationLayer]; а также .modelLayer, но это не помогло. Я попытался поставить в очередь сэмплбуфер и подождать, прежде чем сделать снимок, я попытался поиграться с непрозрачностью и xPosition AVDisplayLayer... Я даже пытался установить разные значения для CMTimebase из AVDisplayLayer, Любые советы приветствуются!

Также согласно этому посту и этому посту у других людей возникают похожие проблемы со снимками в iOS 8.

1 ответ

Решение

Я исправил это, переключившись с AVSampleDisplayLayer в VTDecompressionSession, в VTDecompression didDecompress метод обратного вызова, отправляю распакованное изображение (CVImageBufferRef) в следующем методе, чтобы получить скриншот видео потока и превратить его в UIImage,

-(void) screenshotOfVideoStream:(CVImageBufferRef)imageBuffer
{
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
    CIContext *temporaryContext = [CIContext contextWithOptions:nil];
    CGImageRef videoImage = [temporaryContext
                             createCGImage:ciImage
                             fromRect:CGRectMake(0, 0, 
                             CVPixelBufferGetWidth(imageBuffer), 
                             CVPixelBufferGetHeight(imageBuffer))];

    UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
    [self doSomethingWithOurUIImage:image];
    CGImageRelease(videoImage);
}
Другие вопросы по тегам