ios - 从 RTMP 流 ios 播放 aac 音频

标签 ios objective-c audio rtmp aac

我正在尝试播放从 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/

相关文章:

ios - 使用 Swift 和 Firebase 更改用户电子邮件和密码

IOS应用程序图标名称仍然需要@2x?

javascript - webpack 别名未按 React 类函数中的预期解析

javascript - 如何删除 HTML5 音频标签中的下载选项?

iOS 重定向到 AppStore 以填写账单信息。填写后如何在应用程序中返回用户?

ios - 在 : 以下使用 imagePickerController 委托(delegate)函数时获取模糊引用

html - 用于 Objective-C 语法高亮显示的 Ruby 库

ios - 如何将 View 添加到整个屏幕

ios - 从服务器预加载视频文件以便在 MPMoviePlayerController 中播放

android - 在Android中检测声音的响度