标签: video-toolbox

如何使用VideoToolbox解压缩H.264视频流

在弄清楚如何使用Apple的硬件加速视频框架来解压缩H.264视频流时,我遇到了很多麻烦.几个星期后,我想出来,想分享一个广泛的例子,因为我找不到一个.

我的目标是提供WWDC '14会议513中介绍的Video Toolbox的全面,有启发性的示例.我的代码将无法编译或运行,因为它需要与基本H.264流集成(如从文件读取视频或从在线等流式传输),并且需要根据具体情况进行调整.

我应该提一下,除了我在谷歌搜索主题时学到的东西,我对视频/解码的经验很少.我不知道有关视频格式,参数结构等的所有细节,所以我只包括我认为你需要知道的内容.

我正在使用XCode 6.2并已部署到运行iOS 8.1和8.2的iOS设备.

objective-c h.264 ios8 video-toolbox

61
推荐指数
4
解决办法
4万
查看次数

如何在没有VideoToolbox的情况下访问tvOS上的硬件解码?

由于VideoToolbox不适用于tvOS,我该如何解码视频?

我有一个应用程序,我在内存中有h.264的帧(通过网络流),我之前使用VideoToolbox处理解码.什么是替代品?

decoding video-streaming video-toolbox tvos

10
推荐指数
1
解决办法
804
查看次数

AVFoundation与VideoToolbox - 硬件编码

所以这是一个更理论化的问题/讨论,因为我无法从网上找到其他SO帖子和来源的明确答案.似乎有很多选择:

Brad Larson关于AVFoundation的评论

视频解码加速

VideoToolbox

如果我想在iOS上为H.264(mov)文件进行硬件解码,我可以简单地使用AVFoundation和AVAssets,还是应该使用VideoToolbox(或任何其他框架).使用这些时,如何在运行项目时分析/基准测试硬件性能? - 只是通过简单地查看XCode中"Debug Navigator"中的CPU使用情况?

简而言之,我基本上是在询问AVFoundation和AVAssets是否执行硬件编码?它们是否足够,我如何对实际性能进行基准测试?

谢谢!

avfoundation h.264 ios video-toolbox

8
推荐指数
1
解决办法
1894
查看次数

在iOS上显示CVImageBufferRef的最有效方法是什么?

我有CMSampleBufferRef(s),我使用VTDecompressionSessionDecodeFrame解码,在帧的解码完成后导致CVImageBufferRef,所以我的问题是......

在UIView中显示这些CVImageBufferRefs最有效的方法是什么?

我已经成功地CVImageBufferRef转换为CGImageRef和显示那些由设置CGImageRef作为CALayer的内容但随后DecompressionSession已配置@ {(ID)kCVPixelBufferPixelFormatTypeKey:[NSNumber的numberWithInt:kCVPixelFormatType_32BGRA]};

这是示例/代码我如何将CVImageBufferRef转换为CGImageRef(注意:cvpixelbuffer数据必须是32BGRA格式才能使用)

    CVPixelBufferLockBaseAddress(cvImageBuffer,0);
    // get image properties 
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(cvImageBuffer);
    size_t bytesPerRow   = CVPixelBufferGetBytesPerRow(cvImageBuffer);
    size_t width         = CVPixelBufferGetWidth(cvImageBuffer);
    size_t height        = CVPixelBufferGetHeight(cvImageBuffer);

    /*Create a CGImageRef from the CVImageBufferRef*/
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef    cgContext  = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGImageRef cgImage = CGBitmapContextCreateImage(cgContext);

    // release context and colorspace 
    CGContextRelease(cgContext);
    CGColorSpaceRelease(colorSpace);

    // now CGImageRef can be displayed either by setting CALayer content
    // or by creating a [UIImage withCGImage:geImage] that can …
Run Code Online (Sandbox Code Playgroud)

opengl-es core-graphics avfoundation ios video-toolbox

8
推荐指数
1
解决办法
2151
查看次数

使用VTDecompressionSession的图像缓冲区显示顺序

我有一个项目,我需要从实时网络流解码h264视频,最终得到一个纹理,我可以在iOS设备上的另一个框架(Unity3D)中显示.我可以使用VTDecompressionSession成功解码视频,然后使用CVMetalTextureCacheCreateTextureFromImage(或OpenGL变体)获取纹理.当我使用低延迟编码器并且图像缓冲器按显示顺序出现时,它工作得很好,但是,当我使用常规编码器时,图像缓冲区不按显示顺序出现,重新排序图像缓冲区显然要困难得多.我期望.

第一次尝试是使用kVTDecodeFrame_EnableAsynchronousDecompression和kVTDecodeFrame_EnableTemporalProcessing设置VTDecodeFrameFlags ...然而,事实证明VTDecompressionSession可以选择忽略该标志并做任何它想要的......在我的情况下,它选择忽略该标志并仍然输出编码器顺序的缓冲区(不是显示顺序).基本上没用.

下一次尝试是将图像缓冲区与显示时间戳相关联,然后将它们放入一个向量中,这样我就可以在创建纹理时抓取所需的图像缓冲区.问题似乎是进入与时间戳相关联的VTDecompressionSession的图像缓冲区不再是出现的相同缓冲区,从而使时间戳无效.

例如,进入解码器......

  VTDecodeFrameFlags flags = kVTDecodeFrame_EnableAsynchronousDecompression;
  VTDecodeInfoFlags flagOut;
  // Presentation time stamp to be passed with the buffer
  NSNumber *nsPts = [NSNumber numberWithDouble:pts];

  VTDecompressionSessionDecodeFrame(_decompressionSession, sampleBuffer, flags,
                                          (void*)CFBridgingRetain(nsPts), &flagOut);
Run Code Online (Sandbox Code Playgroud)

在回调方......

void decompressionSessionDecodeFrameCallback(void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef imageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration)
 {
      // The presentation time stamp...
      // No longer seems to be associated with the buffer that it went in with!
      NSNumber* pts = CFBridgingRelease(sourceFrameRefCon);
 }
Run Code Online (Sandbox Code Playgroud)

订购时,回调端的时间戳按预期速率单调增加,但缓冲区的顺序不正确.有没有人在这里看到我在哪里犯错误?或者知道如何确定回调端缓冲区的顺序?在这一点上,我已经尝试了我能想到的一切.

core-video ios video-toolbox

8
推荐指数
1
解决办法
1903
查看次数

使用 CGDisplayStream 编码 H.264 压缩会话

我正在尝试使用屏幕上的数据创建 H.264 压缩会话。我创建了一个CGDisplayStreamRef这样的实例:

displayStream = CGDisplayStreamCreateWithDispatchQueue(0, 100, 100, k32BGRAPixelFormat, nil, self.screenCaptureQueue, ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
    //Call encoding session here
});
Run Code Online (Sandbox Code Playgroud)

以下是我目前如何设置编码功能:

- (void) encode:(CMSampleBufferRef )sampleBuffer {
    CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
    CMTime presentationTimeStamp = CMTimeMake(frameID++, 1000);
    VTEncodeInfoFlags flags;
    OSStatus statusCode = VTCompressionSessionEncodeFrame(EncodingSession,
                                                          imageBuffer,
                                                          presentationTimeStamp,
                                                          kCMTimeInvalid,
                                                          NULL, NULL, &flags);
    if (statusCode != noErr) {
        NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode);

        VTCompressionSessionInvalidate(EncodingSession);
        CFRelease(EncodingSession);
        EncodingSession = NULL;
        return;
    }
    NSLog(@"H264: VTCompressionSessionEncodeFrame Success");
}
Run Code Online (Sandbox Code Playgroud)

我试图了解如何将屏幕上的数据转换为 ,CMSampleBufferRef以便我可以正确调用我的编码功能。到目前为止,我无法确定这是否可行,或者我正在尝试做的事情的正确方法。有没有人有什么建议? …

core-graphics objective-c h.264 iosurface video-toolbox

6
推荐指数
1
解决办法
1135
查看次数

为什么AVSampleBufferDisplayLayer会因操作中断(-11847)而失败?

我正在使用AVSampleBufferDisplayLayer解码和显示从服务器流式传输的H.264视频。当我的应用进入后台并返回到前台时,解码过程就会搞砸并且AVSampleBufferDisplayLayer失败。我看到的错误是:

H.264 decoding layer has failed: Error Domain=AVFoundationErrorDomain
  Code=-11847 "Operation Interrupted" UserInfo=0x17426c500
  {NSUnderlyingError=0x17805fe90 "The operation couldn’t be completed.
    (OSStatus error -12084.)",
   NSLocalizedRecoverySuggestion=Stop other operations and try again.,
   NSLocalizedDescription=Operation Interrupted}
Run Code Online (Sandbox Code Playgroud)

还有其他人遇到这样的问题AVSampleBufferDisplayLayer吗?这是什么意思?

AVSampleBufferDisplayLayer收到错误后,我尝试销毁并创建一个新错误,但是随后我开始从H.264解码器收到其他错误:

Error Domain=AVFoundationErrorDomain Code=-11821 "Cannot Decode"
UserInfo=0x1740e9700 {AVErrorMediaSubTypeKey=(1635148593),
  NSLocalizedFailureReason=The media data could not be decoded. It may be damaged.,
  NSUnderlyingError=0x174247680 "The operation couldn’t be completed. (OSStatus error -12909.)",
  AVErrorMediaTypeKey=vide,
  AVErrorPresentationTimeStampKey=CMTime: {7/30 = 0.233},
  NSLocalizedDescription=Cannot Decode}
Run Code Online (Sandbox Code Playgroud)

AVSampleBufferDisplayLayer失败之前,我没有收到任何这些错误。

h.264 ios video-toolbox

5
推荐指数
1
解决办法
1181
查看次数

如何使用VideoToolbox将音频和视频编码为h264格式?

我可以使用视频工具箱框架将从相机设备捕获的视频压缩为h264格式,但是当我尝试在VLC播放器中播放该h264文件时,我无法听到视频的音频.我认为音频压缩也应该在代码中完成.

但是我怎么没找到任何资源?

objective-c video-streaming h.264 swift video-toolbox

5
推荐指数
1
解决办法
555
查看次数

如何使用 AVAssetWriter 将 colorProfile 添加到使用 CGDisplayStream 从屏幕录制的视频中

我编写了一个屏幕录制应用程序,它使用 VideoToolbox 和 AVWriter 写出 H.264 电影文件。与原始屏幕相比,录制文件中的颜色有点暗淡。我知道这是因为 colorProfile 未存储在视频文件中。

这与如何对 AVAssetWriter 输出进行颜色管理密切相关

我创建了一个测试台来在 github ScreenRecordTest上展示这一点

如果您运行此应用程序,您可以使用 CMD-R 开始录制并使用相同的 CMD-R 停止录制(您必须开始和停止录制一次才能获得完整写入的电影文件)。您将在 /tmp/ 文件夹中找到类似以下名称的录音:“/tmp/grab-2018-10-25 09:23:32 +0000.mov”

录制时,应用程序会显示两个实时图像:a)从 CGDisplayStream 获取的帧 - 和 - b)来自压缩器的 cmSampleBuffer。

我发现从 CGDisplayStream 返回的 IOSurface 没有进行颜色管理,因此您会注意到压缩之前已经出现“暗淡”颜色。如果您取消 AppDelegate.swift 中第 89 行的注释

// cgImage = cgImage.copy(colorSpace: screenColorSpace)!
Run Code Online (Sandbox Code Playgroud)

此实时预览将具有正确的颜色。现在这仅用于显示压缩前的 IOSurface。我不知道如何使其他实时预览(压缩后)(AppDelegate 中的第 69 行)显示正确的颜色(例如:如何将 colorProfile 应用于 CMSampleBuffer),或者最重要的是如何使用正确的配置文件,以便在打开 .mov 文件时我在播放时获得正确的颜色。

macos avfoundation avassetwriter video-toolbox

5
推荐指数
0
解决办法
315
查看次数

在 OSX 上最佳使用 hevc_videotoolbox 和 ffmpeg

我正在使用 ffmpeg 4.3.1 将视频从 h264 转换为 h265,最初我很高兴地发现我可以使用我的 Mac 的 GPU 来加速转换,并带有 hevc_videotoolbox 标志。

我的 Mac 硬件是第 10 代 Intel i5 和 AMD Radeon Pro 5300

我正在使用这个命令:

ffmpeg -i input_h264.mp4 -c:v hevc_videotoolbox -b:v 6000K -c:a copy -crf 19 -preset veryslow output_h265.mp4
Run Code Online (Sandbox Code Playgroud)

转换速度从 0.75 倍提高到 4 倍,几乎提高了 500%!

但后来我注意到大文件和稍微模糊的结果。然后我注意到更改 crf 或预设没有区别,ffmpeg 似乎忽略了这些设置。唯一似乎有效的设置是视频比特率 (-b:v)。

所以我开始在谷歌上搜索,看看如何才能获得更好的结果。

但是除了这里和那里的一些帖子之外,我大部分时间都是空白的。

我在哪里可以获得有关如何使用 hevc_videotoolbox 获得更好结果的文档?如何找出哪些设置有效,哪些设置被忽略?

macos ffmpeg hevc video-toolbox

3
推荐指数
3
解决办法
2639
查看次数

如何为VTCompressionSession设置比特率

我正在努力将我们的应用程序从一些专有的编解码器移动到iOS本机h264编码器(VideoToolbox.framework)并且有疑问:

是否存在为压缩数据设置比特率或数据速率的方法?

以下是我创建编码器会话的方法:

CFMutableDictionaryRef sessionAttributes = CFDictionaryCreateMutable(
                                                                     NULL, 
                                                                     0,    
                                                                     &kCFTypeDictionaryKeyCallBacks,
                                                                     &kCFTypeDictionaryValueCallBacks);

//** bitrate
int fixedBitrate = bitrate; // 2000 * 1024 -> assume 2 Mbits/s

CFNumberRef bitrateNum = CFNumberCreate(NULL, kCFNumberSInt32Type, &fixedBitrate);
CFDictionarySetValue(sessionAttributes, kVTCompressionPropertyKey_AverageBitRate, bitrateNum);
CFRelease(bitrateNum);

CFDictionarySetValue(sessionAttributes, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_High_AutoLevel);

CFDictionarySetValue(sessionAttributes, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);

OSStatus error = VTCompressionSessionCreate(kCFAllocatorDefault,
                                            width,
                                            height,
                                            kCMVideoCodecType_H264,
                                            sessionAttributes, 
                                            NULL, 
                                            kCFAllocatorDefault,  
                                            &EncoderCallback,
                                            this, *outputCallbackRefCon,
                                            &m_EncoderSession);
Run Code Online (Sandbox Code Playgroud)

我玩了很多不同的价值观,kVTCompressionPropertyKey_AverageBitRate但这对我没什么用,我也试过 kVTCompressionPropertyKey_DataRateLimits不同的价值但也没有任何运气.

任何想法,建议都是受欢迎的

ios video-toolbox

2
推荐指数
1
解决办法
3992
查看次数

CMSampleBuffer 中的 CMBlockBuffer 所有权

我正在编写代码来解压本机附件 B H.264 流,我正在完成解析流的过程,从 SPS/PPS NALU 创建 CMVideoFormatDescription,并包装我从流中提取的其他 NALU在 CMSampleBuffers 中。

我在如何处理解码器的 CMBlockBuffer 和 CMSampleBuffer 内存方面遇到了心理障碍。我相信我的问题更多是缺乏对 CF 如何处理内存的透彻理解,所以我的问题更多的是关于这一点,但我希望上下文有帮助。

如果我像这样创建一个 CMBlockBuffer:

CMBlockBufferRef blockBuffer;

OSStatus status = CMBlockBufferCreateWithMemoryBlock(NULL,
                                                     memoryBlock,                       
                                                     blockBufferLength,
                                                     kCFAllocatorNull,
                                                     NULL,
                                                     0, 
                                                     blockBufferLength,          
                                                     kCMBlockBufferAlwaysCopyDataFlag | kCMBlockBufferAssureMemoryNowFlag,
                                                     &blockBuffer);
Run Code Online (Sandbox Code Playgroud)

并将其添加到 CMSampleBuffer 中,如下所示:

CMSampleBufferRef sampleBuffer;

status = CMSampleBufferCreate(kCFAllocatorDefault,
                              blockBuffer,
                              true,
                              NULL,
                              NULL,
                              formatDescription,
                              1,
                              0,
                              NULL,
                              1,
                              &sampleSize,
                              &sampleBuffer);
Run Code Online (Sandbox Code Playgroud)

我应该如何处理块缓冲区?SampleBuffer 是否保留块缓冲区的内存,或者我是否需要做一些事情来确保它没有被释放?

另外,关于异步解码过程,是否有一种明智的方法可以知道解码器何时使用 CMSampleBuffer 完成以便我可以处理它?

我的直觉告诉我 CMSampleBuffer 会保留 CMBlockBuffer,而 VTDecodeSession 会保留 CMSampleBuffer 直到它完成解码,但这是一个未记录的领域,我正在寻找一些方向。我得到的结果暗示我的直觉可能是错误的,所以我需要排除内存管理作为一个问题来保持我的理智......

macos h.264 cmsamplebufferref cmsamplebuffer video-toolbox

1
推荐指数
1
解决办法
816
查看次数