文档章节

Android学习(七)由MediaPlayer切入(3)

lipandroid
 lipandroid
发布于 2015/09/17 17:25
字数 620
阅读 7
收藏 0

MediaPlayer切入(3

继续MediaPlayer的分析:

/*\frameworks\av\media\libmedia\mediaplayer.cpp*/

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)

{

    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);

    status_t err = UNKNOWN_ERROR;

    const sp<IMediaPlayerService>& service(getMediaPlayerService());

    if (service != 0) {

        sp<IMediaPlayer> player(service->create(this, mAudioSessionId));

        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||

            (NO_ERROR != player->setDataSource(fd, offset, length))) {

            player.clear();

        }

        err = attachNewPlayer(player);

    }

    return err;

}

通过getMediaPlayerService()的调用,得到了一个BpMediaPlayerService对象了。

接下来分析service->create(this, mAudioSessionId)

    virtual sp<IMediaPlayer> create(

            const sp<IMediaPlayerClient>& client, int audioSessionId) {

        Parcel data, reply;

        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());

        data.writeStrongBinder(client->asBinder());

        data.writeInt32(audioSessionId);

 

        remote()->transact(CREATE, data, &reply);

        return interface_cast<IMediaPlayer>(reply.readStrongBinder());

    }

同样是调用remote()->transact(CREATE, data, &reply);只不过现在BpBinderhandle值是MediaPlayerServicehandle值,发送的指令也变成了CREATE

/*\Android4.4\frameworks\native\libs\binder\BpBinder.cpp*/

status_t BpBinder::transact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    // Once a binder has died, it will never come back to life.

    if (mAlive) {

        status_t status = IPCThreadState::self()->transact(

            mHandle, code, data, reply, flags);

        if (status == DEAD_OBJECT) mAlive = 0;

        return status;

    }

 

    return DEAD_OBJECT;

}

看看CREATE的定义:

enum {

    CREATE = IBinder::FIRST_CALL_TRANSACTION,

    DECODE_URL,

    DECODE_FD,

    CREATE_MEDIA_RECORDER,

    CREATE_METADATA_RETRIEVER,

    GET_OMX,

    MAKE_CRYPTO,

    MAKE_DRM,

    MAKE_HDCP,

    ADD_BATTERY_DATA,

    PULL_BATTERY_DATA,

    LISTEN_FOR_REMOTE_DISPLAY,

    UPDATE_PROXY_CONFIG,

};

可见CREATE值为1

status_t IPCThreadState::executeCommand(int32_t cmd)

{

    case BR_TRANSACTION:

        {

            binder_transaction_data tr;

            result = mIn.read(&tr, sizeof(tr));

            ALOG_ASSERT(result == NO_ERROR,

                "Not enough command data for brTRANSACTION");

            if (result != NO_ERROR) break;

           

            Parcel buffer;à定义一个buff,然后填充数据

            buffer.ipcSetDataReference(

                reinterpret_cast<const uint8_t*>(tr.dataNaNr.buffer),

                tr.data_size,

                reinterpret_cast<const size_t*>(tr.dataNaNr.offsets),

                tr.offsets_size/sizeof(size_t), freeBuffer, this);

           

                        

          

            Parcel reply;

 

            if (tr.targetNaNr) {

                sp<BBinder> b((BBinder*)tr.cookie);

                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR) reply.setError(error);

 

            } else {

                const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);

                if (error < NO_ERROR) reply.setError(error);

            }

           

           if ((tr.flags & TF_ONE_WAY) == 0) {

                LOG_ONEWAY("Sending reply to %d!", mCallingPid);

                sendReply(reply, 0);

            } else {

                LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);

            }

           

            mCallingPid = origPid;

            mCallingUid = origUid;

           

        }

        break;

 

tr.targetNaNrNULL默认the_context_object(暂时不知道哪里来的)来处理;不为NULL,将tr.cookie强制转换为BBinder,由此可见BBinder就是ServerIPCThreadState沟通的桥梁。

先看看MediaPlayerService的注册过程:

int main(int argc, char** argv)

{

        sp<ProcessState> proc(ProcessState::self());

        sp<IServiceManager> sm = defaultServiceManager();

        ALOGI("ServiceManager: %p", sm.get());

        AudioFlinger::instantiate();

        MediaPlayerService::instantiate();

        CameraService::instantiate();

        AudioPolicyService::instantiate();

        registerExtensions();

        ProcessState::self()->startThreadPool();

        IPCThreadState::self()->joinThreadPool();

}

 

void MediaPlayerService::instantiate() {

    defaultServiceManager()->addService(

            String16("media.player"), new MediaPlayerService());

}

这个地方已经new MediaPlayerService ()一个服务对象。

而看看MediaPlayerService的定义:

\Android4.4\frameworks\av\media\libmediaplayerservice\ MediaPlayerService.cpp

class MediaPlayerService : public BnMediaPlayerService

{

}

class BnMediaPlayerService: public BnInterface<IMediaPlayerService>

{

}

template<typename INTERFACE>

class BnInterface : public INTERFACE, public BBinder

{

public:

    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);

    virtual const String16&     getInterfaceDescriptor() const;

 

protected:

    virtual IBinder*            onAsBinder();

};

可见MediaPlayerService就是一个BBinder

class BnMediaPlayerService: public BnInterface<IMediaPlayerService>

{

public:

    virtual status_t    onTransact( uint32_t code,

                                    const Parcel& data,

                                    Parcel* reply,

                                    uint32_t flags = 0);

};

然后用onTransact做回调。

到此为止,虽然很多地方还没有了解清楚,但基本知道了BpBinderBnBinderBBinder的区别和联系,了解了ServiceManager的工作流程,也就是基本了解了androidBinder的通信原理。

© 著作权归作者所有

lipandroid
粉丝 1
博文 19
码字总数 20690
作品 0
武汉
私信 提问
Android MediaPlayer基本使用方式

使用MediaPlayer播放音频或者视频的最简单例子: JAVA代码部分: public class MediaPlayerStudy extends Activity { private Button bplay,bpause,bstop; private MediaPlayer mp = new Med......

kiy
2014/04/14
81
0
一起学Android之音频视频

概述 Android多媒体框架支持各种常见的媒体类型,可以很容易地将音频、视频和图像集成到App中。通过MediaPlayer Api,可以从应用程序资源(RAW)、文件系统或网络上数据流资源来播放音频或视...

Alan.hsiang
07/13
0
0
Android JNI知识简介

Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语...

长平狐
2013/12/25
83
0
Android媒体播放---Media playback(二)

使用MediaPlayer 媒体框架的最中重要的组件之一是MediaPlayer类。这个类的对象能够用最小的步骤来获取、解码和播放音视频。它支持以下几种不同的媒体来源: 1. 本地资源; 2. 内部的统一资源...

长平狐
2012/10/16
310
0
Android 之 AIDL 和远程 Service 调用

文章转载:http://android.yaohuiji.com/archives/728 本讲的内容,理解起来很难,也许你看了很多资料也看不明白,但是用起来缺简单的要命。所以我们干脆拿一个音乐播放器中进度条的实例来说...

无鸯
2011/09/21
2.1K
1

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud 笔记之Spring cloud config client

观察者模式它的数据的变化是被动的。 观察者模式在java中的实现: package com.hxq.springcloud.springcloudconfigclient;import org.springframework.context.ApplicationListener;i...

xiaoxiao_go
18分钟前
2
0
CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
今天
3
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
7
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部