2015-07-10 1 views
4

Я пытаюсь преобразовать AudioBufferList что я получаю от блока Audio в CMSampleBuffer, что я могу передать в AVAssetWriter, чтобы сохранить звук с микрофона. Это преобразование работает, поскольку вызовы, которые я делаю для выполнения преобразования, не терпят неудачу, но запись в конечном итоге не выполняется, и я вижу некоторый вывод в журналах, которые, как представляется, вызывают беспокойство.Преобразование AudioBufferList к CMSampleBuffer Производит Неожиданные результаты

код я использую, выглядит так:

- (void)handleAudioSamples:(AudioBufferList*)samples numSamples:(UInt32)numSamples hostTime:(UInt64)hostTime { 
    // Create a CMSampleBufferRef from the list of samples, which we'll own 
    AudioStreamBasicDescription monoStreamFormat; 
    memset(&monoStreamFormat, 0, sizeof(monoStreamFormat)); 
    monoStreamFormat.mSampleRate = 48000; 
    monoStreamFormat.mFormatID = kAudioFormatLinearPCM; 
    monoStreamFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved; 
    monoStreamFormat.mBytesPerPacket = 2; 
    monoStreamFormat.mFramesPerPacket = 1; 
    monoStreamFormat.mBytesPerFrame = 2; 
    monoStreamFormat.mChannelsPerFrame = 1; 
    monoStreamFormat.mBitsPerChannel = 16; 

    CMFormatDescriptionRef format = NULL; 
    OSStatus status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &monoStreamFormat, 0, NULL, 0, NULL, NULL, &format); 
    if (status != noErr) { 
     // really shouldn't happen 
     return; 
    } 

    CMSampleTimingInfo timing = { CMTimeMake(1, 48000), kCMTimeZero, kCMTimeInvalid }; 

    CMSampleBufferRef sampleBuffer = NULL; 
    status = CMSampleBufferCreate(kCFAllocatorDefault, NULL, false, NULL, NULL, format, numSamples, 1, &timing, 0, NULL, &sampleBuffer); 
    if (status != noErr) { 
     // couldn't create the sample buffer 
     PTKLogError(@"Failed to create sample buffer"); 
     CFRelease(format); 
     return; 
    } 

    // add the samples to the buffer 
    status = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer, 
                  kCFAllocatorDefault, 
                  kCFAllocatorDefault, 
                  0, 
                  samples); 
    if (status != noErr) { 
     PTKLogError(@"Failed to add samples to sample buffer"); 
     CFRelease(sampleBuffer); 
     CFRelease(format); 
     return; 
    } 

    NSLog(@"Original sample buf size: %ld for %d samples from %d buffers, first buffer has size %d", CMSampleBufferGetTotalSampleSize(sampleBuffer), numSamples, samples->mNumberBuffers, samples->mBuffers[0].mDataByteSize); 
    NSLog(@"Original sample buf has %ld samples", CMSampleBufferGetNumSamples(sampleBuffer)); 

Как я уже говорил, не кажется такой код, терпит неудачу, сама по себе, но AVAssetWriter не нравится, и CMSampleBuffer что Я создаю, кажется, размер 0, основываясь на том факте, что следующие записи журнала в настоящее время вошли:

2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf size: 0 for 1024 samples from 1 buffers, first buffer has size 2048 
2015-07-09 19:34:00.710 xxxx[1481:271334] Original sample buf has 1024 samples 

как ни странно, буфер выборки сообщает, что он имеет 1024 выборок, но размер 0. Оригинальный AudioBufferList имеет 2048 байт данных, что я ожидаю от 1024 2-байтовых выборки.

Я делаю что-то неправильно с точки зрения того, как я инициализирую и заселяю CMSampleBuffer?

ответ

1

Оказывается, тот факт, что размер выборки возвращался как 0, был красной селедкой. После того, как я вымыл несколько вещей, - в частности, я поставил метку правильно, например, так:

uint64_t timeNS = (uint64_t)(hostTime * _hostTimeToNSFactor); 
CMTime presentationTime = CMTimeMake(timeNS, 1000000000); 
CMSampleTimingInfo timing = { CMTimeMake(1, 48000), presentationTime, kCMTimeInvalid }; 

запись начала работать.

Таким образом, в случае, если кто-то другой сброшен размером буфера сообщения, указанным в сообщении 0, имейте в виду, что это нормально, по крайней мере, в том случае, если вы подаете данные в AVAssetWriter.

+0

Что такое _hostTimeToNSFactor? спасибо –

+0

@PabloMartinez Мы вычислили его, вызвав 'mach_timebase_info' и эту математику:' _hostTimeToNSFactor = (double) tinfo.numer/tinfo.denom'. Однако может быть лучший подход: https://developer.apple.com/library/ios/qa/qa1643/_index.html –

+0

Спасибо Джим, и какое значение вы передаете функции в hostTime? –