gpt4 book ai didi

ios - 从 RTMP 流 ios 播放 aac 音频

转载 作者:行者123 更新时间:2023-12-01 16:22:38 27 4
gpt4 key购买 nike

我正在尝试播放从 RTMP 流中接收到的音频(我已设法播放视频部分)。音频采用 .aac 格式。我有 NSData 来了。然后我将其放入 CMAudiSampleBuffer 并将其加入 AVSampleBufferAudioRenderer。 (基本上我正在做与视频数据包相同的事情)。

一切都很好,只是我没有声音。现在我对objective-c和iOS编程很陌生,所以问题可能来自其他地方,欢迎所有想法。

这是我用来制作格式描述的代码

-(void)createFormatDescription:(NSData*)payload
{
OSStatus status;
NSData* data = [NSData dataWithData:[payload subdataWithRange:NSMakeRange(2, [payload length]-2)]];
const uint8_t* bytesBuffer = [data bytes];
_type = bytesBuffer[0]>>3;
_frequency = [self getSampleRate:(bytesBuffer[0] & 0b00000111) << 1 | (bytesBuffer[1] >> 7)];
_channel = (bytesBuffer[1] & 0b01111000) >> 3;
AudioStreamBasicDescription audioFormat;
audioFormat.mFormatID = kAudioFormatMPEG4AAC;
audioFormat.mSampleRate = _frequency;
audioFormat.mFormatFlags = _type;
audioFormat.mBytesPerPacket = 0;
audioFormat.mFramesPerPacket = 1024;
audioFormat.mBytesPerFrame = 0;
audioFormat.mChannelsPerFrame = _channel;
audioFormat.mBitsPerChannel = 0;
audioFormat.mReserved = 0;
status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &audioFormat, 0, nil, 0, nil, nil, &_formatDesc);
}

这是我使用在数据包前面添加 adts 数据并创建缓冲区的代码:
- (NSData*) adts:(int)length
{
int size = 7;
int fullSize =length + size;
uint8_t adts[size];
adts[0] = 0xFF;
adts[1] = 0xF9;
adts[2] = (_type - 1) << 6 | (_frequency << 2) | (_channel >> 2);
adts[3] = (_channel & 3) << 6 | (fullSize >> 11);
adts[4] = (fullSize & 0x7FF) >> 3;
adts[5] = ((fullSize & 7) << 5) + 0x1F;
adts[6] = 0xFC;
NSData* result = [NSData dataWithBytes:adts length:size];
return result;
}

-(void)enqueueBuffer:(RTMPMessage*)message {
OSStatus status;
NSData* payloadData = [NSData dataWithData:[message.payloadData
subdataWithRange:NSMakeRange(2, [message.payloadData length]-2)]];
NSData* adts = [NSData dataWithData:[self adts:(int)[payloadData length]]];
NSMutableData* data = [NSMutableData dataWithData:adts];
[data appendData:payloadData];
uint8_t* bytesBuffer[[data length]];
[data getBytes:bytesBuffer length:[data length]];
const size_t sampleSize = [data length];
AudioStreamPacketDescription packetDescription;
packetDescription.mDataByteSize = (int)sampleSize;
packetDescription.mStartOffset = 0;
packetDescription.mVariableFramesInPacket = 0;
CMBlockBufferRef blockBuffer = NULL;
CMSampleBufferRef sampleBuffer = NULL;
CMTime time = CMTimeMake(5, _frequency);
status = CMBlockBufferCreateWithMemoryBlock(NULL, bytesBuffer, [data length], kCFAllocatorNull, NULL, 0, [data length], 0, &blockBuffer);
status = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, blockBuffer, true, NULL, NULL, _formatDesc, 1, time, &packetDescription, &sampleBuffer);
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
[_audioRenderer enqueueSampleBuffer:sampleBuffer];

}

提前感谢您的帮助

最佳答案

ADTS header 不是必需的。 AVAudioSampleRenderer 只需要裸 aac 压缩包即可播放。但前提是您设置了正确的格式描述,以及创建样本缓冲区的正确参数。

您需要注意的是,HE-AAC(LC+SBR) 像 AAC-LC 一样包装,但采样率为 22050。 HE-V2(LC+SBR+PS) 与 AAC-LC 类似,但采样率为 22050,每个采样一个 channel 。
并且所有 HE-AAC(v1,v2),samplesPerFrame 总是 2048,不像 LC 的 1024。

这就是我所知道的如何正确使用 AVAudioSampleRenderer 播放 aac 流。成功的路还很长。。

关于ios - 从 RTMP 流 ios 播放 aac 音频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50957320/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com