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

wao*_*813 2 macos ffmpeg avfoundation

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

wao*_*813 5

在参考VideoCore项目之后,我可以使用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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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);
        }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 获取VTCallback中的编码帧,这是一个C方法,用作VTCompressionSessionCreate()的参数

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