ReplayKit2 采集音视频回调格式分析

 

一、iOS中的音视频都是采用一个叫做CMSampleBuffer的格式封装的

  比如回调的App音频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Printing description of sampleBuffer:
CMSampleBuffer 0x143d06560 retainCount: 1 allocator: 0x25bae95e0
    invalid = NO
    dataReady = YES
    makeDataReadyCallback = 0x0
    makeDataReadyRefcon = 0x0
    formatDescription = <CMAudioFormatDescription 0x281940990 [0x25bae95e0]> {
    mediaType:'soun'
    mediaSubType:'lpcm'
    mediaSpecific: {
        ASBD: {
            mSampleRate: 44100.000000
            mFormatID: 'lpcm'
            mFormatFlags: 0xe
            mBytesPerPacket: 2
            mFramesPerPacket: 1
            mBytesPerFrame: 2
            mChannelsPerFrame: 1
            mBitsPerChannel: 16     }
        cookie: {(null)}
        ACL: {(null)}
        FormatList Array: {(null)}
    }
    extensions: {(null)}
}
    sbufToTrackReadiness = 0x0
    numSamples = 22528
    sampleTimingArray[1] = {
        {PTS = {619877934457375/1000000000 = 619877.934}, DTS = {INVALID}, duration = {1/44100 = 0.000}},
    }
    dataBuffer = 0x281940360

  

  比如回调的micphone音频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Printing description of sampleBuffer:
CMSampleBuffer 0x149e053b0 retainCount: 1 allocator: 0x25bae95e0
    invalid = NO
    dataReady = YES
    makeDataReadyCallback = 0x0
    makeDataReadyRefcon = 0x0
    formatDescription = <CMAudioFormatDescription 0x281b47b10 [0x25bae95e0]> {
    mediaType:'soun'
    mediaSubType:'lpcm'
    mediaSpecific: {
        ASBD: {
            mSampleRate: 44100.000000
            mFormatID: 'lpcm'
            mFormatFlags: 0xc
            mBytesPerPacket: 2
            mFramesPerPacket: 1
            mBytesPerFrame: 2
            mChannelsPerFrame: 1
            mBitsPerChannel: 16     }
        cookie: {(null)}
        ACL: {(null)}
        FormatList Array: {(null)}
    }
    extensions: {(null)}
}
    sbufToTrackReadiness = 0x0
    numSamples = 1024
    sampleTimingArray[1] = {
        {PTS = {27273930501/44100 = 618456.474, rounded}, DTS = {INVALID}, duration = {1/44100 = 0.000}},
    }
    dataBuffer = 0x281b47c30

 从这个结构中,可以得到这个音频数据的描述信息

1
2
3
4
5
6
7
8
9
10
// Get samples.
      CMBlockBufferRef audioBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
      size_t lengthAtOffset;
      size_t totalLength;
      char *samples;
      CMBlockBufferGetDataPointer(audioBuffer, 0, &lengthAtOffset, &totalLength, &samples);
 
      // Get format.
      CMAudioFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer);
      const AudioStreamBasicDescription *description = CMAudioFormatDescriptionGetStreamBasicDescription(format);

  输出为格式的描述信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Printing description of format:
<CMAudioFormatDescription 0x28282f7b0 [0x25bae95e0]> {
    mediaType:'soun'
    mediaSubType:'lpcm'
    mediaSpecific: {
        ASBD: {
            mSampleRate: 44100.000000
            mFormatID: 'lpcm'
            mFormatFlags: 0xc
            mBytesPerPacket: 2
            mFramesPerPacket: 1
            mBytesPerFrame: 2
            mChannelsPerFrame: 1
            mBitsPerChannel: 16     }
        cookie: {(null)}
        ACL: {(null)}
        FormatList Array: {(null)}
    }
    extensions: {(null)}
}

  关于音频格式有几个关键信息:格式、采样率、采样精度、声道数

  关于音频数据除了上面的格式信息之外,还有 PTS 、 samples(帧数)描述信息

  比如上面的PCM数据中,采样率是44100hz、采样深度是16位、声道数是1,samples是1024帧,最后计算这段声音的长度信息是 (1/44100) * 1024 = 23ms , 这个声音的数据大小是 1024 * 2byte = 2014 Byte

 

  如果是录制声音的话,需要先设置需要录制的音频格式信息  

1
2
3
4
5
6
7
8
9
10
AudioStreamBasicDescription format;
memset(&format, 0, sizeof(format));
format.mSampleRate = 44100;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
format.mChannelsPerFrame = 1;
format.mBitsPerChannel = 16;
format.mBytesPerFrame = (format.mBitsPerChannel/8) * format.mChannelsPerFrame;
format.mFramesPerPacket = 1;
format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket;

  需要设置关键参数、采样率、采样精度、声道数、数据排列格式、 一个packet的帧数

 

附录:

  关于采样精度

  

 

关于采样率

  

 

 

 

posted @   兜兜有糖的博客  阅读(940)  评论(2编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
历史上的今天:
2014-11-05 IOS真机Profile时调用树中的对象只是显示地址,没有显示symbol name
点击右上角即可分享
微信分享提示