Android系统源码分析/多媒体框架/音频子系统/常用结构体分析-audio.h

audio_stream_type_t

定义音频流类型,主要是手机系统各类典型的音频流做出属性上的区分,举个例子:电话和媒体2种类型的音频不管从输出的设备(耳机、功放、还是蓝牙)都是存在明显的不同。把这些明显不同的音频区分并加以定义,可以说对音频策略管理(AudioPolicyManager,在我后续的技术文章会具体jiang)和代码开发实现都存在很大必要性

/* Audio stream types */
typedef enum {
    /* These values must kept in sync with
     * frameworks/base/media/java/android/media/AudioSystem.java
     */
    AUDIO_STREAM_DEFAULT          = -1,
    AUDIO_STREAM_MIN              = 0,
    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,
    AUDIO_STREAM_ALARM            = 4,
    AUDIO_STREAM_NOTIFICATION     = 5,
    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user
                                        * and must be routed to speaker
                                        */
    AUDIO_STREAM_DTMF             = 8,
    AUDIO_STREAM_TTS              = 9,

    AUDIO_STREAM_CNT,
    AUDIO_STREAM_MAX              = AUDIO_STREAM_CNT - 1,
} audio_stream_type_t;
Stream TypeDescription
AUDIO_STREAM_VOICE_CALL电话语音
AUDIO_STREAM_SYSTEM系统声音
AUDIO_STREAM_RING铃声声音,如来电铃声、闹钟铃声等
AUDIO_STREAM_MUSIC音乐声音
AUDIO_STREAM_ALARM警告音
AUDIO_STREAM_NOTIFICATION通知音
AUDIO_STREAM_DTMFDTMF 音(拨号盘按键音)

 audio_content_type_t

内容类型定义了声音是什么,并指明内容的常规类别,如电影、语音或提示音/铃声。音频框架使用内容类型信息来选择性地配置音频处理后块。尽管提供内容类型是可选的,但只要内容类型已知,您就应该包含类型信息,例如针对电影流式传输服务使用 CONTENT_TYPE_MOVIE,或针对音乐播放应用使用 CONTENT_TYPE_MUSIC

typedef enum {
    AUDIO_CONTENT_TYPE_UNKNOWN      = 0,
    AUDIO_CONTENT_TYPE_SPEECH       = 1,
    AUDIO_CONTENT_TYPE_MUSIC        = 2,
    AUDIO_CONTENT_TYPE_MOVIE        = 3,
    AUDIO_CONTENT_TYPE_SONIFICATION = 4,

    AUDIO_CONTENT_TYPE_CNT,
    AUDIO_CONTENT_TYPE_MAX          = AUDIO_CONTENT_TYPE_CNT - 1,
} audio_content_type_t;

audio_source_t

这个枚举定义了各种音频输入设备,比如AUDIO_SOURCE_MIC麦克风 AUDIO_SOURCE_VOICE_CALL电话通话录音 AUDIO_SOURCE_CAMCORDER 摄像头音频录制 AUDIO_SOURCE_VOICE_COMMUNICATION 摄像头旁边的麦克风 AUDIO_SOURCE_VOICE_RECOGNITION语音识别  AUDIO_SOURCE_VOICE_UPLINK 电话通话上行声音 AUDIO_SOURCE_VOICE_DOWNLINK电话通话下行声音  AUDIO_SOURCE_REMOTE_SUBMIX 类似于同屏器设备,比如手机把手机的的画面投在电视机上,那么音频数据一定是通过WIFI传递给同屏器。(我司最近给移动开发的同屏器产品就是通过这个类型的音频输入设备实现音频 从手机到电视的传输)

typedef enum {
    AUDIO_SOURCE_DEFAULT             = 0,
    AUDIO_SOURCE_MIC                 = 1,
    AUDIO_SOURCE_VOICE_UPLINK        = 2,
    AUDIO_SOURCE_VOICE_DOWNLINK      = 3,
    AUDIO_SOURCE_VOICE_CALL          = 4,
    AUDIO_SOURCE_CAMCORDER           = 5,
    AUDIO_SOURCE_VOICE_RECOGNITION   = 6,
    AUDIO_SOURCE_VOICE_COMMUNICATION = 7,
    AUDIO_SOURCE_REMOTE_SUBMIX       = 8, /* Source for the mix to be presented remotely.      */
                                          /* An example of remote presentation is Wifi Display */
                                          /*  where a dongle attached to a TV can be used to   */
                                          /*  play the mix captured by this audio source.      */
    AUDIO_SOURCE_CNT,
    AUDIO_SOURCE_MAX                 = AUDIO_SOURCE_CNT - 1,
    AUDIO_SOURCE_HOTWORD             = 1999, /* A low-priority, preemptible audio source for
                                                for background software hotword detection.
                                                Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION.
                                                Used only internally to the framework. Not exposed
                                                at the audio HAL. */
} audio_source_t;

audio_format_pcm_sub_fmt_t audio_format_mp3_sub_fmt_t audio_format_amr_sub_fmt_t audio_format_aac_sub_fmt_t

这几个枚举类型定义了pcm mp3 amr aac音频格式和各个格式 子类型。


audio_format_t

typedef enum {
    AUDIO_FORMAT_INVALID             = 0xFFFFFFFFUL,
    AUDIO_FORMAT_DEFAULT             = 0,
    AUDIO_FORMAT_PCM                 = 0x00000000UL, /* DO NOT CHANGE */
    AUDIO_FORMAT_MP3                 = 0x01000000UL,
    AUDIO_FORMAT_AMR_NB              = 0x02000000UL,
    AUDIO_FORMAT_AMR_WB              = 0x03000000UL,
    AUDIO_FORMAT_AAC                 = 0x04000000UL,
    AUDIO_FORMAT_HE_AAC_V1           = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/
    AUDIO_FORMAT_HE_AAC_V2           = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/
    AUDIO_FORMAT_VORBIS              = 0x07000000UL,
    AUDIO_FORMAT_OPUS                = 0x08000000UL,
    AUDIO_FORMAT_AC3                 = 0x09000000UL,
    AUDIO_FORMAT_E_AC3               = 0x0A000000UL,
    AUDIO_FORMAT_MAIN_MASK           = 0xFF000000UL,
    AUDIO_FORMAT_SUB_MASK            = 0x00FFFFFFUL,

    /* Aliases */
    /* note != AudioFormat.ENCODING_PCM_16BIT */
    AUDIO_FORMAT_PCM_16_BIT          = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_16_BIT),
    /* note != AudioFormat.ENCODING_PCM_8BIT */
    AUDIO_FORMAT_PCM_8_BIT           = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_8_BIT),
    AUDIO_FORMAT_PCM_32_BIT          = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_32_BIT),
    AUDIO_FORMAT_PCM_8_24_BIT        = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_8_24_BIT),
    AUDIO_FORMAT_PCM_FLOAT           = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_FLOAT),
    AUDIO_FORMAT_PCM_24_BIT_PACKED   = (AUDIO_FORMAT_PCM |
                                        AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED),
    AUDIO_FORMAT_AAC_MAIN            = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_MAIN),
    AUDIO_FORMAT_AAC_LC              = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_LC),
    AUDIO_FORMAT_AAC_SSR             = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_SSR),
    AUDIO_FORMAT_AAC_LTP             = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_LTP),
    AUDIO_FORMAT_AAC_HE_V1           = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_HE_V1),
    AUDIO_FORMAT_AAC_SCALABLE        = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_SCALABLE),
    AUDIO_FORMAT_AAC_ERLC            = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_ERLC),
    AUDIO_FORMAT_AAC_LD              = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_LD),
    AUDIO_FORMAT_AAC_HE_V2           = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_HE_V2),
    AUDIO_FORMAT_AAC_ELD             = (AUDIO_FORMAT_AAC |
                                        AUDIO_FORMAT_AAC_SUB_ELD),
} audio_format_t;

定义了安卓手机系统用到的音频格式和子格式的定义。具体每个格式的含义不在这里具体展开,那是一个很大的课题。

关于PCM格式推荐一篇文章:https://blog.csdn.net/lifei092/article/details/80990813

关于MP3格式推荐一篇文章:https://www.cnblogs.com/ranson7zop/p/7655474.html

关于AAC格式推荐一篇文章:https://www.jianshu.com/p/30856dccd9cb

关于AC3格式推荐一篇文章:https://blog.csdn.net/u013291802/article/details/53283944


audio_output_flags_t

typedef enum {
    AUDIO_OUTPUT_FLAG_NONE = 0x0,       // no attributes
    AUDIO_OUTPUT_FLAG_DIRECT = 0x1,     // this output directly connects a track
                                        // to one output stream: no software mixer
    AUDIO_OUTPUT_FLAG_PRIMARY = 0x2,    // this output is the primary output of
                                        // the device. It is unique and must be
                                        // present. It is opened by default and
                                        // receives routing, audio mode and volume
                                        // controls related to voice calls.
    AUDIO_OUTPUT_FLAG_FAST = 0x4,       // output supports "fast tracks",
                                        // defined elsewhere
    AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers
    AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed
                                                // streams to hardware codec
    AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, // use non-blocking write
    AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 0x40 // output uses a hardware A/V synchronization source
} audio_output_flags_t;

 

AUDIO_OUTPUT_FLAGDescription
AUDIO_OUTPUT_FLAG_DIRECT表示音频流直接输出到音频设备,不需要软件混音,一般用于 HDMI 设备声音输出
AUDIO_OUTPUT_FLAG_PRIMARY表示音频流需要输出到主输出设备,一般用于铃声类声音
AUDIO_OUTPUT_FLAG_FAST表示音频流需要快速输出到音频设备,一般用于按键音、游戏背景音等对时延要求高的场景
AUDIO_OUTPUT_FLAG_DEEP_BUFFER表示音频流输出可以接受较大的时延,一般用于音乐、视频播放等对时延要求不高的场景
AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD表示音频流没有经过软件解码,需要输出到硬件解码器,由硬件解码器进行解码

 audio_input_flags_t

针对输入音频源

AUDIO_INPUT_FLAG_NONE表示输入音频是常规音频输入,即咱们常见的摄像头或者麦克风采集的数据;AUDIO_INPUT_FLAG_FAST表述输入音频是延时要求高的音频输入源,如按键音游戏背景;AUDIO_INPUT_FLAG_HW_HOTWORD主要用于语音识别。可能要做的事情是:处理代码需要对数据识别并提取说话内容

typedef enum {
    AUDIO_INPUT_FLAG_NONE       = 0x0,  // no attributes
    AUDIO_INPUT_FLAG_FAST       = 0x1,  // prefer an input that supports "fast tracks"
    AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2,  // prefer an input that captures from hw hotword source
} audio_input_flags_t;

audio_offload_info_t

该结构体描述offload流的具体信息,所谓offload就是需要硬件解码的音频流。采样率、左右立体声声道、pcm子格式、流类型、比特率以及流是static模式(一次写入播放)还是stream模式(多次写入播放)

 

 

typedef struct {
    uint16_t version;                   // version of the info structure
    uint16_t size;                      // total size of the structure including version and size
    uint32_t sample_rate;               // sample rate in Hz
    audio_channel_mask_t channel_mask;  // channel mask
    audio_format_t format;              // audio format
    audio_stream_type_t stream_type;    // stream type
    uint32_t bit_rate;                  // bit rate in bits per second
    int64_t duration_us;                // duration in microseconds, -1 if unknown
    bool has_video;                     // true if stream is tied to a video stream
    bool is_streaming;                  // true if streaming, false if local playback
} audio_offload_info_t;

 audio_module_handle_t

定义为int类型,表示一个硬件模块,所谓硬件模块是usb downmix a2dp蓝牙 以及primary 四种之一。配置信息在audio_policy.conf描述

具体可以见另外一个文章:https://www.cnblogs.com/wulizhi/p/8179067.html


audio_port_role_t

描述一个port的规则:对于输入就是source ,对于输出就是sink

typedef enum {
    AUDIO_PORT_ROLE_NONE,
    AUDIO_PORT_ROLE_SOURCE,
    AUDIO_PORT_ROLE_SINK,
} audio_port_role_t;

audio_port_type_t

描述输出端口的三个类型:device就是直接向具体的设备进行输出(AUDIO_DEVICE_OUT_SPEAKER)、MIX类型就是向mixthread进行输出(需要做一些重编码、混音、音效处理、音量策略处理动作)、SESSION就是向另外一个audiotrack进行数据输出(举例:这样可以添加自定义音频数据处理挂钩)

typedef enum {
    AUDIO_PORT_TYPE_NONE,
    AUDIO_PORT_TYPE_DEVICE,
    AUDIO_PORT_TYPE_MIX,
    AUDIO_PORT_TYPE_SESSION,
} audio_port_type_t;

audio_port_config_device_ext

描述一个port输出设备:包含改设备对应的hw_module(所谓hw_module上面已经解释)、设备类型(AUDIO_DEVICE_OUT_SPEAKER)、设备地址

struct audio_port_config_device_ext {
    audio_module_handle_t hw_module;                /* module the device is attached to */
    audio_devices_t       type;                     /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */
    char                  address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */
};

audio_port_config_mix_ext

描述port如果输出对象是一个MIX Thread,那么该对象描述该输出配置信息:包含改设备对应的hw_module(所谓hw_module上面已经解释)、输出的IO对象(该io对象对应AudioFilger里面的一个PlaybackThread)、流类型和输入源类型

struct audio_port_config_mix_ext {
    audio_module_handle_t hw_module;    /* module the stream is attached to */
    audio_io_handle_t handle;           /* I/O handle of the input/output stream */
    union {
        //TODO: change use case for output streams: use strategy and mixer attributes
        audio_stream_type_t stream;
        audio_source_t      source;
    } usecase;
};

audio_port_config 

我们需要解释什么是audioport,在解释之前我们先说下另外一个概念:audio patch。那么什么是audio patch?

我们举个例子:近期做了一个车载音频播放设备,该设备声音源来自汽车车载音响,然后通过usb设备传到手机,再通过手机的扬声器播放出来;为了达到这个目的,音频源数据从source 设备(车载音响usb接口)到目标设备(loud speaker)直接建立一个patch就可以了。 数据可以快速的输出,避免经过用户层中转。 提高了音频的实时性

在一个audio patch中,我们输入设备可以不只是一个(除了车载音响,还可以是手机自带的麦克风),输出设备也不只是一个(除了loud speaker,还可以是录制文件。这个场景怎么理解?  车载录音证据保留目的 )

那么既然一个patch内有多个输如输出,这里面一个输入就叫做一个端口,即audio_port。所以audio_port_config 就是描述port配置属性的

 

id是该config唯一id;

role指明该port是输入AUDIO_PORT_ROLE_SOURCE还是输出AUDIO_PORT_ROLE_SINK;

tye指明该porta是device mix 还是一个session;

config_mask是一个AUDIO_PORT_CONFIG_ALL  AUDIO_PORT_CONFIG_GAIN AUDIO_PORT_CONFIG_FORMAT AUDIO_PORT_CONFIG_CHANNEL_MASK 四个值中的一个,这样可以指明下面字段channel format gain三个字段哪一个是有效的。下面是config_mask的定义

#define AUDIO_PORT_CONFIG_SAMPLE_RATE  0x1
#define AUDIO_PORT_CONFIG_CHANNEL_MASK 0x2
#define AUDIO_PORT_CONFIG_FORMAT       0x4
#define AUDIO_PORT_CONFIG_GAIN         0x8
#define AUDIO_PORT_CONFIG_ALL (AUDIO_PORT_CONFIG_SAMPLE_RATE | \
                               AUDIO_PORT_CONFIG_CHANNEL_MASK | \
                               AUDIO_PORT_CONFIG_FORMAT | \
                               AUDIO_PORT_CONFIG_GAIN)

 

sample_rate是该port的采样率

channel_mask:指明该port是左声道 右声道还是 立体声

format 指出音频数据的格式

gain 指出该port的增益属性

ext则是一个联合体,根据type是device mix session,该字段相应的是audio_port_config_device_ext audio_port_config_mix_ext audio_port_config_session_ext


/* audio port configuration structure used to specify a particular configuration of
 * an audio port */
struct audio_port_config {
    audio_port_handle_t      id;           /* port unique ID */
    audio_port_role_t        role;         /* sink or source */
    audio_port_type_t        type;         /* device, mix ... */
    unsigned int             config_mask;  /* e.g AUDIO_PORT_CONFIG_ALL */
    unsigned int             sample_rate;  /* sampling rate in Hz */
    audio_channel_mask_t     channel_mask; /* channel mask if applicable */
    audio_format_t           format;       /* format if applicable */
    struct audio_gain_config gain;         /* gain to apply if applicable */
    union {
        struct audio_port_config_device_ext  device;  /* device specific info */
        struct audio_port_config_mix_ext     mix;     /* mix specific info */
        struct audio_port_config_session_ext session; /* session specific info */
    } ext;
};

android系统音频子系统的其他代码分析,会逐步更新到我的博客。敬请关注

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值