AVAssetReader音频捕获,样本丢失

时间:2014-03-06 09:49:56

标签: cocoa avfoundation avassetreader

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

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的持续时间从Audacity和音频轨道持续时间mainAudioTrack.timeRange报告为3.75,而打印样本长度和播放偏移量的代码转储为:3.657120

这是转储:

2014-03-06 10:48:15.721 FrameDecoder [665:303]收到带有[TIMESTAMP:0.0ms]的PCM缓冲区 2014-03-06 10:48:15.721 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.721 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]缓冲区包含[样本:8192] 2014-03-06 10:48:15.721 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.722 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:371.5ms] 2014-03-06 10:48:15.722 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.722 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.722 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:557.3ms] 2014-03-06 10:48:15.722 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.722 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.723 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:743.0ms] 2014-03-06 10:48:15.723 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.723 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.723 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:928.8ms] 2014-03-06 10:48:15.726 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.726 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.727 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:1114.6ms] 2014-03-06 10:48:15.727 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.727 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.727 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:1300.3ms] 2014-03-06 10:48:15.727 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.727 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.727 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:1486.1ms] 2014-03-06 10:48:15.728 FrameDecoder [665:303]缓冲区包含[样本: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]缓冲区包含[样本: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:1857.6ms] 2014-03-06 10:48:15.729 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.729 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.729 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:2043.4ms] 2014-03-06 10:48:15.729 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.729 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.729 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:2229.1ms] 2014-03-06 10:48:15.730 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.730 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.730 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:2414.9ms] 2014-03-06 10:48:15.730 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.730 FrameDecoder [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]缓冲区包含[样本:8192] 2014-03-06 10:48:15.731 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.731 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:2786.4ms] 2014-03-06 10:48:15.731 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.731 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.732 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:2972.2ms] 2014-03-06 10:48:15.732 FrameDecoder [665:303]缓冲区包含[样本:8192] 2014-03-06 10:48:15.732 FrameDecoder [665:303]缓冲区包含[DURATION:185.8ms]音频 2014-03-06 10:48:15.732 FrameDecoder [665:303]收到PCM缓冲区[TIMESTAMP:3157.9ms] 2014-03-06 10:48:15.732 FrameDecoder [665: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:3343.7ms] 2014-03-06 10:48:15.733 FrameDecoder [665: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]缓冲区包含[样本:5631] 2014-03-06 10:48:15.734 FrameDecoder [665:303]缓冲区包含[DURATION:127.7ms]音频 2014-03-06 10:48:15.734 FrameDecoder [665:303]总样本持续时间:3.657120 2014-03-06 10:48:15.734 FrameDecoder [665:303]报道的总报道持续时间:3.750000

有人遇到过像这样的奇怪问题吗?我尝试过多个音频文件以及压缩不同的.mov文件。同样的东西!我完全坚持这个!

同样,当我通过AudioUnits播放样本时,它会发现实际上缺少的是从样本开始的那些......

谢谢!

1 个答案:

答案 0 :(得分: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个样本: - (