Android MediaPlayer に関するメモ
Android で音楽や動画を再生するときに必要な MediaPlayer だけど、直に JNI に処理を吸い込まれていってデバッグしづらいので、 AOSP ネイティブ実装を追い掛けてみた。
TP Vision の資料 (以下の図) がわかりやすすぎて、あんま調べる意味がなかった感じもする。
Android builders summit - The Android media framework (PDF)
Application
- MediaPlayer (Java)
- https://android.googlesource.com/platform/frameworks/base.git/+/android-5.1.1_r18/media/java/android/media/MediaPlayer.java
- MediaPlayer (Java) は大したことはしてなくて、大部分を MediaPlayer (JNI) に投げている
JNI
- MediaPlayer (JNI)
- https://android.googlesource.com/platform/frameworks/base.git/+/android-5.1.1_r18/media/jni/android_media_MediaPlayer.cpp
- JNI で MediaPlayer (libmedia) のインスタンスを作ってやりとりをしている
libmedia
https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmedia
- MediaPlayer (libmedia)
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmedia/mediaplayer.cpp
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/include/media/mediaplayer.h
- IMediaPlayer や IMediaPlayerService を通じて Binder (IPC) でやりとりしている
getMediaPlayerService()の実装は IMediaDeathNotifier にある
- IMediaPlayer / IMediaPlayerService
- IMediaPlayer
- IMediaPlayerService
- IMediaDeathNotifier
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmedia/IMediaDeathNotifier.cpp
- ServiceManager から "media.player" サービスを取得している
MediaPlayerService
libmedia で ServiceManager 経由で呼び出された "media.player" サービスは libmediaplayerservice に実体がある。
libmediaservice (MediaPlayerService)
- MediaPlayerService
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmediaplayerservice/MediaPlayerService.cpp
MediaPlayerFactory#createPlayerを通じてタイプに応じたプレイヤー (MediaPlayerBase) を生成している
- MediaPlayerFactory
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmediaplayerservice/MediaPlayerFactory.cpp
- registerFactory で実装を追加している
- AOSP 版では StagefrightPlayer 、 NuPlayer 、 SonivoxPlayerFactory 、 TestPlayer の 4 種類を追加している
- MediaPlayerService を変更できる環境 (端末メーカなど) なら、ここに Player を追加することで独自のプレイヤー実装することが出来そう
- Widevine なら StagefrightPlayer 、 RTSP or HLS っぽかったら NuPlayer 、 MIDI は SonivoxPlayer 、それ以外はデフォルトプレイヤー
- Lollipop の場合は、開発者設定からデフォルトプレイヤーを AwesomePlayer (StagefrightPlayer) にするか NuPlayer にするか選べる
- StagefrightPlayer
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libmediaplayerservice/StagefrightPlayer.cpp
- AwesomePlayer (stagefright のプレイヤーの名前) のインスタンスを作って、そことやりとりしている
- Awesome って…
libstagefright (Stagefrihgt)
Stagefright の役割はだいたい以下のような感じ、パースとレンダリングをやって、デコード処理とかは OMX (OpenMAX) を通じてハードウェアにやらせている。
Integrating a Hardware Video Codec into Android Stagefright using OpenMAX IL (PDF)
- AwesomePlayer
- https://android.googlesource.com/platform/frameworks/av/+/android-5.1.1_r18/media/libstagefright/AwesomePlayer.cpp
- やっとメディアプレイヤーっぽい実装がされている
- 各種操作は AwesomeEvent というイベントのインスタンスを作って Queue に入れていく
AwesomePlayer#prepareAsync
prepareAsync_lonPrepareAsyncEventbeginPrepareAsync_l- http や https ならば MediaHTTP を使ってコンテンツを取得してくる
- dataSource を元に MediaExtractor::Create を呼び出す
- MediaExtractor
setDataSource_l- extractor 内の Track に "video/" があれば、それをフィールド変数で保持する
NuPlayer
- NuPlayer は libmediaplayerservice 内にあるけど、 httplive 周りのソースは libstagefright に依存している
用語集
- Stagefright
- 脆弱性で話題の Stagefright
- AwesomePlayer
- Stagefright のプレイヤーの名前
- NuPlayer
- ストリーミング用のプレイヤーの名前
- Lollipop から、ストリーミング以外の部分もやろうとしている (Stagefright 置き換え?)
- OMX / Open MAX
- Khronos Group が策定しているメディア API
- Bellagio
- http://omxil.sourceforge.net/
- OpenMAX IL 実装の一つ
- Widevine
- Google の DRM
- HLS / Http Live Streaming
- HTTP 越しにメディアを再生するやつ
- Apple が m3u というプレイリストフォーマットを魔改造して作ったもの
参考リンク
- http://www.slideshare.net/l_b__/stagefright-9344628
- Android builders summit - The Android media framework (PDF)
- Integrating a Hardware Video Codec into Android Stagefright using OpenMAX IL (PDF)
所感
- メディア再生の仕組みを調べたいのに脆弱性ばかりでてくる
- まだまだ調べ切れてないので、もっとソース読んでいきたい
追記 (2015/9/15)
Git の参照しているブランチが master だったので MediaPlayer まわりにコミットがあるとだんだんこの解説と乖離してしまいそう。ということで、 2015/9/15 現在で最新の android-5.1.1_r18 というタグに変更した。

