官方文档对 CMSampleBufferRef 描述如下: A reference to a CMSampleBuffer. 即 CMSampleBufferRef 是对 CMSampleBuffer[2] 的一个引用。 所里这里核心的数据结构是 CMSampleBuffer,关于它有如下几点需要注意: CMSampleBuffer 则是一个 Core Foundation 的对象,这意味着它的接口是 C 语言实现,它的内存管理是非 CMSampleBuffer 是系统用来在音视频处理的 pipeline 中使用和传递媒体采样数据的核心数据结构。 其中数据拷贝自 AudioBufferList,并将 CMBlockBuffer 实例关联到 CMSampleBuffer 实例。
CMVideoFormatDescription: video的格式,包括宽高、颜色空间、编码格式等;对于H.264的视频,PPS和SPS的数据也在这里; CMBlockBuffer:未压缩的图像数据; CMSampleBuffer CMSampleBuffer的结构: ? 当我们需要原始H.264码流包装成CMSampleBuffer时,我们可以按照以下步骤: 1、替换头字节长度; 2、用CMBlockBuffer把NALUnit包装起来; 3、把SPS和PPS包装成 CMVideoFormatDescription; 4、添加CMTime时间; 5、创建CMSampleBuffer; ? 根据H.264原始码流创建CMSampleBuffer 当我们需要更新SPS和PPS的时候,调用 VTDecompressionSessionCanAcceptFormatDescription判断是否能接受新的
CMVideoFormatDescription video的格式,包括宽高、颜色空间、编码格式等;对于H.264的视频,PPS和SPS的数据也在这里; CMBlockBuffer 未压缩的图像数据; CMSampleBuffer 全文仅此GIF 具体细节 1、把原始码流包装成CMSampleBuffer ? &mFormatDescription); 4、添加CMTime时间; (WWDC视频上说有,但是我在实现过程没有找到添加的地方,可能是我遗漏了) 5、创建CMSampleBuffer NULL, 1, sampleSizeArray, &sampleBuffer); 2、解码并显示 1、传入CMSampleBuffer
1 - 解析视频中的物体飞行轨迹 轨迹检测需要保存状态,因此其传入的图像分析参数需要为包含CMTime信息的CMSampleBuffer数据。 对于一个视频文件,我们首先要做的是将其中的图像帧解析出来,即获取到CMSampleBuffer数据。 } } } } } processFram方法进行轨迹分析,实现如下: func processFrame(_ sampleBuffer: CMSampleBuffer time : CMTime, withDuration duration : CMTime) { // 创建句柄 let handler = VNImageRequestHandler(cmSampleBuffer
CMSampleBufferCreateReady(...)[31]:基于媒体数据创建一个 CMSampleBuffer。 CMFormatDescription[40]:用于描述 CMSampleBuffer 中采样的格式信息。 CMAttachment[45]:为 CMSampleBuffer 添加支持的 metadata。 copyNextSampleBuffer[111]:从 Output 拷贝下一个 CMSampleBuffer。 language=objc [30]CMSampleBuffer: https://developer.apple.com/documentation/coremedia/cmsamplebuffer-u71
平台下如何实现摄像头的视频采集前言视频采集,从编程的角度来看,也就是拿到摄像头采集到的图像数据,至于拿到数据之后的用途,可以五花八门,想干嘛就干嘛,比如:存储为照片、写入本地文件、编码后进行传输、本地预览CMSampleBuffer 在开始之前,必须先了解 CMSampleBuffer 的概念,它可以简单理解为媒体数据之外加了一层封装,在视频相关场景下,其可以包含未编码的视频数据(CVPixelBuffer),也可以包含编码过的视频数据 (CMBlockBuffer)CMSampleBuffer 组成部分CMTime:图像的时间CMVideoFormatDescription:图像格式的描述CMBlockBuffer or CVPixelBuffer sampleBuffer fromConnection:(AVCaptureConnection *)connection 方法给出,且该方法被调用的线程,就是之前我们创建的串行队列对应的线程采集到的原始视频数据,存放在 CMSampleBuffer 中,前面的章节也提到,CMSampleBuffer 可以包含未编码的视频数据,存放在 CVPixelBuffer 中,获取 CVPixelBuffer 的代码如下CVPixelBufferRef pixel_buffer
音频播放 :从音频读取接口mReaderAudioTrackOutput加载音频信息得到CMSampleBuffer,用方法CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer 把音频数据转成AudioBufferList格式,再采用AudioUnit播放; 视频播放:从视频读取接口mReaderVideoTrackOutput加载视频信息得到CMSampleBuffer,用方法
在我们这个 Demo 中,我们想要将采集的图像数据直接转换并存储为图片,所以我们会设置采集的颜色空间格式为 kCVPixelFormatType_32BGRA,这样将更方便将 CMSampleBuffer ; } } - (UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer { // 从 CMSampleBuffer // 从 CMSampleBuffer 获取 CVImageBuffer(也是 CVPixelBuffer)。 这里的颜色空间要与 CMSampleBuffer 图像数据的颜色空间一致。 -imageFromSampleBuffer: 方法实现了将 CMSampleBuffer 转换为 UIImage 的逻辑。
因为 CMSampleBuffer 中的采样是按照解码顺序存储的,展示顺序可能与解码顺序一致,也可能不一致。 在 CMSampleBuffer 中,采样是以解码顺序存储的,即使与展示顺序不一致。 CMFormatDescription[52]:用于描述 CMSampleBuffer 中采样的格式信息。 copyNextSampleBuffer[127]:从 Output 拷贝下一个 CMSampleBuffer。 language=objc [36] CMSampleBuffer: https://developer.apple.com/documentation/coremedia/cmsamplebuffer-u71
completionHandler: AVAssetExportSession 可以将 AVAsset 媒体文件内容由指定的预设格式进行输出 AVAssetWriter 可以将媒体数据 CMSampleBuffer 相比 AVAssetExportSession AVAssetReader + AVAssetWriter 可以有更细粒度的配置,比如我们可以将 CMSampleBuffer 经过特效处理后写入文件 CMSampleBuffer 是 Core Foundation 对象,是音频, 视频的压缩或未压缩数据样本。
设置 customModeType 属性,可选自定义采集视频 CUSTOM_MODE_VIDEO_CAPTURE 和自定义采集音频 CUSTOM_MODE_AUDIO_CAPTURE 2种类型; 设置CMSampleBuffer CMSampleBuffer的输出分辨率sampleBufferSize 建议优先选择autoSampleBufferSize,否则务必保证传给SDK的视频数据分辨率和这里设置的移植。
Data, orientation: CGImagePropertyOrientation, options: [VNImageOption : Any] = [:]) public init(cmSampleBuffer sampleBuffer: CMSampleBuffer, options: [VNImageOption : Any] = [:]) public init(cmSampleBuffer sampleBuffer : CMSampleBuffer, orientation: CGImagePropertyOrientation, options: [VNImageOption : Any] = [:]) } VNImageRequestHandler
} //然后将采集到的数据封装成SDK需要的格式 func captureVideoDataOutput(capture: TRTCAVCapture, sampleBuffer: CMSampleBuffer sendCustomVideoData(videoFrame) } func captureAudioDataOutput(capture: TRTCAVCapture, sampleBuffer: CMSampleBuffer
requested to finish the broadcast. } override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer 3、processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) 终于来到了最重要的方法了
AVFoundation——加载视频; CoreVideo——配置纹理; OpenGL ES——渲染视频; 3D数学——球体以及3维变换; 核心思路 通过AVFoundation加载视频源,读取到每一帧的CMSampleBuffer 开始读取视频帧; 通过mReaderVideoTrackOutput的copyNextSampleBuffer可以获取到下一帧的视频信息; 通过CMSampleBufferGetImageBuffer可以获取到CMSampleBuffer
= noErr) { return; } // 把 PCM 数据所在的 CMBlockBuffer 封装到 CMSampleBuffer 而从 Demuxer 获取的一个 CMSampleBuffer 可能包含多个包,所以这里要拆一下包,再送给解码器。 &packetBlockBuffer); if (status == noErr) { // 3、将 CMBlockBuffer 封装到 CMSampleBuffer 3)将解封装后的数据拆包,以包为单位封装为 CMSampleBuffer 送给解码器解码。 在 -decodeSampleBuffer: 方法中实现。
我们需要做的是录制影像并将其转换为 CMSampleBuffer。 的扩展(Extension)中插入下面的代码: func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer 基本上这个函数所做的就是它确认 CMSampleBuffer 是否存在以及提供一个 AVCaptureOutput。
*) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer:(unsigned char**) pBGRA { // 为媒体数据设置一个CMSampleBuffer
IDR 帧,则会用到该参数调用 VTCompressionSessionEncodeFrame 方法进行编码,iOS 9 开始支持用 block 处理编码回调,比起静态函数方便了很多,编码后的数据存储在 CMSampleBuffer 需要通过 CMSampleBufferRef 对应的 CMFormatDescriptionRef 读取 sps 和 pps 数据,然后拼接到关键帧数据的头部,因为 sps 和 pps 数据不会被包含在 CMSampleBuffer
,didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,from connection: AVCaptureConnection!)