基于android 4.1.1 源码
【1】mediaserver 启动后会把media相关一些服务添加到servicemanager中,其中就有mediaPlayerService.这样应用启动前,系统就有了mediaPlayerService这个服务程序。
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
【2】应用层 mediaPlayer=new MediaPlayer(); 调用SDK中 MediaPlayer.java (frameworks\base\media\java\android\media\MediaPlayer.java)
public MediaPlayer() {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference(this));
}
通过JNI方式调用到framework层 android_media_MediaPlayer.cpp(\frameworks\base\media\jni\android_media_MediaPlayer.cpp)
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV("native_setup");
sp mp = new MediaPlayer();
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
// create new listener and give it to MediaPlayer
sp listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener);
// Stow our new C++ MediaPlayer in an opaque field in the Java object.
setMediaPlayer(env, thiz, mp);
}
继而调用mediaplayer.cpp(frameworks\av\media\libmedia\mediaplayer.cpp)
【3】在整个应用程序的进程中,mediaplayer.cpp 中 setDataSource会从service manager中获得mediaPlayerService 服务,然后通过服务来创建player。这个player就是播放器的真实实例。
status_t MediaPlayer::setDataSource(const sp &source)
{
ALOGV("setDataSource");
status_t err = UNKNOWN_ERROR;
const sp& service(getMediaPlayerService());
if (service != 0) {
sp player(service->create(getpid(), this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(source))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
【4】通过 getMediaPlayerService 得到的service其实是 BpMediaPlayerService,这是和 mediaPlayerService 进程中的BnMediaPlayerService 相对应负责binder通讯。BpMediaPlayerService中的create其实通过binder机制将CREATE消息发送出去。
virtual sp create(
pid_t pid, const sp& client, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeStrongBinder(client->asBinder());
data.writeInt32(audioSessionId);
remote()->transact(CREATE, data, &reply);
return interface_cast(reply.readStrongBinder());
}
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pid_t pid = data.readInt32();
sp client =
interface_cast(data.readStrongBinder());
int audioSessionId = data.readInt32();
sp player = create(pid, client, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
case MAKE_CRYPTO:
}
当发现是CREATE才真正调用了MediaPlayerService 中的create函数。在create函数中其实是创建了一个MediaPlayerService::Client的实例,也就是 说 MediaPlayerService会为每个client应用进程创建一个相应的MediaPlayerService::Client的实例,来提供服务。
sp MediaPlayerService::create(pid_t pid, const sp& client,
int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
sp c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
wp w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
struct stat sb;
int ret = fstat(fd, &sb);
if (ret != 0) {
ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
return UNKNOWN_ERROR;
}
ALOGV("st_dev = %llu", sb.st_dev);
ALOGV("st_mode = %u", sb.st_mode);
ALOGV("st_uid = %lu", sb.st_uid);
ALOGV("st_gid = %lu", sb.st_gid);
ALOGV("st_size = %llu", sb.st_size);
if (offset >= sb.st_size) {
ALOGE("offset error");
::close(fd);
return UNKNOWN_ERROR;
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
ALOGV("calculated length = %lld", length);
}
// Until re-transmit functionality is added to the existing core android
// players, we use the special AAH TX player whenever we were configured for
// retransmission.
player_type playerType = getPlayerType(fd, offset, length);
sp p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
}
// now set data source
setDataSource_post(p, p->setDataSource(fd, offset, length));
return mStatus;
}
sp MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
ALOGV("player type = %d", playerType);
// create the right type of player
sp p = createPlayer(playerType);
if (p == NULL) {
return p;
}
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast(p.get())->setAudioSink(mAudioOutput);
}
return p;
}
sp MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
sp p = mPlayer;
if ((p != NULL) && (p->playerType() != playerType)) {
ALOGV("delete player");
p.clear();
}
if (p == NULL) {
p = android::createPlayer(playerType, this, notify);
}
if (p != NULL) {
p->setUID(mUID);
}
return p;
}
static sp createPlayer(player_type playerType, void* cookie,
notify_callback_f notifyFunc)
{
sp p;
switch (playerType) {
case SONIVOX_PLAYER:
ALOGV(" create MidiFile");
p = new MidiFile();
break;
case STAGEFRIGHT_PLAYER:
ALOGV(" create StagefrightPlayer");
p = new StagefrightPlayer;
break;
case NU_PLAYER:
ALOGV(" create NuPlayer");
p = new NuPlayerDriver;
break;
case TEST_PLAYER:
ALOGV("Create Test Player stub");
p = new TestPlayerStub();
break;
case AAH_RX_PLAYER:
ALOGV(" create A@H RX Player");
p = createAAH_RXPlayer();
break;
case AAH_TX_PLAYER:
ALOGV(" create A@H TX Player");
p = createAAH_TXPlayer();
break;
default:
ALOGE("Unknown player type: %d", playerType);
return NULL;
}
if (p != NULL) {
if (p->initCheck() == NO_ERROR) {
p->setNotifyCallback(cookie, notifyFunc);
} else {
p.clear();
}
}
if (p == NULL) {
ALOGE("Failed to create player object");
}
return p;
}
在上面中已经看不到opencore的影子了,creaPlayer 中会根据类型来创建播放器的实例。Stagefright的实例就是在这里创建的。
下一步我们能真正进入到Stagefright里了