首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >音频等效的SPS和PPS时,突变附件B,MPEG-TS?什么是"DecoderInfo"?

音频等效的SPS和PPS时,突变附件B,MPEG-TS?什么是"DecoderInfo"?
EN

Stack Overflow用户
提问于 2015-05-13 00:04:02
回答 2查看 1.2K关注 0票数 1

我使用Bento4库将附件HLS (MPEG-2传输流)文件与h264视频和AAC音频流分别从VideoToolbox和AVFoundation生成,作为HLS (HTTP )流的源数据。这个问题不一定是特定于Bento4 4的:我试图理解基本的概念,以便我能够完成任务,最好是使用Apple。

到目前为止,我已经知道了如何通过从CMVideoFormatDescriptionRef中获取各种数据来创建CMVideoFormatDescriptionRef,最重要的是使用CMVideoFormatDescriptionGetH264ParameterSetAtIndex的索引0和1生成SPS和PPS,我可以将它们作为字节缓冲区保存到Bento4中。太好了,这就是我需要的所有头信息,这样我就可以让Bento4把视频变成ts文件了!

现在我试着把音频屏蔽到同一个文件中。我正在使用我的CMAudioFormatDescriptionRef来获取构造我的AP4_MpegAudioSampleDescription所需的信息,Bento4使用它来生成必要的QT原子和头。然而,如果字段是一个“解码器信息”字节缓冲区,没有解释它是什么,或者代码从数据生成一个。我本来希望有一个CMAudioFormatDescriptionGetDecoderInfo之类的,但我找不到这样的东西。苹果的图书馆里有这样的功能吗?或者,在如何生成这些数据方面,我还没有找到一个很好的规范吗?

或者,我走错路了吗?有更简单的方法从Mac/iOS代码库中屏蔽ts文件吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-15 23:24:45

Muxing音频进入MPEG-TS是令人惊讶的简单,并且不需要像视频流那样复杂的头!它只需要一个7字节的ADTS头在每个示例缓冲区之前,然后将它写成PES。

Bento4只使用"DecoderInfo“缓冲区将其解析为AP4_Mp4AudioDecoderConfig实例,以便提取ADTS头部所需的信息。我做了一个AP4_Mpeg2TsAudioSampleStream::WriteSample的复制粘贴,编写了一个CMSampleBufferRef,而不是在获取这些数据的过程中如此迂回。它可以很容易地推广到其他音频框架中,但我将其粘贴在这里,以供参考:

代码语言:javascript
复制
// 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
    );
}
票数 2
EN

Stack Overflow用户

发布于 2015-05-13 16:18:22

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30203441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档