• MediaPlayer_Analyze-1-framework


    MediaPlayer Analyze - Framework Java层

    MediaPlayer的简单使用

    // ------ 初始化
    // 方法一
    MediaPlayer mp = new MediaPlayer();
    mp.setDataSource("/sdcard/test.mp3");
    // mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");
    mp.prepare();
    
    // 方法二
    MediaPlayer mp = MediaPlayer.create(this, R.raw.test); //这时就不用调用setDataSource 和 prepare 了
    
    // ------ 播放/暂停/停止/释放
    mp.start();
    mp.pause();
    mp.stop();
    mp.release();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    一 初始化

    1.1 app java调用

    // 方法一
    MediaPlayer mp = new MediaPlayer();
    
    // 方法二
    MediaPlayer mp = MediaPlayer.create(this, R.raw.test); //这时就不用调用setDataSource了
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

    public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting{
    
        public MediaPlayer() {
            super(new AudioAttributes.Builder().build(), AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);
    
            // 线程间异步消息通信(用户不需要考虑互斥加锁的问题) looper,并创建 EventHandler
            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;
            }
    
            mTimeProvider = new TimeProvider(this);
            mOpenSubtitleSources = new Vector<InputStream>();
    
            // 调用jni层接口
            native_setup(new WeakReference<MediaPlayer>(this));
    
            baseRegisterPlayer();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    有 looper 就有 handler:

    frameworks\base\media\java\android\media\MediaPlayer.java

        private class EventHandler extends Handler
        {
            private MediaPlayer mMediaPlayer;
    
            public EventHandler(MediaPlayer mp, Looper looper) {
                super(looper);
                mMediaPlayer = mp;
            }
    
            @Override
            public void handleMessage(Message msg) {
            ...
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    有 native 方法就有:

    frameworks\base\media\java\android\media\MediaPlayer.java

        static {
            System.loadLibrary("media_jni");
            native_init();
        }
    
    • 1
    • 2
    • 3
    • 4

    二 设置source

    2.1 app调用

    // 方法一
    mp.setDataSource("/sdcard/test.mp3");
    // mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");
    
    // 方法二
    MediaPlayer mp = MediaPlayer.create(this, R.raw.test); //这时就不用调用setDataSource 和 prepare了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2 framework-java层接口

    最后都会调用到:

    frameworks\base\media\java\android\media\MediaPlayer.java

        private void setDataSource(String path, String[] keys, String[] values, List<HttpCookie> cookies)
                throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
            final Uri uri = Uri.parse(path);
            // 查找patch对应的方案
            final String scheme = uri.getScheme();
            if ("file".equals(scheme)) { // 本地流
                path = uri.getPath();
            } else if (scheme != null) { // 非本地流,如网络片源
                // handle non-file sources
                nativeSetDataSource( // 非本地流调用
                    MediaHTTPService.createHttpServiceBinderIfNecessary(path, cookies),
                    path,
                    keys,
                    values);
                return;
            }
    
            final File file = new File(path);
            try (FileInputStream is = new FileInputStream(file)) {
                setDataSource(is.getFD());
            }
        }
        private native void nativeSetDataSource(IBinder httpServiceBinder, String path, String[] keys, String[] values)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
        
        //  本地流调用
        public void setDataSource(FileDescriptor fd, long offset, long length)
                throws IOException, IllegalArgumentException, IllegalStateException {
            _setDataSource(fd, offset, length);
        }
        private native void _setDataSource(FileDescriptor fd, long offset, long length)
                throws IOException, IllegalArgumentException, IllegalStateException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    三 准备prepare

    3.1 app调用

    mp.prepare();
    
    • 1

    3.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        public void prepare() throws IOException, IllegalStateException {
            _prepare();
            scanInternalSubtitleTracks();
    
            // DrmInfo, if any, has been resolved by now.
            synchronized (mDrmLock) {
                mDrmInfoResolved = true;
            }
        }
        private native void _prepare() throws IOException, IllegalStateException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    四 开始/恢复播放

    4.1 app调用

    mp.start();
    
    • 1

    4.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        // TODO: 暂时没找到怎样保存播放进度,resume如何恢复
        public void start() throws IllegalStateException {
            final int delay = getStartDelayMs();
            if (delay == 0) {
                startImpl();
            } else {
                new Thread() {
                    public void run() {
                        try {
                            Thread.sleep(delay);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        baseSetStartDelayMs(0);
                        try {
                            startImpl();
                        } catch (IllegalStateException e) {
                        }
                    }
                }.start();
            }
        }
    
        private void startImpl() {
            baseStart(); // 更新状态信息 PlayerBase.java
            stayAwake(true); // 如果有显示,则保持亮屏
            _start();
        }
        private native void _start() throws IllegalStateException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    五 暂停播放

    5.1 app调用

    mp.pause();
    
    • 1

    5.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        public void pause() throws IllegalStateException {
            stayAwake(false); // 如果有显示,关闭保持亮屏
            _pause();
            basePause(); // 更新状态信息 PlayerBase.java
        }
        private native void _pause() throws IllegalStateException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    六 停止播放

    6.1 app调用

    mp.stop();
    
    • 1

    6.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        public void stop() throws IllegalStateException {
            stayAwake(false); // 如果有显示,关闭保持亮屏
            _stop();
            baseStop(); // 更新状态信息 PlayerBase.java
        }
        private native void _stop() throws IllegalStateException;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    七 重置

    7.1 app调用

    mp.reset();
    
    • 1

    7.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        public void reset() {
            mSelectedSubtitleTrackIndex = -1;
            synchronized(mOpenSubtitleSources) {
                for (final InputStream is: mOpenSubtitleSources) {
                    try {
                        is.close();
                    } catch (IOException e) {
                    }
                }
                mOpenSubtitleSources.clear();
            }
            if (mSubtitleController != null) {
                mSubtitleController.reset();
            }
            synchronized (mTimeProviderLock) {
                if (mTimeProvider != null) {
                    mTimeProvider.close();
                    mTimeProvider = null;
                }
            }
    
            stayAwake(false);
            _reset();
            // make sure none of the listeners get called anymore
            if (mEventHandler != null) {
                mEventHandler.removeCallbacksAndMessages(null);
            }
    
            synchronized (mIndexTrackPairs) {
                mIndexTrackPairs.clear();
                mInbandTrackIndices.clear();
            };
    
            resetDrmState();
        }
        private native void _reset();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    八 释放

    8.1 app调用

    mp.release();
    
    • 1

    8.2 framework-java层接口

    frameworks\base\media\java\android\media\MediaPlayer.java

        public void release() {
            baseRelease();
            stayAwake(false);
            updateSurfaceScreenOn();
            mOnPreparedListener = null;
            mOnBufferingUpdateListener = null;
            mOnCompletionListener = null;
            mOnSeekCompleteListener = null;
            mOnErrorListener = null;
            mOnInfoListener = null;
            mOnVideoSizeChangedListener = null;
            mOnTimedTextListener = null;
            synchronized (mTimeProviderLock) {
                if (mTimeProvider != null) {
                    mTimeProvider.close();
                    mTimeProvider = null;
                }
            }
            synchronized(this) {
                mSubtitleDataListenerDisabled = false;
                mExtSubtitleDataListener = null;
                mExtSubtitleDataHandler = null;
                mOnMediaTimeDiscontinuityListener = null;
                mOnMediaTimeDiscontinuityHandler = null;
            }
    
            // Modular DRM clean up
            mOnDrmConfigHelper = null;
            mOnDrmInfoHandlerDelegate = null;
            mOnDrmPreparedHandlerDelegate = null;
            resetDrmState();
    
            _release();
        }
        private native void _release();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
  • 相关阅读:
    Spring Cloud--从零开始搭建微服务基础环境【三】
    【动态规划】是泰波那契数,不是斐波那契数
    Boom 3D for Mac 破解版(3D环绕立体声音效增强软件)2.0.2中文支持M3
    Python文件读写案例——复制大小文件
    一文带你了解IPsec协议
    基础组件-流量回放(全链路流量回放预研)
    JavaWeb-解析session机制和cookie机制
    前端input上传文件 使用new FormData()同时上传文件类型和JSON数据
    重装系统后笔记本电脑无线wifi怎么连接
    DSS Dockerfile 单体
  • 原文地址:https://blog.csdn.net/tujidi1csd/article/details/126867525