android mediacode 解码aac

本文详细介绍了在Android平台上如何使用MediaCodec解码AAC音频,包括AAC文件解析、MediaCodec参数设置,特别是`csd-0`参数的设定。通过自定义AAC帧数据送入MediaCodec进行解码,并利用AudioTrack播放解码后的PCM数据。同时,代码示例展示了如何使用MediaPlayer简单播放AAC文件。尽管官方文档稀缺,但通过分析Android源码理解了MediaCodec的特定参数用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

主要流程:

mediacode解码aac:

mediacode参数 "csd-0",如何设定?


这里手动解析 aac文件,如果只是本地播放aac文件那么android已经有完善的方法:MediaExtractor + MediaCoddec 或者直接是MediaPlayer, 但有的时候我们有自己的aac帧数据,想利用Mediacode进行解码,里面就有些坑。
完整app源码:github openScreen/clientAndroid/AACPlayer at main · Canok7/openScreen · GitHub

当然,如果使用java mediaplyer播放,使用android现成的功能,简单只需几行代码:
                   MediaPlayer player = new MediaPlayer();
                    try {
                        player.setDataSource("/storage/emulated/0/test.aac");
                        player.prepare();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    player.start();

主要流程:

 1.这里写了个aac文件的解析类,解析aac-adts文件,从中读取 音频信息如:通道,采样率,编码等级等信息。2.然后从aac文件中逐步取出aac raw (去掉adts头的数据),送到mediacode解码(ndk),3.再将解码的pcm数据调用java的audioTrack(也可以采用opensl 直接在native层渲染,只是ndk还没有开放提供audioTrack的接口,所以这里使用native反过来调用java的audioTrack接口。vlc也是如此

解析aac源文件:
有很多的blog介绍其组成,这里不赘述,源码中有完整的解析流程:

    int64_t  iheader=MAKE64_LEFT(headers[0],headers[1],headers[2],headers[3],
            headers[4],headers[5],headers[6],0);
    //ALOGD("[%s%d]%#lx",__FUNCTION__ ,__LINE__,iheader);
    int id = GET64BIT_LEFT(iheader,12,1);
    int layer = GET64BIT_LEFT(iheader,13,2);
    int protection_absent = GET64BIT_LEFT(iheader,15,1);
    int profile = GET64BIT_LEFT(iheader,16,2);
    int sampling_frequency_index = GET64BIT_LEFT(iheader,18,4);
    int private_bt = GET64BIT_LEFT(iheader,22,1);
    int channel_configuration = GET64BIT_LEFT(iheader,23,3);
    int original_copy = GET64BIT_LEFT(iheader,26,1);
    int home = GET64BIT_LEFT(iheader,27,1);

    //adts_variable_header
    int copyright_identification_bit = GET64BIT_LEFT(iheader,28,1);
    int copyright_identification_start=GET64BIT_LEFT(iheader,29,1);
    int aac_frame_length =GET64BIT_LEFT(iheader,30,13);
    int adts_buffer_fullness=GET64BIT_LEFT(iheader,33,11);
    int number_of_raw_data_blocks_in_frame=GET64BIT_LEFT(iheader,44,2);

一直想找个官方的标准文档看看,就是没找着,大部分文章都是雷同一句话:AAC音频格式在MPEG-2(ISO-13318-7 2003)中有定义,可是没人提及这个文档哪里有, 这个标准据说是收费的,而且很贵,MPEG官网也没找着。
抄一个网络上常见的图记录下:

mediacode解码aac:

mediacode参数 "csd-0",如何设定?

 其中有一个参数,"csd-0", 很难找到这个参数的官方完整说明,因为这个参数和AAC格式本身无关,在ffmpeg软解中也没有找到该参数,只是MediaCode(也有可能是omx的)自己使用的一个特殊参数,全称:Codec specific data,  可以在android源码中找到其相关信息,android 源码中:
frameworks/av/media/libstagefight/MetaDataUtils.cpp ::
里面函数:
MakeAVCCodecSpecificData()
MakeAACCodecSpecificData()

bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index,
        unsigned channel_configuration) {

    if(sampling_freq_index > 11u) {
        return false;
    }

    uint8_t csd[2];
    csd[0] = ((profile + 1) << 3) | (sampling_freq_index >> 1);
    csd[1] = ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);

    static const int32_t kSamplingFreq[] = {
        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
        16000, 12000, 11025, 8000
    };
    int32_t sampleRate = kSamplingFreq[sampling_freq_index];

    AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd, sizeof(csd));
    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channel_configuration);

    return true;
}

所以这个参数只是 Mediacode 自定的,和aac文件自身格式无关,没什么好研究的,既然要用Mediacode,就遵循它的设定,直接套用上面函数即可(可以看到这个数据也只是包含了profie, sampleFrequency, channel 三个信息,而这三个参数明明有单独的设置接口,还要重复这么一个信息,真是对它无语)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值