3

このライブラリに関するドキュメントは本質的に存在しないため、ここであなたの助けが本当に必要です.

目標: MPEG トランスポート ストリームに渡すことができるように、H264 エンコーディングが必要です (できればオーディオとビデオの両方を使用しますが、ビデオだけでも問題ありません。オーディオも動作させるために数日間試してみます)。

私が持っているもの:サンプルバッファを記録して出力するカメラがあります。入力はカメラバックと内蔵マイク。

いくつかの質問: A. カメラに CMSampleBuffer を H264 形式で出力させることは可能ですか?つまり、2014 では VTCompressionSessions から生成されていますが、captureOutput を書き込んでいるときに、既に CMSampleBuffer を取得していることがわかります... B. VTCompressionSession を設定するにはどうすればよいですか? セッションはどのように使用されますか?これに関する最上位レベルでの包括的な議論は、ほとんど文書化されていないこのライブラリで実際に何が起こっているのかを人々が理解するのに役立つかもしれません。

ここにコードを記述してください (必要に応じてさらに質問してください。コードの残りの部分がどの程度関連しているかがわからないため、captureOutput のみを入れています):

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
    println(CMSampleBufferGetFormatDescription(sampleBuffer))
    var imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    if imageBuffer != nil {
        var pixelBuffer = imageBuffer as CVPixelBufferRef
        var timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer as CMSampleBufferRef)
        //Do some VTCompressionSession stuff
    }
}

皆さんありがとう!

4

1 に答える 1

0

最初に VTCompression セッションを初期化し、そのプロパティを設定します

    NSDictionary* bAttributes= @{};

    VTCompressionSessionRef vtComp;
    OSStatus result = VTCompressionSessionCreate(NULL,
        trackSize.width,
        trackSize.height,
        kCMVideoCodecType_H264,
        NULL,
        (CFDictionaryRef)bAttributes,
        NULL,
        compressCallback,
        NULL,
        &vtComp);
    NSLog(@"create VTCS Status: %d",result);
    
    NSDictionary* compProperties = @{ 
        (id)kVTCompressionPropertyKey_ProfileLevel: (id)kVTProfileLevel_H264_High_AutoLevel,
        (id)kVTCompressionPropertyKey_H264EntropyMode: (id)kVTH264EntropyMode_CABAC,
        (id)kVTCompressionPropertyKey_Quality: @(0.95),
        (id)kVTCompressionPropertyKey_RealTime: @(YES),
        (id)kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder: @(YES),
        (id)kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder: @(YES)
    };

    result=VTSessionSetProperties(vtComp,(CFDictionaryRef)compProperties);

これcompressCallbackは、圧縮データが利用可能になったときに呼び出されるメソッドです。そして、このように見えます。

void compressCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer)
{
    AVAssetWriterInput* aw = (AVAssetWriterInput*)sourceFrameRefCon;    
    [aw appendSampleBuffer:sampleBuffer];
}

次に、読み取り/圧縮ループがあります。CMSample バッファーから CVImage バッファーを取得し、それをコンプレッサーに渡します。

        CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(cmbuf);
        VTEncodeInfoFlags encodeResult;

        result = VTCompressionSessionEncodeFrame (vtComp,
            buffer, 
            currentTime,
            frameDuration,
            NULL, // frameProperties
            writerInput, // opaque context to callback
            &encodeResult);

明らかに、ステータスを確認して値を返す必要がありますが、これにより正しい方向に進むはずです。

于 2020-06-25T07:24:12.780 に答える