2014-03-06 31 views
0

我有一个奇怪的问题。我正在捕获一些.mov/.wav/.aiff文件的音频样本以播放它们。 我使用以下代码捕获未更改的PCM样本(如果可用),否则将它们转换为32位浮点型。AVAssetReader音频捕获,样本丢失

NSError *error = nil; 
AVAssetReader *assetReader= [[[AVAssetReader alloc] initWithAsset:self.movieAsset error:&error] autorelease]; 
NSArray *audioTracks=[movieAsset tracksWithMediaType:AVMediaTypeAudio]; 
AVAssetReaderTrackOutput* audioReaderOutput=nil; 
AVAssetTrack *mainAudioTrack = nil; 
CMTimeRange audioRange; 
if ([audioTracks count]) { 
    mainAudioTrack=[audioTracks objectAtIndex:0]; 
    audioRange = mainAudioTrack.timeRange; 
    CMTimeRange readingRange = CMTimeRangeMake(kCMTimeZero,audioRange.duration); 
    assetReader.timeRange = readingRange; 
    NSArray* formatDesc = mainAudioTrack.formatDescriptions; 
    if ([formatDesc count]) { 
     CMAudioFormatDescriptionRef item = (CMAudioFormatDescriptionRef)[formatDesc objectAtIndex:0]; 
     const AudioStreamBasicDescription* pcmAudioDescription = CMAudioFormatDescriptionGetStreamBasicDescription (item); 
     NSDictionary * outputSettings; 
     memcpy(&audioDescription,pcmAudioDescription,sizeof(AudioStreamBasicDescription)); 

     if (pcmAudioDescription->mFormatID != kAudioFormatLinearPCM) { 

      // Resample 
      outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
           [NSNumber numberWithFloat:pcmAudioDescription->mSampleRate], AVSampleRateKey, 
           [NSNumber numberWithInt:pcmAudioDescription->mChannelsPerFrame], AVNumberOfChannelsKey, 
           [NSNumber numberWithInt:32], AVLinearPCMBitDepthKey, 
           [NSNumber numberWithBool:YES], AVLinearPCMIsFloatKey, 
           nil]; 

      audioDescription.mFormatID = kAudioFormatLinearPCM; 
      audioDescription.mBitsPerChannel = 32; 
      audioDescription.mFramesPerPacket = 1; 
      audioDescription.mChannelsPerFrame = pcmAudioDescription->mChannelsPerFrame; 
      audioDescription.mBytesPerFrame = audioDescription.mBitsPerChannel/8 * audioDescription.mChannelsPerFrame; 
      audioDescription.mBytesPerPacket = audioDescription.mFramesPerPacket * audioDescription.mBytesPerFrame; 
      audioDescription.mFormatFlags = kAudioFormatFlagIsFloat; 

     } else { 

      outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
           nil]; 

      audioDescription.mFormatID = kAudioFormatLinearPCM; 
     } 

     audioReaderOutput=[[[AVAssetReaderTrackOutput alloc] 
          initWithTrack:mainAudioTrack 
          outputSettings:outputSettings] autorelease]; 
     if([assetReader canAddOutput:audioReaderOutput]) [assetReader addOutput:audioReaderOutput]; 
     else audioReaderOutput = nil; 

    } 

} 

if (audioReaderOutput) { 
    if([assetReader startReading]==YES){ 
     CMSampleBufferRef buffer = 0; 
     NSTimeInterval duration = 0.0; 

     while([assetReader status]==AVAssetReaderStatusReading){ 
      if (audioReaderOutput != nil) { 
       buffer=[audioReaderOutput copyNextSampleBuffer]; 
       if (buffer) { 
        CMTime sampleDuration = CMSampleBufferGetDuration (buffer); 
        CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp (buffer); 
        MovieSample* sample = [[[MovieSample alloc] init] autorelease]; 
        sample.sampleTime = currentSampleTime; 
        sample.sampleBuffer = buffer; 
        sample.sampleDuration = sampleDuration; 
        [self.audioStore addObject:sample]; 
        //NSLog(@"Adding sample %lld %lld %f %f",currentSampleTime.value,sampleDuration.value,currentOutputSampleTime.value/(NSTimeInterval)currentOutputSampleTime.timescale, 
         // (currentOutputSampleTime.value+sampleDuration.value)/(NSTimeInterval)currentOutputSampleTime.timescale); 
        NSLog(@"Received PCM buffer with [TIMESTAMP:%.1fms]", CMTimeGetSeconds(currentSampleTime) * 1000); 
        NSLog(@"Buffer contains [SAMPLES:%ld]", CMSampleBufferGetNumSamples(buffer)); 
        NSLog(@"Buffer contains [DURATION:%.1fms] worth of audio", CMTimeGetSeconds(sampleDuration) * 1000); 
        duration += CMTimeGetSeconds(CMSampleBufferGetDuration(buffer)); 
       } 

      } 

     } 
     NSLog(@"Total samples duration: %f", duration); 
     NSLog(@"Total track reported duration: %f", audioRange.duration.value/(NSTimeInterval)audioRange.duration.timescale); 

    } 
    else { 
     DLog(@"could not start Audio reading asset."); 
     DLog(@"reader status: %ld", [assetReader status]); 
    } 


} 

现在奇怪的是,无论我开什么文件时,它总是在文件中错过了一些样品。 下面的循环http://www.vvertex.com/loop.wav有无论是从无畏和音频轨道持续时间,mainAudioTrack.timeRange报告为3.75的持续时间,而我的代码打印样品长度和播放抵消转储:3.657120

这是转储FrameDecoder [665:303] FrameDecoder [665:303] FrameDecoder [665:303]缓冲区包含:[TIMESTAMP:0.0ms]接收到的PCM缓冲区:

2014-03-06 10:48:15.721 FrameDecoder [665:303] FrameDecoder [665:303]缓冲包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.721 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:185.8ms] 2014-03-06 10:48:15.721 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]缓冲区包含[样本:8192] 2014-03-06 10:48:15.721 FrameDecoder [665:303]的音频信号 2014-03-06 10:48:15.722 FrameDecoder [665:303] FrameDecoder [665:303]缓冲区包含[SAMPLES :8192] 2014-03-06 10:48:15.722 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频帧解码器[665:303]接收到的PCM缓冲区包含[TIMESTAMP:557.3ms]缓冲区包含[SAMPLES:8192] BufferDecoder [665:303] BufferDecoder [665:303]缓冲区包含[包含[DURATION:185.8ms]的音频 2014-03-06 10:4 8:15.723 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10收到的带有[TIMESTAMP:743.0ms]的PCM缓冲区 2014-03-06 10:48:15.723 FrameDecoder [665:303] :48:15.723 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.723 FrameDecoder [665:303]收到的带有[TIMESTAMP:928.8ms]的PCM缓冲区 2014 -03-06 10:48:15.726 FrameDecoder [665:303]缓冲液含有[样品:8192] 2014年3月6日 10:48:15.726 FrameDecoder [665:303]缓冲液含有[DURATION:185.8ms]音频的值得帧解码器[665:303]缓冲器包含[样本:8192] ] 2014-03-06 10:48:15.727 FrameDecoder [665:303] Buffer contains [TIMERAMP:1300.3ms]收到的PCM缓冲器[TIMER:185.8ms] 2014-03-06 10:48:15.727 FrameDecoder [665:303] FrameDecoder [665 :303]缓冲器包含[时间:185.8ms]缓冲器包含[样品:8192] 2014-03-06 10:48:15.727 FrameDecoder [665:303] FrameDecoder [665:303]收到的PCM缓冲区[TIMESTAMP:1486.1ms] 2014-03-06 10:48:15.728 FrameDecoder [665:303]缓冲区包含[SAMPLES:8192] 2014-03-06 10:48:15.728 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.728 FrameDecoder [665:303]收到的PCM缓冲区为[TIMESTAMP:1671.8ms] 2014-03-06 10:48:15.728 FrameDecoder [665:303]缓冲区包含[SAMPLES:8192] 2014年3月6日10:48:15.728 FrameDecoder [665:303]缓冲液含有[DURATION:185.8ms]值得音频 2014年3月6日10:48:15.728 FrameDecoder [665:303]所获PCM缓冲液[ TIMESTAMP:1857.6ms] 2014-03-06 10:48:15。729 FrameDecoder [665:303] BufferDecoder [665:303]缓冲器包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.729 FrameDecoder [665:303] 48:15.729 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10收到的带有[TIMESTAMP:2043.4ms]的PCM缓冲区 2014-03-06 10:48:15.729 FrameDecoder [665:303] :48:15.729帧解码器[665:303]缓冲器包含[时长:185.8ms]的音频 2014-03-06 10:48:15.729帧解码器[665:303]收到的PCM缓冲器与[TIMESTAMP:2229.1ms] 2014 -03-06 10:48:15.730 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频缓冲区包含[样本:8192] 2014-03-06 10:48:15.730 FrameDecoder [665:303] 2014-03-06 10:48:15.730 FrameDecoder [665:303]收到的PCM bu帧解码器[665:303]缓冲器包含[样本:8192] 2014-03-06 10:48:15.730帧解码器[665:303]缓冲器包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.731 FrameDecoder [665:303]收到的PCM缓冲区[TIMESTAMP:2600.6ms] 2014-03-06 10:48:15.731 FrameDecoder [ 665:303]缓冲区包含[DATE:185.8ms]缓冲区包含[DATE:185.8ms] 2014-03-06 10:48:15 FrameDecoder [665:303]收到的PCM缓冲区[TIMESTAMP:2786.4ms] 2014-03-06 10:48:15.731 FrameDecoder [665:303]缓冲区包含[SAMPLES:8192] 2014-03-06 10:48: 15.731 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.732 FrameDecoder [665:303] FrameDecoder [665:303]缓冲区包含[SAMPLES:8192 ] 2014-03-06 10:48:15.732 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频数据FrameDecoder [665:303]帧解码器[665:303]缓冲器包含[样本:8192] 2014-03-06 10:48:15.733帧解码器[665:303]帧频解码器[665:303]收到的PCM缓冲器与[TIMESTAMP:3343.7ms] 2014-03-06 10:48:15.733帧解码器[665:303.7ms]价值的音频 2014-03-06 10:48:15.733 FrameDecoder [ 303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.733 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]的音频 2014-03-06 10:48:15.733 FrameDecoder [665:303]收到的PCM缓冲区[TIMESTAMP:3529.4ms] 2014-03-06 10:48:15.734 FrameDecoder [665:303]缓冲区包含[DURATION:127.7ms]的音频 2014-03缓冲区包含[样本:5631] 2014-03-06 10:48:15.734 FrameDecoder [665:303] -06 10:48:15.734 FrameDecoder [665:303]总样本持续时间:3.657120 2014-03-06 10:48:15.734 FrameDecoder [665:303]总的曲目报告的持续时间:3.750000

任何人都会遇到一个奇怪的像这样的问题?我已经尝试了几个音频文件以及具有不同压缩的.mov文件。相同的东西!我完全沉迷于此!

此外,当我通过AudioUnits打样品,它的接缝什么有效缺少的是从样品的开始....

谢谢!

+0

附加说明,AVReaderWriterOSX样品有同样的问题,它轧液音频采样的初始部分!这是否意味着AVAssetReader不好翻录音频样本? –

回答

0

我的解决办法...

//starting 2 buffers before 
[_reader setTimeRange:CMTimeRangeMake(CMTimeMake(-16384, samplerate), kCMTimeNegativeInfinity)]; 

//and 
while ([_reader status] == AVAssetReaderStatusReading) { 
    CMSampleBufferRef sampleBufferRef = [_ringBufferReaderTrackOutput copyNextSampleBuffer]; 
    if (sampleBufferRef){ 
     CMTime t = CMSampleBufferGetOutputPresentationTimeStamp(sampleBufferRef); 
     if(t.value < 0) 
      release, continue... 
    } 

,但我缺少年底4096个样本:-(

+0

是啊苹果告诉我,AVAssetReader是窃听:/其实我生成了一个32位quicktime助手,撕裂音频,并通过NSConnection XPC发送回来.. –

+0

@LeonardoBernardini我相信我遇到了同样的问题:当阅读一个带有AVAssetReader的30-FPS mp4文件,它从不输出文件中最后一帧视频。此外,它将第一帧的时间戳解释为0.033333而不是0,这对我来说似乎很奇怪。你有没有向苹果公司提交错误报告?他们碰巧提供了任何解决方法吗? – gilby

+0

我还没有发现视频中缺少的样本,只是音频。我试过H264 .mov文件成功,但不是mp4。顺便说一下,苹果公司并没有给我提供解决方案,他们也把我的票推回“可用”! (洗手!) –