【问题标题】:How to encode picture to H264 use AVFoundation on Mac, not use x264如何将图片编码为 H264 在 Mac 上使用 AVFoundation,而不是使用 x264
【发布时间】:2015-06-12 16:44:39
【问题描述】:

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

【问题讨论】:

    标签: macos ffmpeg avfoundation


    【解决方案1】:

    参考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中获取编码帧,这是一个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);
      
      }
      

    【讨论】:

    • 我有你做的3个功能。但是我的回调永远不会被调用。我错过了什么吗?
    • @dcheng,如果你和我的一样,它应该可以工作。确保回调函数和其他函数必须在同一个类中。
    猜你喜欢
    • 2011-11-10
    • 2013-08-08
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    相关资源
    最近更新 更多