Android Media Player MediaPlayer Architecture Introduction Tutorial

Source: Internet
Author: User
Tags prepare reset

This article is mainly about the architecture of the most important and complex media Player (MediaPlayer) in Android. For Android, a complete and relatively complex system, the implementation of a MediaPlayer function is not a function of its specific features, but a specific feature how to adapt to the Android system Android The main concrete implementation of MediaPlayer is in Opencore player, which is not the focus of this article. This article focuses on the architecture of the MediaPlayer system, and some other Android applications use similar architectures.

The first part MediaPlayer overview

Android's MediaPlayer contains audio and video playback capabilities, and in the Android interface, music and two applications are called MediaPlayer implementations.

MediaPlayer is implemented at the bottom based on the Opencore (PacketVideo) library, and in order to build a MediaPlayer program, the upper layer also contains interprocess communication, which is based on the binder mechanism in the Android Basic library.

For example, open source Android, MediaPlayer's code is mainly in the following directories:

Path to Java program:

packages/apps/music/src/com/android/music/

Path to Java class:

Frameworks/base/media/java/android/media/mediaplayer.java

Java Local call section (JNI):

Frameworks/base/media/jni/android_media_mediaplayer.cpp

This part of the content compiled into a target is libmedia_jni.so.

The main header files are in the following directory:

frameworks/base/include/media/

The multimedia underlying library is in the following directory:

frameworks/base/media/libmedia/

This part of the content is compiled into a library libmedia.so.

Multimedia Services Section:

frameworks/base/media/libmediaplayerservice/

Files for Mediaplayerservice.h and Mediaplayerservice.cpp

This part of the content is compiled into a library libmediaplayerservice.so.

The part of multimedia player based on Opencore

External/opencore/

This part of the content is compiled into a library libopencoreplayer.so.

In terms of the size of the program, Libopencoreplayer.so is the main implementation part, while the other libraries are basically the ones that are built on them and the mechanism for establishing interprocess communication.

Part II interface and architecture of MediaPlayer

2.1 Overall Frame Chart

The structure of the MediaPlayer is more complex and can be represented by the following diagram

In each library, the libmedia.so is located at the core, and the interface that it provides to the upper level is primarily the MediaPlayer class, and class libmedia_jni.so provides a Java interface by invoking the MediaPlayer class. and implements the Android.media.MediaPlayer class.

Libmediaplayerservice.so is a media server that implements the functionality of the server by inheriting libmedia.so classes, and Other parts of the libmedia.so are communicated through interprocess communication and libmediaplayerservice.so. The true functionality of libmediaplayerservice.so is accomplished by calling Opencore player.

The header file in the MediaPlayer section is in the frameworks/base/include/media/directory, which is the directory of the Libmedia.so library source files frameworks/base/media/libmedia/ corresponding to. The main header file has the following several:

IMediaPlayerClient.h

Mediaplayer.h

IMediaPlayer.h

IMediaPlayerService.h

MediaPlayerInterface.h

In these header files Mediaplayer.h provides an interface to the upper layer, while the other several header files provide some interface classes (that is, classes containing pure virtual functions) that must be inherited by the implementation class to be able to use them.

The relationship between the entire MediaPlayer library and the call is shown in the following illustration:

The entire MediaPlayer, when run, can be roughly divided into client and server two parts, which run in two processes, using the binder mechanism to implement IPC communication. In terms of frame structure, IMediaPlayerService.h, IMediaPlayerClient.h and MediaPlayer.h Three classes define Meidaplayer interfaces and schemas, MediaPlayerService.cpp and Mediaplayer.coo two files are used for Meidaplayer architecture implementation, meidaplayer specific functions in Pvplayer (library libopencoreplayer.so) implementation.

2.2 Header File IMediaPlayerClient.h

IMediaPlayerClient.h is used to describe an interface for a MediaPlayer client, as described below:

Class Imediaplayerclient:public IInterface
{
Public
Declare_meta_interface (mediaplayerclient);
virtual void Notify (int msg, int ext1, int ext2) = 0;
};

Class Bnmediaplayerclient:public Bninterface<imediaplayerclient>
{
Public:
    Virtual status_t  ontransact (uint32_t code,
                                    const parcel& data,
                                    parcel* reply,
                                    uint32_t flags = 0);
};

In the definition, the Imediaplayerclient class inherits the IInterface and defines an interface for the MediaPlayer client, Bnmediaplayerclient inherits Bninterface , which is based on the Android's basic class binder mechanism is implemented in process communication. In fact, according to the definition of the Bninterface class template Bninterface class is equivalent to double inheriting bninterface and imediaplayerclient. This is a common definition of Android.

2.3 Header File Mediaplayer.h

Mediaplayer.h is an external interface class, and it is primarily defined as a MediaPlayer class:

Class Mediaplayer:public Bnmediaplayerclient


{


Public


MediaPlayer ();


~mediaplayer ();


void Onfirstref ();


void Disconnect ();


status_t setdatasource (const char *url);


status_t setdatasource (int fd, int64_t offset, int64_t length);


status_t setvideosurface (const sp&lt;surface&gt;&amp; Surface);


status_t Setlistener (const sp&lt;mediaplayerlistener&gt;&amp; listener);


status_t prepare ();


status_t Prepareasync ();


status_t start ();


status_t Stop ();


status_t pause ();


BOOL IsPlaying ();


status_t getvideowidth (int *w);


status_t getvideoheight (int *h);


status_t seekto (int msec);


status_t getcurrentposition (int *msec);


status_t getduration (int *msec);


status_t Reset ();


status_t setaudiostreamtype (int type);


status_t setlooping (int loop);


status_t SetVolume (float leftvolume, float rightvolume);


void Notify (int msg, int ext1, int ext2);


Static sp&lt;imemory&gt; decode (const char* URL, uint32_t *psamplerate, int* pnumchannels);


Static sp&lt;imemory&gt; decode (int fd, int64_t offset, int64_t length, uint32_t *psamplerate, int* pnumchannels);


......


}

From the interface you can see that the MediaPlayer class just implements a MediaPlayer basic operation, such as play (start), Stop (stop), pause (pause), and so on.

Another class, defined in the MediaPlayer class, inherits the Deathrecipient class in the IBinder class: Deathnotifier.

Class Deathnotifier:public IBinder:: deathrecipient
{
Public
Deathnotifier () {}
Virtual ~deathnotifier ();
virtual void binderdied (const wp<ibinder>& WHO);
};

In fact, the MediaPlayer class is indirectly inheriting IBinder, and MediaPlayer:: Deathnotifier class Inherits IBinder:: Deathrecipient, which is built to implement interprocess communication.

2.4 Header File IMediaPlayer.h

The main content of IMediaPlayer.h is an interface that implements the MediaPlayer function, and its main definition is as follows:

Class Imediaplayer:public IInterface


{


Public


Declare_meta_interface (MediaPlayer);


virtual void disconnect () = 0;


Virtual status_t setvideosurface (const sp&lt;isurface&gt;&amp; surface) = 0;


Virtual status_t prepareasync () = 0;


Virtual status_t start () = 0;


Virtual status_t Stop () = 0;


Virtual status_t pause () = 0;


Virtual status_t isplaying (bool* state) = 0;


Virtual status_t getvideosize (int* W, int* h) = 0;


Virtual status_t seekto (int msec) = 0;


Virtual status_t getcurrentposition (int* msec) = 0;


Virtual status_t getduration (int* msec) = 0;


Virtual status_t reset () = 0;


Virtual status_t setaudiostreamtype (int type) = 0;


Virtual status_t setlooping (int loop) = 0;


Virtual status_t setvolume (float leftvolume, float rightvolume) = 0;


};


Class Bnmediaplayer:public Bninterface&lt;imediaplayer&gt;


{


Public


Virtual status_t ontransact (uint32_t code,


Const parcel&amp; Data,


parcel* reply,


uint32_t flags = 0);


};

In the Imediaplayer class, the main definition of the functional interface of MediaPlayer, which must be inherited to be able to use. It is noteworthy that these interfaces are somewhat similar to the interfaces of the MediaPlayer class, but they are not directly related. In fact, in the various implementations of the MediaPlayer class, it is generally done by calling the implementation class of the Imediaplayer class.

2.5 Header File IMediaPlayerService.h

Class Imediaplayerservice:public IInterface


{


Public


Declare_meta_interface (Mediaplayerservice);


Virtual sp&lt;imediaplayer&gt; Create (pid_t PID, const sp&lt;imediaplayerclient&gt;&amp; client, const char* URL) = 0;


Virtual sp&lt;imediaplayer&gt; Create (pid_t PID, const sp&lt;imediaplayerclient&gt;&amp; Client, int fd, int64_t offset, int64_t length) = 0;


Virtual sp&lt;imemory&gt; decode (const char* URL, uint32_t *psamplerate, int* pnumchannels) = 0;


Virtual sp&lt;imemory&gt; decode (int fd, int64_t offset, int64_t length, uint32_t *psamplerate, int* pnumchannels) = 0;


};


Class Bnmediaplayerservice:public Bninterface&lt;imediaplayerservice&gt;


{


Public


Virtual status_t ontransact (uint32_t code,


Const parcel&amp; Data,


parcel* reply,


uint32_t flags = 0);


};

Because of the pure virtual function, Imediaplayerservice and Bnmediaplayerservice must be implemented to be able to use, in Imediaplayerservice defined create and decode interfaces, is actually something that must be implemented by the successor. Note that the type of the return value of the Create is the SP, which is the interface that provides the implementation functionality. Imediaplayer

The main realization analysis of the third part MediaPlayer

3.1 Java Program section

In the Mediaplaybackservice.java file in the packages/apps/music/src/com/android/music/directory, a call to MediaPlayer is included.

Include a reference to the package in Mediaplaybackservice.java:

Import Android.media.MediaPlayer;

Within the Mediaplaybackservice class, the multiplayer class is defined:

Private class Multiplayer {
Private MediaPlayer Mmediaplayer = new MediaPlayer ();
}

The MediaPlayer class is used in the multiplayer class, and there are some calls to this MediaPlayer, which are called as follows:

Mmediaplayer.reset ();
Mmediaplayer.setdatasource (path);
Mmediaplayer.setaudiostreamtype (Audiomanager.stream_music);

Interfaces such as reset, Setdatasource, and Setaudiostreamtype are implemented through Java native Invocation (JNI).

3.2 MediaPlayer Java Local call section

The MediaPlayer Java Local call section is implemented in a file in the android_media_mediaplayer.cpp of the directory frameworks/base/media/jni/.

Android_media_mediaplayer.cpp defines an array gmethods of the Jninativemethod (Java Native calling method) type, as follows:

Static Jninativemethod gmethods[] = {


{"Setdatasource", "(ljava/lang/string;) V", (void *) Android_media_mediaplayer_setdatasource},


{"Setdatasource", "ljava/io/filedescriptor; JJ) V ", (void *) ANDROID_MEDIA_MEDIAPLAYER_SETDATASOURCEFD},


{"Prepare", "() V", (void *) Android_media_mediaplayer_prepare},


{"Prepareasync", "() V", (void *) Android_media_mediaplayer_prepareasync},


{"_start", "() V", (void *) Android_media_mediaplayer_start},


{"_stop", "() V", (void *) Android_media_mediaplayer_stop},


{"Getvideowidth", "() I", (void *) Android_media_mediaplayer_getvideowidth},


{"Getvideoheight", "() I", (void *) Android_media_mediaplayer_getvideoheight},


{"Seekto", "(I) V", (void *) Android_media_mediaplayer_seekto},


{"_pause", "() V", (void *) Android_media_mediaplayer_pause},


{"IsPlaying", "() Z", (void *) android_media_mediaplayer_isplaying},


{"GetCurrentPosition", "() I", (void *) Android_media_mediaplayer_getcurrentposition},


{"Getduration", "() I", (void *) Android_media_mediaplayer_getduration},


{"_release", "() V", (void *) Android_media_mediaplayer_release},


{"_reset", "() V", (void *) Android_media_mediaplayer_reset},


{"Setaudiostreamtype", "(I) V", (void *) Android_media_mediaplayer_setaudiostreamtype},


{"Setlooping", "(Z) V", (void *) android_media_mediaplayer_setlooping},


{"SetVolume", "(FF) V", (void *) Android_media_mediaplayer_setvolume},


{"Getframeat", "(I) Landroid/graphics/bitmap;", (void *) Android_media_mediaplayer_getframeat},


{"Native_setup", "(Ljava/lang/object;) V", (void *) Android_media_mediaplayer_native_setup},


{"Native_finalize", "() V", (void *) Android_media_mediaplayer_native_finalize},


}

The first member of the Jninativemethod is a string representing the name of the Java native invocation method, which is the name called in the Java program, and the second member is also a string representing the parameters and return values of the Java native invocation method; The third member is the C language function corresponding to the Java local invocation method.

The implementation of the Android_media_mediaplayer_reset function is shown below:

static void Android_media_mediaplayer_reset (JNIEnv *env, Jobject thiz)
{
Sp<mediaplayer> MP = Getmediaplayer (env, thiz);
if (MP = = NULL) {
Jnithrowexception (env, "java/lang/illegalstateexception", NULL);
Return
}
Process_media_player_call (env, Thiz, Mp->reset (), NULL, NULL);
}

In the Android_media_mediaplayer_reset call, you get a MediaPlayer pointer that implements the actual functionality by calling it.

Register_android_media_mediaplayer is used to register Gmethods as the class "Android/media/mediaplayer", which is implemented as follows.

static int Register_android_media_mediaplayer (jnienv *env)
{
Jclass Clazz;
Clazz = Env->findclass ("Android/media/mediaplayer");
// ......
Return Androidruntime::registernativemethods (env, "Android/media/mediaplayer", Gmethods, Nelem (gMethods));
}

The core library of 3.3 MediaPlayer libmedia.so

The Libs/media/mediaplayer.cpp file is used to implement the interface provided by Mediaplayer.h, and one of the important fragments is as follows:

Const sp&lt;imediaplayerservice&gt;&amp; Mediaplayer::getmediaplayerservice ()


{


Mutex::autolock _l (Mservicelock);


if (mmediaplayerservice.get () = = 0) {


sp&lt;iservicemanager&gt; sm = Defaultservicemanager ();


Sp&lt;ibinder&gt; Binder;


do {


Binder = Sm-&gt;getservice (String16 ("Media.player"));


if (Binder!= 0)


Break


LOGW ("Mediaplayerservice not published, waiting ...");


Usleep (500000); 0.5 s


} while (true);


if (Mdeathnotifier = = NULL) {


Mdeathnotifier = new Deathnotifier ();


}


Binder-&gt;linktodeath (Mdeathnotifier);


Mmediaplayerservice = interface_cast&lt;imediaplayerservice&gt; (binder);


}


Loge_if (mmediaplayerservice==0, "no mediaplayerservice!?");


return mmediaplayerservice;


}

One of the most important is binder = Sm->getservice (String16 ("Media.player"), which is used to get a service called "Media.player" that returns the type of the value of IBinder. Converts it to a type imediaplayerservice using the implementation.

A specific function setdatasource is shown below:

status_t mediaplayer::setdatasource (const char *url)
{
LOGV ("Setdatasource (%s)", URL);
status_t err = Unknown_error;
if (URL!= NULL) {
Const sp<imediaplayerservice>& Service (Getmediaplayerservice ());
if (service!= 0) {
Sp<imediaplayer> player (Service->create (Getpid (), this, url));
Err = Setdatasource (player);
}
}
return err;
}

In the function Setdatasource function, the call Getmediaplayerservice gets a imediaplayerservice, and the pointer to the Imediaplayer type is obtained from the Imediaplayerservice , this pointer carries out a specific operation.

Some other functions are also implemented similar to Setdatasource.

Some of the other files in the libmedia.so are the same as the header file names:

Libs/media/imediaplayerclient.cpp

Libs/media/imediaplayer.cpp

Libs/media/imediaplayerservice.cpp

In order to implement the specific functions of binder, it is also necessary to implement a bpxxx class in these classes, such as the IMediaPlayerClient.cpp implementation as follows: L

Class Bpmediaplayerclient:public Bpinterface<imediaplayerclient>
{
Public
Bpmediaplayerclient (const sp<ibinder>& IMPL)
: bpinterface<imediaplayerclient> (impl) {}
virtual void Notify (int msg, int ext1, int ext2)
{
Parcel data, reply;
Data.writeinterfacetoken (Imediaplayerclient::getinterfacedescriptor ());
Data.writeint32 (msg);
Data.writeint32 (EXT1);
Data.writeint32 (ext2);
Remote ()->transact (NOTIFY, data, &reply, Ibinder::flag_oneway);
}
};

You also need to implement the Define macro Implement_meta_interface, which will be expanded to generate several functions:

Implement_meta_interface (mediaplayerclient, "android.hardware.IMediaPlayerClient");

The above implementation is based on the implementation of the binder framework, just follow the template to achieve. Where the Bpxxx class is the proxy class (proxy) and the Bnxxx class is the local class (native). The Transact function of the proxy class and the Ontransact function of the local class implement the corresponding communication.

3.4 Media Service Libmediaservice.so

The MediaPlayerService.h and MediaPlayerService.cpp in the Frameworks/base/medialibmediaplayerservice directory are used to implement a

servers/media/Service, Mediaplayerservice is the implementation of the inheritance Bnmediaplayerservice, within which the class Client,mediaplayerservice is defined: The client inherits Bnmediaplayer.

Class Mediaplayerservice:public Bnmediaplayerservice
{
Class Client:public Bnmediaplayer
}

In Mediaplayerservice, there is a static function instantiate as follows:

void Mediaplayerservice::instantiate () {
Defaultservicemanager ()->addservice (
String16 ("Media.player"), New Mediaplayerservice ());
}

In the instantiate function, you invoke a function AddService of Iservicemanager, which adds a service named "Media.player" to it.

This service named "Media.player" is the same name as the one used in the Mediaplayer.cpp call in GetService. Therefore, the call AddService Add service here can be used by the name "Media.player" in Mediaplayer.cpp. This is the use of binder to implement interprocess communication (IPC), in fact this Mediaplayerservice class is running in the service, while the mediaplayer.cpp called function is running in the application, the two are not a process. But in Mediaplayer.cpp it calls the Mediaplayerservice function like a call to a process.

The Createplayer function in MediaPlayerService.cpp is as follows:

Static sp&lt;mediaplayerbase&gt; Createplayer (Player_type playertype, void* cookies, Notify_callback_f NotifyFunc)


{


Sp&lt;mediaplayerbase&gt; p;


Switch (playertype) {


Case Pv_player:


LOGV ("Create Pvplayer");


p = new Pvplayer ();


Break


Case Sonivox_player:


LOGV ("Create MIDIfile");


p = new MIDIfile ();


Break


Case Vorbis_player:


LOGV ("Create Vorbisplayer");


p = new Vorbisplayer ();


Break


}


......


return p;


}

A different player is created here based on the type of Playertype: For most cases, the type will be Pv_player, and the new Pvplayer () will be invoked to create a pvplayer and then convert the pointer to a mediaplayerbase to use; For the mini file, the type is Sonivox_player and a midifile will be created; for Ogg Vorbis format, a vorbisplayer will be created.

(OGG Vobis is an audio compression format similar to the music format of MP3, which features completely free, open, and without patent restrictions.) )

It is noteworthy that the three classes of Pvplayer, MIDIfile and Vorbisplayer are inherited Mediaplayerinterface, and Mediaplayerinterface are inherited mediaplayerbase , so the three have the same interface type. The respective constructors are invoked only when they are established, and they are mediaplayerbase controlled by the Mediaplayerbase interface only after they are established.

In the Frameworks/base/media/libmediaplayerservice directory, the implementation midifile of MidiFile.h and MidiFile.cpp, VorbisPlayer.h and VorbisPlayer.cpp implement a vorbisplayer.

The realization of 3.5 Opencoreplayer libopencoreplayer.so

Opencore player is implemented in External/opencore/, which is an implementation of a opencore based player. The specific implementation of the file is playerdriver.cpp. It implements two classes: Playerdriver and Pvplayer. Pvplayer implements specific functions by calling the Playerdriver function.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.