0

まず、AVCaptureSession を使用して、camero と micophone から vedio とオーディオをキャプチャします。次に、以下のメソッド コードをデリゲートします。

 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{

     // if is Vedio data ,append to vedioInputWriter
    if (mediaType == kCMMediaType_Vedio){
        // ...
        // ...
        // ...
        // write the video data
        if (_assetWriterVideoInput.readyForMoreMediaData){
           [_assetWriterInputPixelBufferAdaptor appendPixelBuffer:renderedOutputPixelBuffer withPresentationTime:timestamp];
        }
        return;
    }


    size_t bufferListSizeNeededOut;
    CMBlockBufferRef blockBufferOut = nil;

    // get AudioBufferList
    err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
                                                                  &bufferListSizeNeededOut,
                                                                  currentInputAudioBufferList,
                                                                  CAAudioBufferList::CalculateByteSize(currentInputASBD.mChannelsPerFrame),
                                                                  kCFAllocatorSystemDefault,
                                                                  kCFAllocatorSystemDefault,
                                                                  kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
                                                                  &blockBufferOut); 

    // mix recorded audio with background music 
    [self mixAudioBufferListwithBackgroundMusic:currentInputAudioBufferList];

    if (!self.audioInputAssetWriter.readyForMoreMediaData) {
        if (self.assetWriter.status == AVAssetWriterStatusFailed) {
            NSLog(@"assetWrite error=%@",self.viewController.assetWriter.error);
        }
        return;
    }

    // tranfer `AudioBufferList` to `CMSampleBuffer`
    CMSampleBuffer newSampleBuffer = [self processAudioData:outputBufferList->ABL() framesNumber:numberOfFrames format:&mClientFormat];

    // append samplebuffer to assetInputWriter
    if ([self.audioInputAssetWriter appendSampleBuffer:newSampleBuffer]) {
        NSLog(@" append sample buffer success");
    }else{
         NSLog(@"append sample buffer failed");
    }
}

以下のコードに転送AudioBufferListします。CMSampleBuffer

- (CMSampleBufferRef)processAudioData:(AudioBufferList *)audioData framesNumber:(UInt32 )num format:(AudioStreamBasicDescription *)asbd
{
    CMSampleBufferRef sbuf;
    OSStatus status;
    // 1.audio foramt description
    CMAudioFormatDescriptionRef format;
    status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault,&(bufferToSampleFormat), 0, NULL, 0, NULL, NULL, &format); 

    // 2.sample timing info
    CMSampleTimingInfo timing;
    timing.duration = CMTimeMake(1,44100);
    timing.presentationTimeStamp = kCMTimeZero;
    timing.decodeTimeStamp = kCMTimeInvalid;

    size_t sampleSizeArray[1] = {4};

    // 3.create sample buffer
    status = CMSampleBufferCreate(kCFAllocatorDefault,NULL,false, NULL,NULL,format,(CMItemCount)num,1,&timing,0,NULL, &sbuf);

    // 4.sample buffer set data buffer from audio buffer list
    status = CMSampleBufferSetDataBufferFromAudioBufferList(sbuf, kCFAllocatorDefault, kCFAllocatorDefault, 0, audioData);
    if (status != noErr) {
        NSLog(@"sample buffer set data buffer from audio buffer list failed -- %d",(int)status);
        return nil;
    }
    return sbuf;
}

最後に、ビデオとオーディオ データをtest.movファイルとして保存します。VLC でファイルを再生し、音を出します。また、ffmpeg で aac 形式のオーディオ ファイルを剥がすことができます。

AudioBufferList問題は への転送だと思いCMSampleBufferます。いくつかの情報が欠落しているため、Quicktime が正しく再生できません。

4

0 に答える 0