基 于 Linux 的 internet 收 音 机 的 实 现 王 辉
版 权 } 华 清 远 见 嵌 入 式 培 训 中 心 版 权 所 有 ; } 未 经 华 清 远 见 明 确 许 可, 不 能 为 任 何 目 的 以 任 何 形 式 复 制 或 传 播 此 文 档 的 任 何 部 分 ; } 本 文 档 包 含 的 信 息 如 有 更 改, 恕 不 另 行 通 知 ; } 保 留 所 有 权 利 2
今 日 内 容 大 纲 } Internet Radio 功 能 简 介 } Linux 应 用 层 Mplayer 简 介 } Mplayer 的 输 入 -Keypad driver } Mplayer 的 声 音 输 出 -sound driver
Internet Radio 功 能 简 介 } 也 叫 IP Radio, 可 以 实 时 收 听 网 络 电 台 } rtsp://211.167.134.41/broadcast/live3 } mms://211.89.225.101/live3 } http://www.stv.sh.cn/1422.asx
Internet Radio 功 能 要 点 } 网 络 功 能 } Ethernet WiFi 网 络 层 } TCP/IP } rtsp mms http } upnp } DHCP client } 多 媒 体 功 能 } 立 体 声 声 音 输 出 } Line Out Line In } MP3 WMA RA(Real Audio) 解 码 功 能 } 时 钟 功 能 } 实 时 时 钟 RTC } 网 络 时 钟 同 步 NTP } 存 储 功 能 } SD 卡 播 放 } U 盘 播 放 } SD 卡 升 级 } 用 户 交 互 界 面 } 按 键 } 红 外 遥 控 器 } GUI 界 面
Internet Radio 硬 件 框 图
Internent Radio 软 件 结 构
Mplayer 概 述 } 网 站 http://www.mplayerhq.hu/ } 其 遵 守 GPLv2 许 可 证 } 支 持 本 地 播 放 网 络 数 据 流 获 取 } HTTP/FTP } RTP/RTSP } MMS/MMST } 支 持 常 见 视 频 音 频 格 式 的 编 解 码 } MPEG layer 1, 2, and 3 (MP3) audio } WMA (DivX Audio) v1, v2 } WMA 9 (WMAv3)(using x86 DLLs) } RealAudio: COOK, SIPRO, ATRAC3 (using Real libraries) } RealAudio: DNET and older codecs } 支 持 多 种 音 频 设 备 输 入 设 备 } OSS (Open Sound System) - factory standard under UNIX } ALSA (Advanced Linux Sound Architecture) 0.5/0.9/1.0 for Linux } Keyboard mouse joystick
Mplayer 输 入 及 控 制 } Mplayer 中 输 入 机 制 读 键 值 - 解 析 绑 定 命 令 - 调 用 命 令 code = ((mp_key_func_t)key_fds[i].read_func)(key_fds[i].fd); if (code >= 0) { mp_cmd_t *ret = interpret_key(code, paused); if (ret) } return ret; } 向 Mplayer 注 册 输 入 设 别 : int fd = mp_input_keypad_init(keypadname); mp_input_add_key_fd(fd,1,mp_input_keypad_read,(mp_close _func_t)close); Mplayer cmd process Interpret key and call cmd proc Mplayer input layer($(src)/input) Bind key to cmd 设 备 节 点 /dev/input/event0 } 键 值 与 命 令 的 绑 定 : { { KEY_RIGHT, 0 }, "seek 10" }, { { KEY_LEFT, 0 }, "seek -10" }, { { KEY_UP, 0 }, "seek 60" }, Open/select/ read/close { { KEY_DOWN, 0 }, "seek -60" }, Linux kernel keypad driver
Linux 内 核 input 子 系 统
Linux 内 核 keypad 驱 动 } 键 盘 注 册 : struct input_dev*input_allocate_device(void); int must_check input_register_device(struct input_dev*); struct input_dev{ }; const char *name; unsigned long evbit[bits_to_longs(ev_cnt)]; unsigned long keybit[bits_to_longs(key_cnt)]; unsigned int keycodemax; unsigned int keycodesize; void *keycode; } 获 取 按 键 信 息 : 打 开 press down 中 断 ; 按 键, 进 入 中 断, 判 断 某 键 按 下 stat=firstpress; 防 止 毛 刺, 关 闭 中 断 打 开 kernel timer; 在 timer 中 根 据 按 键 状 态 及 上 一 次 stat 状 态, 如 stat 为 firstpress 并 且 新 状 态 为 按 下, 则 确 认 某 键 按 下, 向 input core 传 递 键 值 void input_report_key(struct input_dev*dev, unsigned int code, int value); 或 input_event(dev, EV_KEY, code,!!value);
Mplayer 音 频 输 出 } Mplayer 中 音 频 输 出 机 制 获 取 音 频 输 出 设 备 - 调 用 设 备 接 口 - 控 制 音 频 设 备 写 出 声 音 数 据 mpctx->audio_out=init_best_audio_out(audio_driver_list, flag ao_data.samplerate, ao_data.channels, ao_data.format,0) } 调 用 音 频 设 备 接 口 : 0, // plugin mpctx->audio_out->play(sh_audio->a_out_buffer, playsize, playflags); } 实 现 mplayer 音 频 设 备 typedefstruct ao_functions_s{ ao_info_t *info; int (*control)(intcmd,void *arg); int(*init)(intrate,intchannels,intformat,intflags); void (*uninit)(intimmed); void (*reset)(void); int (*get_space)(void); int (*play)(void* data,intlen,int flags); float (*get_delay)(void); void (*pause)(void); void (*resume)(void); } ao_functions_t; CALL ao_functions Mplayer ao layer($(src)/libao2) ALSA API Mplayer audio process ALSA-lib ALSA 节 点 /dev/snd/pcmc0d0 /dev/snd/controlc0d0 Open/select/ read/close Linux kernel sound driver OSS 节 点 /dev/dsp /dev/mixer typedef struct ao_functions_s { ao_info_t *info; int (*control)(int cmd,void *arg); int (*init)(int rate,int channels,int format,int flags); void (*uninit)(int immed); void (*reset)(void); int (*get_space)(void); int (*play)(void* data,int len,int flags); float (*get_delay)(void); void (*pause)(void); void (*resume)(void); } ao_functions_t;
Linux 内 核 sound 驱 动 (ALSA) } CARD: struct snd_card *snd_card_new(int idx, const char *id, struct module *module, int extra_size); plb0 cap0... int snd_card_register(struct snd_card *card); } PCM device: int snd_pcm_new(struct snd_card *card, const char *id, int device, int playback_count, int capture_count, struct snd_pcm**rpcm); pcm0... control void snd_pcm_set_ops(struct snd_pcm* pcm, int direction, struct snd_pcm_ops *ops); } Control: Device0 Device1... struct snd_kcontrol*snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data); int snd_ctl_add(struct snd_card * card, struct snd_kcontrol* kcontrol); Sound card 0...
Q&A 14
15