如何将图片编码为H264在Mac上使用AVFoundation,而不是使用x264

时间:2015-04-07 22:35:45

标签: macos ffmpeg avfoundation

我正在尝试使用FFmpeg而不是x264库将Mac广播客户端编码为H264。 所以基本上,我可以在CMSampleBufferRefAVPicture中从AVFoundation中获取原始帧。那么有没有办法使用Apple框架将一系列图片编码为H264帧,如AVVideoCodecH264。 我知道编码它的方法使用AVAssetWriter,但是只将视频保存到文件中,但我不想要文件,相反,我想要AVPacket,所以我可以使用FFmpeg发送。有谁有想法吗?谢谢。

1 个答案:

答案 0 :(得分:5)

在参考VideoCore project后,我可以使用Apple的VideoToolbox框架在硬件中进行编码。

  1. 启动VTCompressionSession:

    // Create compression session
    err = VTCompressionSessionCreate(kCFAllocatorDefault,
                                 frameW,
                                 frameH,
                                 kCMVideoCodecType_H264,
                                 encoderSpecifications,
                                 NULL,
                                 NULL,
                                 (VTCompressionOutputCallback)vtCallback,
                                 self,
                                 &compression_session);
    
    if(err == noErr) {
        comp_session = session;
    }
    
  2. 将原始帧推送到VTCompressionSession

    // Delegate method from the AVCaptureVideoDataOutputSampleBufferDelegate
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
        // get pixelbuffer out from samplebuffer
        CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        //set up all the info for the frame
        // call VT to encode frame
        VTCompressionSessionEncodeFrame(compression_session, pixelBuffer, pts, dur, NULL, NULL, NULL);
        }
    
  3. 在VTCallback中获取编码帧,这是一个用作VTCompressionSessionCreate()参数的C方法

    void vtCallback(void *outputCallbackRefCon,
            void *sourceFrameRefCon,
            OSStatus status,
            VTEncodeInfoFlags infoFlags,
            CMSampleBufferRef sampleBuffer ) {
        // Do whatever you want with the sampleBuffer
        CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
    
    }