Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Flow of events during Media Player creation in Android
1. Flow of events during Media Player Creation in
Android
Somenath Mukhopadhyay
som.mukhopadhyay@gmail.com
The flow of events of the Android media player is complex. This document will serve as a
hand-holding for code walkthrough of the Android multimedia framework for the Android lovers.
To start with, let me give you the call stack of the media player framework in Android. This has
been depicted as in the following diagram.
Now lets come to the fact findings. There are two sides of the Android Media Framework. What we
as an user see is the Java interface which is called the Mediaplayer.java. However, this java
interface interacts with a native mediaplayer object through Java Native Interface (JNI)
mechanism. This interaction is done through the functionalities defined in
Android_media_Mediaplayer.cpp. In this file the framework engineers have kept all the
necessary JNI functions.
Now when we are about to start the MediaPlayer, the JNI function that is called is the
private native final void native_setup.
This function is actually responsible for creating a C++ mediaplayer object in the native side and
storing it as an opaque reference in the Java client side. So when we interact with the client side
Java mediaplayer object, we internally interact with this native C++ object.
2. The JNI layer actually delegates its task to a Mediaplayer object. The functionalities of this C++
class are defined in the file Mediaplayer.cpp.
Now the next step is that we set a data source in the Java side using the function setDataSource
function in which the URI of the data source is passed. This in turn calls the native function
android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)
In the native source, this function is defined as
adodmdaMdalyrstaaoreJIn *n,jbetti,jtigpt)
nri_ei_eiPae_eDtSuc(NEv ev ojc hz srn ah
{
s < e i P a e >m =g t e i P a e ( n , t i )
pMdalyr p eMdalyrev hz;
i ( p = N L ) {
f m = UL
jihoEcpinev "aaln/leaSaexeto" NL)
nTrwxeto(n, jv/agIlglttEcpin, UL;
rtr;
eun
}
i ( a h = N L ) {
f pt = UL
jihoEcpinev "aaln/leaAgmnEcpin,NL)
nTrwxeto(n, jv/agIlglruetxeto" UL;
rtr;
eun
}
c n tc a * a h t =e v > e S r n U F h r ( a h N L )
os hr ptSr n-GttigTCaspt, UL;
i ( a h t = N L ) { / O t o m m r
f ptSr = UL
/ u f eoy
jihoEcpinev "aaln/utmEcpin,"u o mmr";
nTrwxeto(n, jv/agRniexeto" Ot f eoy)
rtr;
eun
}
LG(staaore pt %" ptSr;
OV"eDtSuc: ah s, aht)
s a u _ o S a u =m - s t a a o r e p t S r ;
ttst ptts p>eDtSuc(aht)
/ Mk sr ta lclrfi rlae bfr aptnilecpin
/ ae ue ht oa e s eesd eoe
oeta xeto
ev>eesSrnUFhr(ah ptSr;
n-RlaetigTCaspt, aht)
poesmdapae_al ev ti,oSau,"aai/Oxeto" "eDtSuc
rcs_ei_lyrcl( n, hz ptts jv/oIEcpin, staaore
f i e . )
ald" ;
}
Look at the line:
status_t opStatus = mp->setDataSource(pathStr);
This function is defined as
s a u _ M d a l y r : e D t S u c ( o s c a * r )
ttst eiPae:staaorecnt hr ul
{
LG(staaore%),ul;
OV"eDtSuc(s" r)
s a u _ e r =B D V L E
ttst r A_AU;
i ( r ! N L ) {
f ul = UL
c n ts < M d a l y r e v c > s r i e g t e i P a e S r i e ) ;
os pIeiPaeSrie& evc(eMdalyrevc()
i ( e v c ! 0 {
f srie = )
3. s < M d a l y r p a e ( e v c - c e t ( e p d ) t i , u l )
pIeiPae> lyrsrie>raegti(, hs r);
e r =s t a a o r e p a e )
r eDtSuc(lyr;
}
}
r t r e r
eun r;
}
Look at the line :
sp<IMediaPlayer> player(service->create(getpid(), this, url));
It actually takes the help of the IMediaPlayerservice layer and calls the create function on this. This
function can be found in basemedialibmediaIMediaPlayerService.cpp file.
The create function of the MediaPlayerService looks like the following. It can be found at
basemedialibmediaplayerserviceMediaPlayerService.cpp.
sp<IMediaPlayer>
MediaPlayerService::create(pid_t pid, const
s < M d a l y r M d a l y r e v c : c e t ( i _ p d c n ts < M d a l y r l e t &
pIeiPae> eiPaeSrie:raepdt i, os pIeiPaeCin>
c i n , c n tc a *u l
let os hr r)
{
i t 2 tc n I =a d o d a o i _ n ( m e t o n d ;
n3_ ond nri_tmcic&NxCnI)
s < l e t c =n wC i n ( h s p d c n I , c i n )
pCin>
e letti, i, ond let;
LG(Cet nwcin(d fo pd%,ul%,cnI=d,cnI,pd ul cnI)
OV"rae e let%) rm i d r=s ond%" ond i, r, ond;
i ( O E R R ! c > e D t S u c ( r )
f N_RO = -staaoreul)
{
ccer)
.la(;
r t r c
eun ;
}
w < l e t w =c
pCin>
;
Mtx:uooklc(Lc)
ue:Atlc okmok;
mlet.d()
Cinsadw;
r t r c
eun ;
}
Look at the line :
sp<Client> c = new Client(this, pid, connId, client)
The client constructor is as the following:
s < M d a l y r M d a l y r e v c : c e t ( i _ p d c n ts < M d a l y r l e t &
pIeiPae> eiPaeSrie:raepdt i, os pIeiPaeCin>
c i n , c n tc a *u l
let os hr r)
{
i t 2 tc n I =a d o d a o i _ n ( m e t o n d ;
n3_ ond nri_tmcic&NxCnI)
s < l e t c =n wC i n ( h s p d c n I , c i n )
pCin>
e letti, i, ond let;
4. LG(Cet nwcin(d fo pd%,ul%,cnI=d,cnI,pd ul cnI)
OV"rae e let%) rm i d r=s ond%" ond i, r, ond;
i ( O E R R ! c > e D t S u c ( r )
f N_RO = -staaoreul)
{
ccer)
.la(;
r t r c
eun ;
}
w < l e t w =c
pCin>
;
Mtx:uooklc(Lc)
ue:Atlc okmok;
mlet.d()
Cinsadw;
r t r c
eun ;
}
Now look at the following line (line number 6) of sp<IMediaPlayer>
MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url)
if (NO_ERROR != c->setDataSource(url))
So we are basically calling the setDataSource on the Client.
This function is like the following:
s a u _ M d a l y r e v c : C i n : s t a a o r e c n tc a * r )
ttst eiPaeSrie:let:eDtSuc(os hr ul
{
LG(staaore%),ul;
OV"eDtSuc(s" r)
i ( r = N L )
f ul = UL
r t r U K O N E R R
eun NNW_RO;
i ( t n m ( r , " o t n : / , 1 ) = 0 {
f srcpul cnet/" 0 = )
/ gtafldsrpo frtecnetUiad
/ e
ieecitr o h otn r n
/ ps i t testaaoref)mto
/ as t o h eDtSuc(d ehd
Srn1 ul6ul;
tig6 r1(r)
i tf =a d o d : p n o t n P o i e F l ( r 1 )
n d nri:oeCnetrvdrieul6;
i ( d <0
f f )
{
LG(Cud' oe f fr%" ul;
OE"olnt pn d o s, r)
r t r U K O N E R R
eun NNW_RO;
}
staaoref,0 07ffffL) / ti st mtts
eDtSuc(d , xfffffL; / hs es Sau
coef)
ls(d;
r t r m t t s
eun Sau;
} e s {
le
p a e _ y e p a e T p =g t l y r y e u l ;
lyrtp lyrye ePaeTp(r)
LG(pae tp =%" paeTp)
OV"lyr ye
d, lyrye;
/ cet tergttp o pae
/ rae h ih ye f lyr
s < e i P a e B s >p =c e t P a e ( l y r y e ;
pMdalyrae
raelyrpaeTp)
i ( = N L ) r t r N _ N T
f p = UL eun OII;
i ( p > a d a e u p t ) {
f !-hrwrOtu()
5. m u i O t u =n wA d o u p t )
Adoupt e uiOtu(;
sai_atMdalyrnefc*(.e()>eAdoikmuiOtu)
ttccs<eiPaeItrae>pgt)-stuiSn(Adoupt;
}
/ nwstdt suc
/ o e aa ore
LG( staaore)
OV" eDtSuc";
m t t s =p > e D t S u c ( r )
Sau -staaoreul;
i ( S a u = N _ R O ) m l y r =p
f mtts = OERR Pae ;
r t r m t t s
eun Sau;
}
}
From the above code snippet it becomes clear that either we do
i ( t n m ( r , " o t n : / , 1 ) = 0 {
f srcpul cnet/" 0 = )
/ gtafldsrpo frtecnetUiad
/ e
ieecitr o h otn r n
/ ps i t testaaoref)mto
/ as t o h eDtSuc(d ehd
Srn1 ul6ul;
tig6 r1(r)
i tf =a d o d : p n o t n P o i e F l ( r 1 )
n d nri:oeCnetrvdrieul6;
i ( d <0
f f )
{
LG(Cud' oe f fr%" ul;
OE"olnt pn d o s, r)
r t r U K O N E R R
eun NNW_RO;
}
staaoref,0 07ffffL) / ti st mtts
eDtSuc(d , xfffffL; / hs es Sau
coef)
ls(d;
r t r m t t s
eun Sau;
●
●
or
we do the following:
e s {
le
p a e _ y e p a e T p =g t l y r y e u l ; / h r i e t a t t e P a e T p f o
lyrtp lyrye ePaeTp(r) /ee t xrcs h lyr ye rm
teUL
h R.
LG(pae tp =%" paeTp)
OV"lyr ye
d, lyrye;
/ cet tergttp o pae
/ rae h ih ye f lyr
s < e i P a e B s >p =c e t P a e ( l y r y e ;
pMdalyrae
raelyrpaeTp)
.......
.......
.......
.......
I t e f r t c s t e s t a a o r e ( i e 1 ) f n t o l o s l k t e f l o i g
n h is ae h eDtSuc ln 2 ucin ok ie h olwn:
s a u _ M d a l y r e v c : C i n : s t a a o r e i tf , i t 4 to f e , i t 4 tl n t )
ttst eiPaeSrie:let:eDtSuc(n d n6_ fst n6_ egh
{
6. LG(staaoref=d ofe=ld lnt=ld,f,ofe,lnt)
OV"eDtSuc d%, fst%l, egh%l" d fst egh;
s r c s a s ;
tut tt b
i tr t =f t t f , & b ;
n e sa(d s)
i ( e ! 0 {
f rt = )
LG(ftt%)fie:%,%" f,rt srro(rn);
OE"sa(d ald d s, d e, terrero)
r t r U K O N E R R
eun NNW_RO;
}
LG(s_e =%l" s.tdv;
OV"tdv
lu, bs_e)
LG(s_oe=%" s.tmd)
OV"tmd
u, bs_oe;
LG(s_i =%u,s.tud;
OV"tud
l" bs_i)
LG(s_i =%u,s.tgd;
OV"tgd
l" bs_i)
LG(s_ie=%l" s.tsz)
OV"tsz
lu, bs_ie;
i ( f s t > s . t s z ) {
f ofe = bs_ie
LG(ofe err)
OE"fst ro";
:coef)
:ls(d;
r t r U K O N E R R
eun NNW_RO;
}
i ( f s t +l n t >s . t s z ) {
f ofe egh bs_ie
l n t =s . t s z -o f e ;
egh bs_ie fst
LG(cluae lnt =%l" lnt)
OV"acltd egh
ld, egh;
}
p a e _ y e p a e T p =g t l y r y e f , o f e , l n t ) / h r i g t t e f l t p
lyrtp lyrye ePaeTp(d fst egh; /ee t es h ie ye
fo teFl dsrpo
rm h ie ecitr
LG(pae tp =%" paeTp)
OV"lyr ye
d, lyrye;
/ cet tergttp o pae
/ rae h ih ye f lyr
s < e i P a e B s >p =c e t P a e ( l y r y e ;
pMdalyrae
raelyrpaeTp)
i ( = N L ) r t r N _ N T
f p = UL eun OII;
i ( p > a d a e u p t ) {
f !-hrwrOtu()
m u i O t u =n wA d o u p t )
Adoupt e uiOtu(;
sai_atMdalyrnefc*(.e()>eAdoikmuiOtu)
ttccs<eiPaeItrae>pgt)-stuiSn(Adoupt;
}
/ nwstdt suc
/ o e aa ore
m t t s =p > e D t S u c ( d o f e , l n t )
Sau -staaoref, fst egh;
i ( S a u = N _ R O ) m l y r =p
f mtts = OERR Pae ;
r t r m t t s
eun Sau;
}
Look at the line :
sp<MediaPlayerBase> p = createPlayer(playerType). It becomes clear that we create the
player here.
The sp<MediaPlayerBase> p = createPlayer (playerType) actually creates the right player.
7. In the second case (the else part) we call sp<MediaPlayerBase> p = createPlayer(playerType)
at line 6. We extract the file type from the URL. This helps us in creating the right player object.
The createPlayer function looks like the following:
s < e i P a e B s >M d a l y r e v c : C i n : c e t P a e ( l y r t p p a e T p )
pMdalyrae eiPaeSrie:let:raelyrpae_ye lyrye
{
/ dtriei w hv tergtpae tp
/ eemn f e ae h ih lyr ye
s < e i P a e B s >p =m l y r
pMdalyrae
Pae;
i ( p ! N L ) & ( - p a e T p ( ! p a e T p ) {
f ( = UL & p>lyrye) = lyrye)
LG(dlt pae";
OV"eee lyr)
pcer)
.la(;
}
i ( = N L ) {
f p = UL
p =a d o d : r a e l y r p a e T p , t i , n t f )
nri:cetPae(lyrye hs oiy;
}
r t r p
eun ;
}
Hence it actually delegates the task to p = android::createPlayer(playerType, this, notify);
The above function is as follows;
s a i s < e i P a e B s >c e t P a e ( l y r t p p a e T p , v i *c o i ,
ttc pMdalyrae raelyrpae_ye lyrye od oke
ntf_alakfntfFn)
oiyclbc_ oiyuc
{
s < e i P a e B s >p
pMdalyrae ;
s i c ( l y r y e {
wth paeTp)
#fdfN_PNOE
ine OOECR
c s P _ L Y R
ae VPAE:
LG( cet PPae";
OV" rae Vlyr)
p =n wP P a e ( ;
e Vlyr)
bek
ra;
#ni
edf
c s S N V X P A E :
ae OIO_LYR
LG( cet MdFl";
OV" rae iiie)
p =n wM d F l ( ;
e iiie)
bek
ra;
c s V R I _ L Y R
ae OBSPAE:
LG( cet VriPae";
OV" rae obslyr)
p =n wV r i P a e ( ;
e obslyr)
bek
ra;
}
i ( ! N L ) {
f p = UL
i ( - i i C e k ) = N _ R O ) {
f p>nthc( = OERR
p>eNtfClbc(oke ntfFn)
-stoiyalakcoi, oiyuc;
} e s {
le
pcer)
.la(;
}
8. }
i ( = N L ) {
f p = UL
LG(Fie t cet pae ojc";
OE"ald o rae lyr bet)
}
r t r p
eun ;
}
Thus we find that the right player is created through the parameterized factory function
createPlayer.
i hope this explains how the right mediaplayer is created from the Uri passed in the Java client
side interface of the Mediaplyer.