0

First I use AVCaptureSession capture vedio and audio from camero and micophone. Then delegate method code below:

 - (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");
    }
}

Tranfer AudioBufferList to CMSampleBuffer code below:

- (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;
}

Last,save the vedio and audio data as a test.mov file.Question is play the file with Quicktime,but no sound. Play the file with VLC ,have sound.And can peel out an aac format audio file with ffmpeg.

I guess the problem is tranfer AudioBufferList to CMSampleBuffer,missing some infomation lead to Quicktime can not play correctly.

alpine
  • 927
  • 6
  • 17
  • It looks like you are trying to use 2 AVAssetWriter? with video+Audio, you just use one writer with both inputs pointing into it. – Sean Lintern Apr 20 '16 at 13:15
  • @SeanLintern88 I use one AVAssetWriter for both video and audio.The above code is pseudo code。 – alpine Apr 20 '16 at 13:18

0 Answers0