You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
5.9 KiB

#import "OpusBridge.h"
#import "opus.h"
// 编码器结构体
typedef struct {
OpusEncoder *encoder;
int channels;
int sampleRate;
int frameSize;
} OpusEncoderWrapper;
// 解码器结构体
typedef struct {
OpusDecoder *decoder;
int channels;
int sampleRate;
} OpusDecoderWrapper;
@implementation OpusBridge {
OpusEncoderWrapper *_encoderWrapper;
OpusDecoderWrapper *_decoderWrapper;
}
#pragma mark - 初始化和销毁
- (instancetype)init {
self = [super init];
if (self) {
_encoderWrapper = NULL;
_decoderWrapper = NULL;
}
return self;
}
- (void)dealloc {
[self disposeEncoder];
[self disposeDecoder];
}
#pragma mark - 编码器方法
- (BOOL)createEncoderWithSampleRate:(int)sampleRate
channels:(int)channels
application:(int)application
complexity:(int)complexity
frameSize:(int)frameSize {
// 先释放已有资源
[self disposeEncoder];
int error = OPUS_OK;
OpusEncoder *encoder = opus_encoder_create(sampleRate, channels, application, &error);
if (error != OPUS_OK || encoder == NULL) {
NSLog(@"[OpusBridge] Failed to create encoder: %s", opus_strerror(error));
return NO;
}
// 设置编码器参数
opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(complexity));
// 创建封装结构
_encoderWrapper = malloc(sizeof(OpusEncoderWrapper));
_encoderWrapper->encoder = encoder;
_encoderWrapper->channels = channels;
_encoderWrapper->sampleRate = sampleRate;
_encoderWrapper->frameSize = frameSize;
NSLog(@"[OpusBridge] Encoder created: sampleRate=%d, channels=%d", sampleRate, channels);
return YES;
}
- (NSData *)encodePCMData:(NSData *)pcmData {
if (_encoderWrapper == NULL || _encoderWrapper->encoder == NULL) {
NSLog(@"[OpusBridge] Encoder not initialized");
return nil;
}
// 检查PCM数据大小是否匹配
int frameSize = _encoderWrapper->frameSize;
int channels = _encoderWrapper->channels;
// PCM数据大小 = 帧大小 * 声道数 * 每样本字节数(2字节)
int frameBytes = frameSize * channels * 2;
if (pcmData.length < frameBytes) {
NSLog(@"[OpusBridge] PCM data too small: %lu bytes (need %d bytes)",
(unsigned long)pcmData.length, frameBytes);
return nil;
}
// 创建输出缓冲区 - 通常编码后的数据会小于PCM,可以用更小的缓冲区
// 但这里保守起见,使用相同大小的缓冲区
const int maxEncodedSize = (int)pcmData.length;
unsigned char *encodedData = malloc(maxEncodedSize);
// 编码
int encodedBytes = opus_encode(
_encoderWrapper->encoder,
(const opus_int16 *)[pcmData bytes],
frameSize,
encodedData,
maxEncodedSize
);
if (encodedBytes <= 0) {
NSLog(@"[OpusBridge] Encoding failed: %s", opus_strerror(encodedBytes));
free(encodedData);
return nil;
}
// 封装为NSData并返回
NSData *result = [NSData dataWithBytes:encodedData length:encodedBytes];
free(encodedData);
NSLog(@"[OpusBridge] Encoded %d bytes", encodedBytes);
return result;
}
- (void)disposeEncoder {
if (_encoderWrapper) {
if (_encoderWrapper->encoder) {
opus_encoder_destroy(_encoderWrapper->encoder);
_encoderWrapper->encoder = NULL;
}
free(_encoderWrapper);
_encoderWrapper = NULL;
NSLog(@"[OpusBridge] Encoder disposed");
}
}
#pragma mark - 解码器方法
- (BOOL)createDecoderWithSampleRate:(int)sampleRate channels:(int)channels {
// 先释放已有资源
[self disposeDecoder];
int error = OPUS_OK;
OpusDecoder *decoder = opus_decoder_create(sampleRate, channels, &error);
if (error != OPUS_OK || decoder == NULL) {
NSLog(@"[OpusBridge] Failed to create decoder: %s", opus_strerror(error));
return NO;
}
// 创建封装结构
_decoderWrapper = malloc(sizeof(OpusDecoderWrapper));
_decoderWrapper->decoder = decoder;
_decoderWrapper->channels = channels;
_decoderWrapper->sampleRate = sampleRate;
NSLog(@"[OpusBridge] Decoder created: sampleRate=%d, channels=%d", sampleRate, channels);
return YES;
}
- (NSData *)decodeOpusData:(NSData *)opusData frameSize:(int)frameSize {
if (_decoderWrapper == NULL || _decoderWrapper->decoder == NULL) {
NSLog(@"[OpusBridge] Decoder not initialized");
return nil;
}
// 准备输出缓冲区,frameSize * channels 个short类型
int outputSizeInSamples = frameSize * _decoderWrapper->channels;
int outputSizeInBytes = outputSizeInSamples * sizeof(opus_int16);
opus_int16 *outputBuffer = malloc(outputSizeInBytes);
// 解码
int samplesPerChannel = opus_decode(
_decoderWrapper->decoder,
[opusData bytes],
(int)[opusData length],
outputBuffer,
frameSize,
0 // 不使用FEC
);
if (samplesPerChannel <= 0) {
NSLog(@"[OpusBridge] Decoding failed: %s", opus_strerror(samplesPerChannel));
free(outputBuffer);
return nil;
}
// 实际输出大小
int actualSamples = samplesPerChannel * _decoderWrapper->channels;
int actualBytes = actualSamples * sizeof(opus_int16);
// 封装为NSData并返回
NSData *result = [NSData dataWithBytes:outputBuffer length:actualBytes];
free(outputBuffer);
NSLog(@"[OpusBridge] Decoded %d samples per channel", samplesPerChannel);
return result;
}
- (void)disposeDecoder {
if (_decoderWrapper) {
if (_decoderWrapper->decoder) {
opus_decoder_destroy(_decoderWrapper->decoder);
_decoderWrapper->decoder = NULL;
}
free(_decoderWrapper);
_decoderWrapper = NULL;
NSLog(@"[OpusBridge] Decoder disposed");
}
}
@end