来自 AVAssetReader 的 PCM 样本中的奇怪数据
Strange data in PCM Samples from AVAssetReader
我正在 iOS 设备上使用 AVAssetReader
从音乐中提取样本。在每首曲目的末尾,我遇到了一些奇怪的数据:
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);
}
这是我误读的某种签名吗?
我刚才发现问题了,忘记在这里添加答案了。
// 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)
我正在 iOS 设备上使用 AVAssetReader
从音乐中提取样本。在每首曲目的末尾,我遇到了一些奇怪的数据:
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);
}
这是我误读的某种签名吗?
我刚才发现问题了,忘记在这里添加答案了。
// 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)