Skip to content

Commit

Permalink
添加双声道aac
Browse files Browse the repository at this point in the history
Change-Id: Iffafcbab42a88e6819788b874ab90809d828d682
  • Loading branch information
tonychanchen committed Sep 20, 2022
1 parent f846c54 commit de3c48c
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,17 @@ - (void)getDeviceStatusWithType:(NSString *)singleType qualityType:(NSString *)q
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];

[[TIoTCoreXP2PBridge sharedInstance] sendVoiceToServer:weakSelf.deviceName?:@"" channel:channel];
// [[TIoTCoreXP2PBridge sharedInstance] sendVoiceToServer:weakSelf.deviceName?:@"" channel:channel];
TIoTCoreAudioConfig *audio_config = [TIoTCoreAudioConfig new];
audio_config.sampleRate = TIoTAVCaptionFLVAudio_8;
audio_config.channels = 1;
audio_config.isEchoCancel = NO;

TIoTCoreVideoConfig *video_config = [TIoTCoreVideoConfig new];
video_config.localView = nil;
video_config.videoPosition = AVCaptureDevicePositionFront;

[[TIoTCoreXP2PBridge sharedInstance] sendVoiceToServer:weakSelf.deviceName?:@"" channel:channel audioConfig:audio_config videoConfig:video_config];
}

}else {
Expand Down
2 changes: 1 addition & 1 deletion Source/SDK/LinkVideo/FLV/TIoTAACEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import "TIoTAVCaptionFLV.h"
#import "TIoTCoreAudioConfig.h"

@protocol TIoTAACEncoderDelegate <NSObject>
- (void)getEncoderAACData:(NSData *)data;
Expand Down
8 changes: 4 additions & 4 deletions Source/SDK/LinkVideo/FLV/TIoTAACEncoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ - (void)setUpConverter {
outAudioStreamBasicDescription.mBytesPerFrame = 0;
outAudioStreamBasicDescription.mFramesPerPacket = 1024;
//设定声道数为1
outAudioStreamBasicDescription.mChannelsPerFrame = 1;
outAudioStreamBasicDescription.mChannelsPerFrame = inAudioStreamBasicDescription.mChannelsPerFrame;
//设定采样率为16000
// outAudioStreamBasicDescription.mSampleRate = inAudioStreamBasicDescription.mSampleRate;
if (self.audioType == TIoTAVCaptionFLVAudio_8) {
Expand Down Expand Up @@ -145,14 +145,14 @@ -(void)encodePCMData:(NSData *)pcmdata {
FillComplexInputParm userParam;
userParam.source = pcmData;
userParam.sourceSize = (UInt32)pcmLength;
userParam.channelCount = 1;
userParam.channelCount = self->inAudioStreamBasicDescription.mChannelsPerFrame;
userParam.packetDescription = NULL;
//在堆区创建audiobufferlist
AudioBufferList outputBufferList;
outputBufferList.mNumberBuffers = 1;
outputBufferList.mBuffers[0].mData = outputBuffer;
outputBufferList.mBuffers[0].mDataByteSize = (UInt32)pcmLength;
outputBufferList.mBuffers[0].mNumberChannels = 1;
outputBufferList.mBuffers[0].mNumberChannels = self->inAudioStreamBasicDescription.mChannelsPerFrame;
//编码
OSStatus status = AudioConverterFillComplexBuffer(self->convertContext->converter, audioConverterComplexInputDataProc, &userParam, &packetSize, &outputBufferList, outputPacketDes);
free(outputPacketDes);
Expand Down Expand Up @@ -257,7 +257,7 @@ - (NSData*) adtsDataForPacketLength:(NSUInteger)packetLength {
// else if (self.audioType == TIoTAVCaptionFLVAudio_441) {
// freqIdx = 4;
// }
int chanCfg = 1; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
int chanCfg = inAudioStreamBasicDescription.mChannelsPerFrame; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
NSUInteger fullLength = adtsLength + packetLength;
// fill in ADTS data
packet[0] = (char)0xFF; // 11111111 = syncword
Expand Down
10 changes: 3 additions & 7 deletions Source/SDK/LinkVideo/FLV/TIoTAVCaptionFLV.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

typedef NS_ENUM(NSInteger, TIoTAVCaptionFLVAudioType) {
TIoTAVCaptionFLVAudio_8,
TIoTAVCaptionFLVAudio_16
};
#import "TIoTCoreAudioConfig.h"
#import "TIoTCoreVideoConfig.h"

@protocol TIoTAVCaptionFLVDelegate <NSObject>
-(void) capture:(uint8_t *)data len:(size_t) size;
Expand All @@ -17,7 +13,7 @@ typedef NS_ENUM(NSInteger, TIoTAVCaptionFLVAudioType) {
@property (nonatomic, assign)UIView *videoLocalView;
@property (nonatomic, assign)BOOL isEchoCancel;
@property (nonatomic, assign)AVCaptureDevicePosition devicePosition;
-(instancetype) initWithAudioConfig:(TIoTAVCaptionFLVAudioType)audioSampleRate;
-(instancetype) initWithAudioConfig:(TIoTAVCaptionFLVAudioType)audioSampleRate channel:(int)channel;

- (void)preStart;
- (BOOL)startCapture;
Expand Down
96 changes: 19 additions & 77 deletions Source/SDK/LinkVideo/FLV/TIoTAVCaptionFLV.mm
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,30 @@ @interface TIoTAVCaptionFLV ()<AVCaptureVideoDataOutputSampleBufferDelegate,AVCa
@property (nonatomic, strong) AVCaptureSession *session;
// 队列
@property (nonatomic, strong) dispatch_queue_t videoQueue;
@property (nonatomic, strong) dispatch_queue_t AudioQueue;

// 负责从 AVCaptureDevice 获得输入数据
@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;
@property (nonatomic, strong) AVCaptureConnection *videoConnection;
@property (nonatomic, strong) AVCaptureConnection *audioConnection;
// 拍摄预览图层
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic, strong) TIoTH264Encoder *h264Encoder;
@property (nonatomic, strong) TIoTAACEncoder *aacEncoder;
//@property (nonatomic, strong) NSMutableData *data;
//@property (nonatomic, copy ) NSString *h264File;
//@property (nonatomic, strong) NSFileHandle *fileHandle;
@property (nonatomic, assign) TIoTAVCaptionFLVAudioType audioRate;
@property (nonatomic, assign) int channel;
@property (nonatomic, assign) int captureVideoFPS;
@property (nonatomic, strong) AVCaptureSessionPreset resolutionRatioValue;
@property (nonatomic, strong) TIoTPCMXEchoRecord *pcmRecord;
@end

@implementation TIoTAVCaptionFLV

-(instancetype) initWithAudioConfig:(TIoTAVCaptionFLVAudioType)audioSampleRate {
-(instancetype) initWithAudioConfig:(TIoTAVCaptionFLVAudioType)audioSampleRate channel:(int)channel {
self = [super init];
if (self) {
tAVCaptionFLV = self;
_audioRate = audioSampleRate;
_channel = channel;
_isEchoCancel = NO;
_devicePosition = AVCaptureDevicePositionBack;
[self onInit];
Expand All @@ -68,7 +65,6 @@ -(void) onInit{

muxerQueue = dispatch_queue_create("FLV_Muxer_Queue", DISPATCH_QUEUE_SERIAL);

// _data = [NSMutableData new];
_session = [AVCaptureSession new];

self.resolutionRatioValue = AVCaptureSessionPreset352x288;
Expand All @@ -82,52 +78,17 @@ - (void)setupAudioCapture {
return;
}
AudioStreamBasicDescription inAudioStreamBasicDescription;
if (_isEchoCancel) {

self.pcmRecord = [[TIoTPCMXEchoRecord alloc] init];
[self.pcmRecord set_record_callback:record_callback user:(__bridge void * _Nonnull)(self)];
// [self.record start_record];

inAudioStreamBasicDescription = self.pcmRecord.pcmStreamDescription;
self.aacEncoder = [[TIoTAACEncoder alloc] initWithAudioDescription:inAudioStreamBasicDescription];
self.aacEncoder.delegate = self;
self.aacEncoder.audioType = _audioRate;
return;
}
self.pcmRecord = [[TIoTPCMXEchoRecord alloc] initWithChannel:_channel isEcho:_isEchoCancel];
[self.pcmRecord set_record_callback:record_callback user:(__bridge void * _Nonnull)(self)];
// [self.record start_record];

inAudioStreamBasicDescription = self.pcmRecord.pcmStreamDescription;
self.aacEncoder = [[TIoTAACEncoder alloc] initWithAudioDescription:inAudioStreamBasicDescription];
self.aacEncoder.delegate = self;
self.aacEncoder.audioType = _audioRate;

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];

NSError *error = nil;

AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc]initWithDevice:audioDevice error:&error];

if (error) {

NSLog(@"Error getting audio input device:%@",error.description);
}

if ([self.session canAddInput:audioInput]) {

[self.session addInput:audioInput];
}

self.AudioQueue = dispatch_queue_create("Audio Capture Queue", DISPATCH_QUEUE_SERIAL);

AVCaptureAudioDataOutput *audioOutput = [AVCaptureAudioDataOutput new];
[audioOutput setSampleBufferDelegate:self queue:self.AudioQueue];

if ([self.session canAddOutput:audioOutput]) {

[self.session addOutput:audioOutput];
}

self.audioConnection = [audioOutput connectionWithMediaType:AVMediaTypeAudio];


}

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
Expand Down Expand Up @@ -349,17 +310,10 @@ - (void)calculatorCaptureFPS {

#pragma mark - 实现 AVCaptureOutputDelegate:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
if (connection == _videoConnection) { // Video

if (self.videoLocalView) { //开关打开,才推送视频
[self.h264Encoder encode:sampleBuffer];

[self calculatorCaptureFPS];
}

} else if (connection == _audioConnection) { // Audio
if (self.videoLocalView) { //开关打开,才推送视频
[self.h264Encoder encode:sampleBuffer];

[self.aacEncoder encodeSampleBuffer:sampleBuffer];
[self calculatorCaptureFPS];
}
}

Expand Down Expand Up @@ -415,6 +369,7 @@ - (void)gotEncodedData:(NSData*)data isKeyFrame:(BOOL)isKeyFrame {

#pragma mark - TIoTAACEncoderDelegate
- (void)getEncoderAACData:(NSData *)data {
// [_fileHandle writeData:data];
encodeFlvData(0, data);
}

Expand Down Expand Up @@ -500,26 +455,22 @@ -(BOOL) startCapture {
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSString *documentsDirectory = [paths firstObject];

// self.h264File = [documentsDirectory stringByAppendingPathComponent:@"lyh.h264"];
// [fileManager removeItemAtPath:self.h264File error:nil];
// [fileManager createFileAtPath:self.h264File contents:nil attributes:nil];
// _fileHandle = [NSFileHandle fileHandleForWritingAtPath:self.h264File];
// NSString *h264File = [documentsDirectory stringByAppendingPathComponent:@"lyh.aac"];
// [fileManager removeItemAtPath:h264File error:nil];
// [fileManager createFileAtPath:h264File contents:nil attributes:nil];
// _fileHandle = [NSFileHandle fileHandleForWritingAtPath:h264File];

flv_init_load();

[self startCamera];

if (_isEchoCancel) {
[self.pcmRecord start_record];
}
[self.pcmRecord start_record];
return YES;
}

-(void) stopCapture{
[self stopCarmera];
if (_isEchoCancel) {
[self.pcmRecord stop_record];
}
[self.pcmRecord stop_record];
}

- (void) startCamera
Expand Down Expand Up @@ -551,15 +502,6 @@ - (void) stopCarmera
// [_fileHandle closeFile];
// _fileHandle = NULL;
//
// 获取程序Documents目录路径
/*NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSMutableString * path = [[NSMutableString alloc]initWithString:documentsDirectory];
[path appendString:@"/AACFile.aac"];
[_data writeToFile:path atomically:YES];
*/
}

- (void)setCameraFPS:(int)fps {
Expand Down
1 change: 1 addition & 0 deletions Source/SDK/LinkVideo/FLV/TIoTPCMXEchoRecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface TIoTPCMXEchoRecord : NSObject
@property (nonatomic, assign, readonly)AudioStreamBasicDescription pcmStreamDescription;

- (instancetype)initWithChannel:(int)channel isEcho:(BOOL)isEcho;
- (void)set_record_callback:(RecordCallback)c user:(void *)u;
- (void)start_record;
- (void)stop_record;
Expand Down
33 changes: 19 additions & 14 deletions Source/SDK/LinkVideo/FLV/TIoTPCMXEchoRecord.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
@interface TIoTPCMXEchoRecord()
{
AudioUnit audioUnit;
std::queue<std::pair<std::shared_ptr<char>, int>> queue;
std::mutex mutex;
RecordCallback callback;
void *user;
}

@end

@implementation TIoTPCMXEchoRecord
- (instancetype)init
- (instancetype)initWithChannel:(int)channel isEcho:(BOOL)isEcho
{
self = [super init];
if (!self) return nil;
Expand All @@ -28,7 +27,11 @@ - (instancetype)init
des.componentFlagsMask = 0;
des.componentManufacturer = kAudioUnitManufacturer_Apple;
des.componentType = kAudioUnitType_Output;
des.componentSubType = kAudioUnitSubType_VoiceProcessingIO; //kAudioUnitSubType_RemoteIO;
if (isEcho) {
des.componentSubType = kAudioUnitSubType_VoiceProcessingIO; //kAudioUnitSubType_RemoteIO;
}else {
des.componentSubType = kAudioUnitSubType_RemoteIO;
}

AudioComponent audioComponent;
audioComponent = AudioComponentFindNext(NULL, &des);
Expand All @@ -41,10 +44,10 @@ - (instancetype)init
outStreamDes.mFormatID = kAudioFormatLinearPCM;
outStreamDes.mFormatFlags = kAudioFormatFlagIsSignedInteger;
outStreamDes.mFramesPerPacket = 1;
outStreamDes.mChannelsPerFrame = 1;
outStreamDes.mChannelsPerFrame = channel;
outStreamDes.mBitsPerChannel = 16;
outStreamDes.mBytesPerFrame = 2;
outStreamDes.mBytesPerPacket = 2;
outStreamDes.mBytesPerFrame = 2 * channel;
outStreamDes.mBytesPerPacket = 2 * channel;
outStreamDes.mReserved = 0;
_pcmStreamDescription = outStreamDes;

Expand Down Expand Up @@ -76,11 +79,12 @@ - (instancetype)init

#define kTVURecoderPCMMaxBuffSize 2048
static int pcm_buffer_size = 0;
static uint8_t pcm_buffer[kTVURecoderPCMMaxBuffSize*2];
static uint8_t pcm_buffer[kTVURecoderPCMMaxBuffSize*4];

static OSStatus record_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrame, AudioBufferList *__nullable ioData)
{
TIoTPCMXEchoRecord *r = (__bridge TIoTPCMXEchoRecord *)(inRefCon);
int channel = r->_pcmStreamDescription.mChannelsPerFrame;

AudioBufferList list;
list.mNumberBuffers = 1;
Expand All @@ -107,13 +111,13 @@ static OSStatus record_callback(void *inRefCon, AudioUnitRenderActionFlags *ioAc
memcpy(pcm_buffer+pcm_buffer_size, bufferData, bufferSize);
pcm_buffer_size = pcm_buffer_size + bufferSize;

if(pcm_buffer_size >= kTVURecoderPCMMaxBuffSize) {
if(pcm_buffer_size >= (kTVURecoderPCMMaxBuffSize*channel)) {
if (r->callback)
r->callback(pcm_buffer, pcm_buffer_size, r->user);

// 因为采样不可能每次都精准的采集到1024个样点,所以如果大于2048大小就先填满2048,剩下的跟着下一次采集一起送给转换器
memcpy(pcm_buffer, pcm_buffer + kTVURecoderPCMMaxBuffSize, pcm_buffer_size - kTVURecoderPCMMaxBuffSize);
pcm_buffer_size = pcm_buffer_size - kTVURecoderPCMMaxBuffSize;
memcpy(pcm_buffer, pcm_buffer + (kTVURecoderPCMMaxBuffSize*channel), pcm_buffer_size - (kTVURecoderPCMMaxBuffSize*channel));
pcm_buffer_size = pcm_buffer_size - (kTVURecoderPCMMaxBuffSize*channel);
}

return error;
Expand All @@ -125,15 +129,14 @@ OSStatus outputRender_cb(void *inRefCon, AudioUnitRenderActionFlags *ioActionFla

- (void)start_record
{
pcm_buffer_size = 0;
AudioOutputUnitStart(audioUnit);
}

- (void)stop_record
{
AudioOutputUnitStop(audioUnit);
std::unique_lock<std::mutex> lock(mutex);
decltype(queue) empty;
std::swap(empty, queue);
pcm_buffer_size = 0;
}

- (void)set_record_callback:(RecordCallback)c user:(nonnull void *)u
Expand All @@ -146,5 +149,7 @@ - (void)dealloc
{
callback = NULL;
user = NULL;
[self stop_record];
AudioComponentInstanceDispose(audioUnit);
}
@end
Loading

0 comments on commit de3c48c

Please sign in to comment.