MediaPlayer of the framework of Android source analysis

Source: Internet
Author: User
Tags throw exception

In Android, MediaPlayer is used to play audio and video files, and here is an analysis of how MediaPlayer is called in the framework layer, MediaPlayer code is located at:./frameworks/base/media/ Java/android/media/mediaplayer.java the code used below is based on Android 4.4

When opened, there is a static code block that loads the library file, as long as the class is created and the library is loaded.

    static {        system.loadlibrary ("Media_jni");        Native_init ();    }
The source code for libmedia_jni.so is located at:./frameworks/base/media/jni

There is a makefile file in the Jni folder android.mk

Local_path:= $ (call My-dir) include $ (clear_vars) local_src_files:= android_media_imagereader.cpp Android_media_medi ACrypto.cpp android_media_mediacodec.cpp android_media_mediacodeclist.cpp android_media_mediadrm.cpp Andro Id_media_mediaextractor.cpp android_media_mediamuxer.cpp android_media_mediaplayer.cpp Android_media_MediaReco Rder.cpp android_media_mediascanner.cpp android_media_mediametadataretriever.cpp android_media_resampleinputst Ream.cpp android_media_mediaprofiles.cpp android_media_amrinputstream.cpp android_media_utils.cpp android_ Mtp_mtpdatabase.cpp android_mtp_mtpdevice.cpp android_mtp_mtpserver.cpp local_shared_libraries: = Libandroid_r Untime libnativehelper libutils libbinder libmedia libskia libui liblog libcutils LIBG UI Libstagefright libstagefright_foundation libcamera_client libmtp libusbhost libexif Libstag Efright_amrnb_common LOCAl_required_modules: = libjhead_jnilocal_static_libraries: = libstagefright_amrnbenclocal_c_includes + + extern Al/libexif/external/tremor/tremor Frameworks/base/core/jni Frameworks/av/media/libmedia frameworks/av/med Ia/libstagefright frameworks/av/media/libstagefright/codecs/amrnb/enc/src frameworks/av/media/libstagefright/     Codecs/amrnb/common Frameworks/av/media/libstagefright/codecs/amrnb/common/include $ (TOP)/MEDIATEK/EXTERNAL/AMR     FRAMEWORKS/AV/MEDIA/MTP Frameworks/native/include/media/openmax $ (call include-path-for, Libhardware)/hardware System/media/camera/include $ (pv_includes) $ (jni_h_include) $ (call include-path-for, CORECG graphics) ifeq ( $ (Strip $ (mtk_tb_debug_support)), yes) Local_c_includes + = $ (mtk_path_source)/frameworks/base/include endififeq ($ ( Strip $ (mtk_high_quality_thumbnail)), yes) Local_cflags + =-dmtk_high_quality_thumbnailendififeq ($ (Strip $ (MTK_USE_ Android_mm_default_code), yes) local_cflags + =-dandroid_default_codeendiflocal_cflags +=local_ldlibs: =-lpthreadlocal_module:= libmedia_jniinclude $ (BUILD_ shared_library) # Build libsoundpool.so# build Libaudioeffect_jni.soinclude $ (call all-makefiles-under,$ (LOCAL_PATH))
local_module:= Libmedia_jni generates LIBMEDIA_JNI library after compiling

There are four overloaded functions to open a file

Setdatasource (String Path)
Setdatasource (FileDescriptor FD)
Setdatasource (context context, URI Uri)
Setdatasource (filedescriptor fd, long offset, long length)

In the app, such as native music

 /** * M:add Async prepare to Aviod ANR, add information and duration Update listener * * @param  Player the MediaPlayer * @param path The data source path * @param async m:use Async Prepare if it ' s set         True.         * @return If Set Data source success, return True, otherwise false. */Private Boolean Setdatasourceimpl (MediaPlayer player, String path, Boolean async) {MUSICLOGUTILS.D (T            AG, "Setdatasourceimpl (" + path + "); async =" + Async ";                try {player.reset ();                if (async) {Player.setonpreparedlistener (Preparedlistener);                } else {player.setonpreparedlistener (null); } if (Path.startswith ("content://")) {Player.setdatasource (Mediaplaybackservice.this, U                Ri.parse (path)); } else {///M:add Add for DRM secure flag @{mediaplayerex.setcontextforsecureflag (player,medIaPlaybackService.this.getApplicationContext ());//@}player.setdatasource (path);                     }//M:attach auxiliary audio effect only with valid effect ID if (Mauxeffectid > 0) {                    Player.attachauxeffect (Mauxeffectid);                    Player.setauxeffectsendlevel (1.0f);                    Mwhetherattachwhenpause = false;                MUSICLOGUTILS.D (TAG, "setdatasourceimpl:attachauxeffect Mauxeffectid =" + Mauxeffectid);                } player.setaudiostreamtype (Audiomanager.stream_music);                if (async) {Player.prepareasync ();                } else {player.prepare ();                }} catch (IOException ex) {//todo:notify The user why the file couldn ' t is opened                MUSICLOGUTILS.E (TAG, "Setdatasourceimpl:" + ex);            return false; } catch (IllegalArgumentException ex) {//todo:notify The user why the file couldn ' t is opened MUSICLOGUTILS.E (TAG, "Setdatasourceimpl:" + ex);            return false;                } catch (IllegalStateException ex) {MUSICLOGUTILS.E (TAG, "Setdatasourceimpl:" + ex);            return false;            } player.setoncompletionlistener (listener);            Player.setonerrorlistener (Errorlistener);            Player.setoninfolistener (Infolistener);            Player.setondurationupdatelistener (Durationlistener);            Sendsessionidtoaudioeffect (FALSE);        return true; }
Regardless of which function is called in the app, the last in Mediaplayer.java is called

/** * Sets the data source (FileDescriptor) to use. The FileDescriptor must be * seekable (n.b. A localsocket are not seekable). It is the caller's responsibility * to close the file descriptor.     The It is safe-to-do as soon-a-call returns. * * @param fd The FileDescriptor for the file, want to play * @param offset the offset into the file where the Data to being played starts, in bytes * @param length The length in bytes of the data to be played * @throws illegals  Tateexception if it is called in a invalid state */public void Setdatasource (FileDescriptor fd, long offset, long        Length) throws IOException, IllegalArgumentException, illegalstateexception {disableproxylistener ();    _setdatasource (fd, offset, length); Private native void _setdatasource (FileDescriptor fd, long offset, long length) throws IOException, Illega Largumentexception, illegalstateexception; 
_setdatasource has native modification, is libmedia_jni.so in the method, found./frameworks/base/media/jni/android_media_mediaplayer.cpp

----------------------------------------------------------------------------static Jninativemethod gmethods[] = {{"_setdatasource", "(ljava/lang/string;[ ljava/lang/string;       [ljava/lang/string;) V ", (void *) Android_media_mediaplayer_setdatasourceandheaders}, {" _setdatasource ", "(Ljava/io/filedescriptor;        JJ) v ", (void *) ANDROID_MEDIA_MEDIAPLAYER_SETDATASOURCEFD}, {" _setvideosurface "," (landroid/view/surface;) v ", (void *) Android_media_mediaplayer_setvideosurface}, {"Prepare", "() V", (voi d *) Android_media_mediaplayer_prepare}, {"Prepareasync", "() V", (void *) android_med Ia_mediaplayer_prepareasync}, {"_start", "() V", (void *) ANDROID_MEDIA_MEDIAPL Ayer_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_m Ediaplayer_pause}, {"IsPlaying", "() Z", (void *) Android_media_mediaplayer_isplay ing}, {"GetCurrentPosition", "() I", (void *) Android_media_mediaplayer_getcurrentposition} , {"Getduration", "() I", (void *) Android_media_mediaplayer_getduration}, {"_rel              Ease "," () 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}, {"Islooping", "() Z", (void *) Android_me Dia_mediaplayer_islooping}, {"SetVolume", "(FF) V", (void *) Android_media_mediaplay Er_setvolume}, {"Native_invoke", "(Landroid/os/parcel; Landroid/os/parcel;) I ", (void *) Android_media_mediaplayer_invoke}, {" Native_setmetadatafilter "," (landroid/os/ Parcel;) I ", (void *) Android_media_mediaplayer_setmetadatafilter}, {" Native_getmetadata "," (Zzlandroid/os/parcel;) Z                              ", (void *) Android_media_mediaplayer_getmetadata}, {" Native_init "," () V ", (void *) Android_media_mediaplayer_native_init}, {"Native_setup", "(Ljava/lang/object;) V", (void *) an                     Droid_media_mediaplayer_native_setup}, {"Native_finalize", "() V",         (void *) Android_media_mediaplayer_native_finalize}, {"Getaudiosessionid", "() I",                             (void *) android_media_mediaplayer_get_audio_session_id}, {"Setaudiosessionid", "(I) V", (void *) android_media_mediaplayer_set_audio_session_id}, {"Setauxeffectsendlevel", "(F) v", (v OID *) Android_media_mediaplayer_setauxeffectsendlevel}, {"Attachauxeffect", "(I) V", (VO ID *) Android_media_mediaplayer_attachauxeffect}, {"Native_pullbatterydata", "(Landroid/os/parcel;) I", (void *) an Droid_media_mediaplayer_pullbatterydata}, {"Setparameter", "(Ilandroid/os/parcel;) Z", (void *) android_m Edia_mediaplayer_setparameter}, {"GetParameter", "(Ilandroid/os/parcel;) V", (void *) Android_media_media Player_getparameter}, {"Native_setretransmitendpoint", "(ljava/lang/string;i) I", (void *) Android_media_mediaplayer    _setretransmitendpoint},{"Setnextmediaplayer", "(Landroid/media/mediaplayer;) V", (void *) Android_media_mediaplayer_setnextmediaplayer}, {" Updateproxyconfig "," (landroid/net/proxyproperties;) V ", (void *) Android_media_mediaplayer_updateproxyconfig},};
Will enter the following function

Static VOIDANDROID_MEDIA_MEDIAPLAYER_SETDATASOURCEFD (jnienv *env, Jobject thiz, jobject filedescriptor, Jlong offset, Jlong length) {    sp<mediaplayer> MP = Getmediaplayer (env, thiz);    if (MP = = null) {        jnithrowexception (env, "java/lang/illegalstateexception", null);        return;    }    if (FileDescriptor = = null) {        jnithrowexception (env, "java/lang/illegalargumentexception", null);        return;    }    int FD = Jnigetfdfromfiledescriptor (env, filedescriptor);    ALOGV ("Setdatasourcefd:fd%d", FD);    Process_media_player_call (env, Thiz, Mp->setdatasource (FD, offset, length), "Java/io/ioexception", " SETDATASOURCEFD failed. ");
Mp->setdatasource (fd, offset, length)//Call Open File method

Open the./frameworks/av/media/libmedia/mediaplayer.cpp Setdatasource has three overloaded functions, depending on the parameters

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;}
Open./frameworks/av/media/libmedia/imediaplayer.cpp Setdatasource also has three overloaded functions, depending on the parameters

    status_t setdatasource (int fd, int64_t offset, int64_t length) {        Parcel data, reply;        Data.writeinterfacetoken (Imediaplayer::getinterfacedescriptor ());        Data.writefiledescriptor (FD);        Data.writeint64 (offset);        Data.writeint64 (length);        Remote ()->transact (SET_DATA_SOURCE_FD, DATA, &reply);        return Reply.readint32 ();    }
This open file process is for local media files only.

Process_media_player_call (env, Thiz, Mp->setdatasource (FD, offset, length), "Java/io/ioexception", " SETDATASOURCEFD failed. ") Processing based on the returned results

If exception is NULL and Opstatus are not OK, this method sends a error//event to the client application; Otherwise, if exception is not NULL and//opstatus are not OK, this method throws the given exception to the client//appli cation.static void Process_media_player_call (jnienv *env, Jobject thiz, status_t opstatus, const char* exception, Const CH Ar *message) {if (exception = = NULL) {//Don ' t throw exception.        Instead, send an event.            if (opstatus! = (status_t) OK) {sp<mediaplayer> MP = Getmediaplayer (env, thiz);        if (MP! = 0) mp->notify (media_error, opstatus, 0);        }} else {//Throw exception! if (Opstatus = = (status_t) invalid_operation) {jnithrowexception (env, "java/lang/illegalstateexception", NUL        L); } else if (Opstatus = = (status_t) permission_denied) {jnithrowexception (env, "java/lang/securityexception",        NULL); } else if (opstatus! = (status_t) OK) {if (strlen (message) (>) {//If the message is too long, and don ' t bother displaying the status code JNI            ThrowException (env, exception, message);                } else {char msg[256];               Append the status code to the message sprintf (MSG, "%s:status=0x%x", message, opstatus);            Jnithrowexception (env, exception, MSG); }        }    }}
Other features (start ' Stop ' play ' seek_to) are the same process, the difficulty is the JNI technology and the Aidl in the app, of course, the above is just a simple call process, to more in-depth understanding or take some time.

MediaPlayer of the framework of Android source analysis

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.