【问题标题】:Strange data in PCM Samples from AVAssetReader来自 AVAssetReader 的 PCM 样本中的奇怪数据
【发布时间】:2015-01-18 18:38:22
【问题描述】:

我正在使用 AVAssetReader 从 iOS 设备上的音乐中提取样本。在每首曲目的结尾,我都会遇到一些奇怪的数据:

18834289801492731920107175936.000000(0x6e736d70)
somesample
somesample
19285086905947468252206596096000.000000(0x7373697a)

这两个数字总是接近曲目的结尾(可能在最后几千个样本中),并且在它们之间总是有 2 个看似正常的样本。

这是我为设置AVAssetReader而编写的代码:

NSURL* url = [now_playing valueForProperty:MPMediaItemPropertyAssetURL];
if (url == nil)
{
    // DRM
    continue;
}

AVURLAsset* asset = [AVURLAsset URLAssetWithURL:url options:nil];
NSError* error = nil;
reader = [[AVAssetReader alloc] initWithAsset:asset error:&error];

if (error != nil)
{
    NSLog(@"Error initialising AVAssetReader");
    NSLog(@"%@", error.localizedDescription);
    continue;
}

AVAssetTrack* track = [asset.tracks objectAtIndex:0];

NSDictionary* output_settings = [[NSDictionary alloc]
    initWithObjectsAndKeys:

    [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
    [NSNumber numberWithInt:44100], AVSampleRateKey,
    [NSNumber numberWithInt:1], AVNumberOfChannelsKey,
    [NSNumber numberWithInt:32], AVLinearPCMBitDepthKey,
    [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
    [NSNumber numberWithBool:YES], AVLinearPCMIsFloatKey,
    [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, nil];

reader_output =
    [[AVAssetReaderTrackOutput alloc] initWithTrack:track
                     outputSettings:output_settings];
[reader addOutput:reader_output];
[reader startReading];

while(true)
{
    CMSampleBufferRef sample_buffer = [reader_output copyNextSampleBuffer];
    if (sample_buffer == nil)
    {
        continue;
    }

    CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(sample_buffer);

    uint32 block_size = CMBlockBufferGetDataLength(block_buffer);
    if (block_size > buffer_size)
    {
        if (buffer != nullptr)
        {
            delete[] buffer;
            buffer = nullptr;
        }

        buffer_size = block_size;
        buffer = new uint8[buffer_size];
    }

    char* returned_pointer = nullptr;
    OSStatus status =
        CMBlockBufferAccessDataBytes(block_buffer, 0, block_size, buffer, &returned_pointer);
    if (status != kCMBlockBufferNoErr)
    {
        NSLog(@"status != kCMBlockBufferNoErr");
        break;
    }

    uint32 num_floats = buffer_size / sizeof(float);
    float32* src = reinterpret_cast<float32*>(returned_pointer);

    float32* dst = &m_data[(m_write_slice * SAMPLES_PER_SLICE) % BUFFER_SIZE];

    for (uint32 i = 0; i < num_floats; ++i, ++m_write_index)
    {
        m_data[m_write_index] = src[i];
    }

    CFRelease(sample_buffer);
}

这是我误读的某种签名吗?

【问题讨论】:

    标签: ios objective-c avfoundation avassetreader


    【解决方案1】:

    前段时间发现了问题,忘记在这里补充答案了。

    // Note here, block_size is the ACTUAL SIZE OF THE BLOCK
    uint32 block_size = CMBlockBufferGetDataLength(block_buffer);
    
    // And here, buffer_size is the SIZE OF THE BIGGEST BLOCK RECEIVED SO FAR 
    if (block_size > buffer_size)
    {
        if (buffer != nullptr)
        {
            delete[] buffer;
            buffer = nullptr;
        }
    
        buffer_size = block_size;
        buffer = new uint8[buffer_size];
    }
    
    char* returned_pointer = nullptr;
    OSStatus status =
        CMBlockBufferAccessDataBytes(block_buffer, 0, block_size, buffer, &returned_pointer);
    if (status != kCMBlockBufferNoErr)
    {
        NSLog(@"status != kCMBlockBufferNoErr");
        break;
    }
    
    // THIS IS THE PROBLEM
    // A silly mistake, if the last block is smaller than buffer_size, it will cause the loop
    // below to read too many floats. It should really be 
    // uint32 num_floats = block_size / sizeof(float)
    uint32 num_floats = buffer_size / sizeof(float);
    float32* src = reinterpret_cast<float32*>(returned_pointer);
    
    float32* dst = &m_data[(m_write_slice * SAMPLES_PER_SLICE) % BUFFER_SIZE];
    
    for (uint32 i = 0; i < num_floats; ++i, ++m_write_index)
    

    【讨论】:

    • 我是新手。我不确定应该用什么来代替CMBlockBufferAccessDataBytes(block_buffer, 0, block_size, buffer, &amp;returned_pointer); 中的缓冲区。我不确定什么是临时阻塞。你能帮我理解吗
    • @prabhu 'buffer' 是一个 uint8 数组,分配有 buffer = new uint8[buffer_size]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    相关资源
    最近更新 更多