音频相当于SPS和PPS流合并时,附件B MPEG-TS的? 什么是“DecoderInfo”?

2019-10-23 02:24发布

我使用Bento4库多路复用器的附件B TS(MPEG-2传输流)与我的H264视频和正在从VideoToolbox和AVFoundation分别生成AAC音频流文件,作为用于HLS(HTTP实时流)的源数据流。 这个问题不一定Bento4特异性:我想了解的基本概念,这样我可以完成任务,最好用的苹果库。

到目前为止,我已经找到了如何创建一个AP4_AvcSampleDescription通过获取各种数据从我的CMVideoFormatDescriptionRef使用索引0和1分别产生SPS和PPS,最重要的CMVideoFormatDescriptionGetH264ParameterSetAtIndex ,我可以只是坚持为字节的缓冲区进入Bento4。 太好了,这就是我需要的,这样我可以问Bento4于MUX视频转换成TS文件头信息!

现在,我想给MUX音频到同一个文件。 我用我的CMAudioFormatDescriptionRef以获得所需的信息来构建我AP4_MpegAudioSampleDescription ,这Bento4使用进行必要的QT原子和头。 然而,如果一个字段是“解码信息”字节的缓冲区,没有解释它是什么,或代码来生成一个与数据。 我本来希望能有一个CMAudioFormatDescriptionGetDecoderInfo或东西,但我找不到这样的事情。 是否有任何苹果库这样的功能? 或者是有,我还没有就如何产生这个数据找到了一个很好的规范吗?

或可替换地,我是走在错误的道路? 有没有从Mac / iOS的代码库混流TS文件更简单的方法?

Answer 1:

木星音频为MPEG-TS是非常容易的,像视频流确实不需要复杂的头! 它仅需要每个样品缓冲之前7字节的ADTS头标,则写它作为一个PES前。

Bento4仅使用“DecoderInfo”缓冲器以便将其解析为一个AP4_Mp4AudioDecoderConfig实例,以便它可以提取所需的ADTS头标中的信息。 取而代之的是在获取这个数据,因此回旋,我做的复制粘贴AP4_Mpeg2TsAudioSampleStream::WriteSample一个写入CMSampleBufferRef 。 它可以很容易地推广到其它音频框架,但我只是贴吧的,是在这里以供参考:

// These two functions are copy-pasted from Ap4Mpeg2Ts.cpp
static unsigned int GetSamplingFrequencyIndex(unsigned int sampling_frequency) { ... }
static void
MakeAdtsHeader(unsigned char *bits,
               size_t  frame_size,
               unsigned int  sampling_frequency_index,
               unsigned int  channel_configuration) { ... }

static const size_t kAdtsHeaderLength = 7;

- (void)appendAudioSampleBuffer2:(CMSampleBufferRef)sampleBuffer
{
    // Get the actual audio data from the block buffer.
    CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
    size_t blockBufferLength = CMBlockBufferGetDataLength(blockBuffer);

    // Get the audio meta-data from its AudioFormatDescRef
    CMAudioFormatDescriptionRef audioFormat = CMSampleBufferGetFormatDescription(sampleBuffer);
    const AudioStreamBasicDescription *asbd = CMAudioFormatDescriptionGetStreamBasicDescription(audioFormat);

    // These are the values we will need to build our ADTS header
    unsigned int sample_rate = asbd->mSampleRate;
    unsigned int channel_count = asbd->mChannelsPerFrame;
    unsigned int sampling_frequency_index = GetSamplingFrequencyIndex(sample_rate);
    unsigned int channel_configuration = channel_count;

    // Create a byte buffer with first the header, and then the sample data.
    NSMutableData *buffer = [NSMutableData dataWithLength:kAdtsHeaderLength + blockBufferLength];
    MakeAdtsHeader((unsigned char*)[buffer mutableBytes], blockBufferLength, sampling_frequency_index, channel_configuration);
    CMBlockBufferCopyDataBytes(blockBuffer, 0, blockBufferLength, ((char*)[buffer mutableBytes])+kAdtsHeaderLength);

    // Calculate a timestamp int64 that Bento4 can use, by converting our CMTime into an Int64 in the timescale of the audio stream.
    CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    AP4_UI64 ts = CMTimeConvertScale(presentationTime, _audioStream->m_TimeScale, kCMTimeRoundingMethod_Default).value;

    _audioStream->WritePES(
        (const unsigned char*)[buffer bytes],
        (unsigned int)[buffer length],
        ts,
        false, // don't need a decode timestamp for audio
        ts,
        true, // do write a presentation timestamp so we can sync a/v
        *_output
    );
}


Answer 2:

通过Bento4创建AP4_MpegAudioSampleDescription实例所需的“解码器信息”字节缓冲器是编解码器的初始化数据,这是特定的编解码器。 对于AAC-LC音频,它通常是2个字节数据(HE-AAC,你会得到一些更多的字节),其中的细节在AAC规范中规定。 例如,44.1kHz的,立体声,AAC-LC流将具有[0x12,0x10]作为初始化数据。 在大多数苹果的API,这种类型的编解码器的初始化数据是通过他们所谓的“魔法饼干”传送。 这是可能的功能CMAudioFormatDescriptionGetMagicCookie将返回您这里需要。



文章来源: Audio equivalent of SPS and PPS when muxing Annex B MPEG-TS? What is “DecoderInfo”?