android 跨进程多实例播放demo

2019独角兽企业重金招聘Python工程师标准>>> hot3.png


客户端进程需要实现,其中notify方法需要service 跨进程调用,通知客户端播放消息

IMediaPlayerClient.aidl

package com.example.demo;

import com.example.demo.ParcelableParcel;

interface IMediaPlayerClient {
         void notify(int msg, int ext1, int ext2, in ParcelableParcel obj);

}

public class MediaPlayerClientBn extends IMediaPlayerClient.Stub implements
        IMediaDeathNotifier {

// 其中重要的方法

    public void init() {
        this.mLock = new ReentrantLock();
        this.mNotifyLock = new ReentrantLock();
        this.mSignal = this.mLock.newCondition();
        mPlayer = null;
        mListener = null;
        mCookie = null;
        mStreamType = 3 /* TODO AUDIO_STREAM_MUSIC */;
        mAudioAttributesParcel = null;
        mCurrentPosition = -1;
        mSeekPosition = -1;
        mCurrentState = MEDIA_PLAYER_IDLE;
        mPrepareSync = false;
        mPrepareStatus = MediaErrorsNum.NO_ERROR;
        mLoop = false;
        mLeftVolume = mRightVolume = 1.0f;
        mVideoWidth = mVideoHeight = 0;
        mLockThreadId = 0;
        mAudioSessionId = 0;
        /*
         * TODO mAudioSessionId = AudioSystem::newAudioUniqueId();
         * AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
         */
        mSendLevel = 0;
        mRetransmitEndpointValid = false;
    }


    int attachNewPlayer(IMediaPlayer player) {
        Log.i(LOG_TAG, "attachNewPlayer");
        int err = MediaErrorsNum.UNKNOWN_ERROR;
        IMediaPlayer p;
        { // scope for the lock
            mLock.lock();

            if (( 0 == (mCurrentState & MEDIA_PLAYER_IDLE)) || (mCurrentState == MEDIA_PLAYER_STATE_ERROR)) {
                Log.e(LOG_TAG, "attachNewPlayer called in state = "
                        + mCurrentState);
                return MediaErrorsNum.INVALID_OPERATION;
            }

            clear_l();
            p = mPlayer;
            mPlayer = player;
            Log.i(LOG_TAG, "mPlayer is "+mPlayer.toString());
            if (player != null) {
                mCurrentState = MEDIA_PLAYER_INITIALIZED;
                err = MediaErrorsNum.NO_ERROR;
            } else {
                Log.e(LOG_TAG, "Unable to create media player");
            }
            mLock.unlock();
        }

        if (p != null) {
            try {
                p.disconnect();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return err;
    }

//获得getRemoteMediaPlayerServiceInstance,创建IMediaPlayer,并且使得

IMediaPlayer 和IMediaPlayerClient 实例一一对应,互相引用。 并且用MediaDeathNotifier

通知service 的生命周期。

    public int setDataSource(final IMediaHTTPService httpService, String url,
            final HashMap<String, String> headers) {
        mAudioSessionId ++;
        int err = MediaErrorsNum.BAD_VALUE;
        Log.i(LOG_TAG, "setDataSource(" + url + ")");
        try {

            if (url != null) {
                IMyMediaPlayerService service;

/*                service = MediaDeathNotifier.getMediaPlayerService();*/
                service = MediaPlayer_Surface_iadl_MultThread_TestBase.getRemoteMediaPlayerServiceInstance();

                if (service != null) {
                    IMediaPlayer player = (service
                            .create(this, mAudioSessionId));
                    if ((MediaErrorsNum.NO_ERROR != doSetRetransmitEndpoint(player))
                            || (MediaErrorsNum.NO_ERROR != player
                                    .setDataSource(httpService, url, null/* TODO */))) {
                        player = null;
                    }
                    err = attachNewPlayer(player);
                }
            }
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return err;
    }

//prepare

    public int prepare() {

        Log.i(LOG_TAG, "prepare()");
        mLock.lock();
        mLockThreadId = (int) Thread.currentThread().getId();
        if (mPrepareSync) {
            mLockThreadId = 0;
            return MediaErrorsNum.EALREADY;
        }
        mPrepareSync = true;
        int ret = MediaErrorsNum.NO_ERROR;
        try {
            ret = prepareAsync_l();
        } catch (RemoteException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        if (ret != MediaErrorsNum.NO_ERROR) {
            mLockThreadId = 0;
            return ret;
        }

        if (mPrepareSync) {
            try {

                mSignal.await();

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } // wait for prepare done
            mPrepareSync = false;
        }
        Log.i(LOG_TAG, "prepare complete - status= " + mPrepareStatus);
        mLockThreadId = 0;
        mLock.unlock();
        return mPrepareStatus;
    }

    private int prepareAsync_l() throws RemoteException {
        if ((mPlayer != null)&& (mCurrentState & (MediaPlayerClientBn.MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED)) != 0) {
            Log.i(LOG_TAG,"mCurrentState is MEDIA_PLAYER_INITIALIZED or MEDIA_PLAYER_STOPPED");
            if (mAudioAttributesParcel != null) {
                mPlayer.setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES,
                        ParcelableParcel.CREATOR
                                .createFromParcel(mAudioAttributesParcel));
            } else {
                mPlayer.setAudioStreamType(mStreamType);
            }
            mCurrentState = MEDIA_PLAYER_PREPARING;

            return mPlayer.prepareAsync();
        }
        Log.i(LOG_TAG, "prepareAsync called in state = " + mCurrentState);
        return MediaErrorsNum.INVALID_OPERATION;

    }

// start play

    public int start() {
        Log.i(LOG_TAG, "start()");

        int ret = MediaErrorsNum.NO_ERROR;
        mLock.lock();

        mLockThreadId = Thread.currentThread().getId();

        if ((mCurrentState & MEDIA_PLAYER_STARTED) == 1) {
            ret = MediaErrorsNum.NO_ERROR;
        } else if ((mPlayer != null)&& ((mCurrentState & (MEDIA_PLAYER_PREPARED| MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED)) != 0)) {
            try {
                mPlayer.setLooping(mLoop);

                mPlayer.setVolume(mLeftVolume, mRightVolume);
                mPlayer.setAuxEffectSendLevel(mSendLevel);
                mCurrentState = MEDIA_PLAYER_STARTED;
                ret = mPlayer.start();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if (ret != MediaErrorsNum.NO_ERROR) {
                mCurrentState = MEDIA_PLAYER_STATE_ERROR;
            } else {
                if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
                    Log.i(LOG_TAG,
                            "playback completed immediately following start()");
                }
            }
        } else {
            Log.e(LOG_TAG, "start called in state " + mCurrentState);
            ret = MediaErrorsNum.INVALID_OPERATION;
        }

        mLockThreadId = 0;
        mLock.unlock();
        return ret;
    }


// 消息传递

   @Override
    public void notify(int msg, int ext1, int ext2, ParcelableParcel obj)
            throws RemoteException {
        // TODO Auto-generated method stub
        
        Log.i(LOG_TAG,"message received msg=%d, ext1=%d, ext2=%d"+msg+":"+ext1+":"+ ext2);
            boolean send = true;
            boolean locked = false;
        
            // TODO: In the future, we might be on the same thread if the app is
            // running in the same process as the media server. In that case,
            // this will deadlock.
            //
            // The threadId hack below works around this for the care of prepare,
            // seekTo and start within the same process.
            // FIXME: Remember, this is a hack, it's not even a hack that is applied
            // consistently for all use-cases, this needs to be revisited.
            if (mLockThreadId != Thread.currentThread().getId()) {
                mLock.lock();
                locked = true;
            }
        
            // Allows calls from JNI in idle state to notify errors
            if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == null) {
                Log.i(LOG_TAG,"notify(%d, %d, %d) callback on disconnected mediaplayer :"+msg+":"+ext1+":"+ext2);
                if (locked) mLock.unlock();   // release the lock when done.
                return;
            }
        
            switch (msg) {
            case MEDIA_NOP: // interface test message
                break;
            case MEDIA_PREPARED:
                Log.i(LOG_TAG,"prepared");
                mCurrentState = MEDIA_PLAYER_PREPARED;
                if (mPrepareSync) {
                    Log.i(LOG_TAG,"signal application thread");
                    mPrepareSync = false;
                    mPrepareStatus = MediaErrorsNum.NO_ERROR;
                    mSignal.signal();
                }
                break;
            case MEDIA_PLAYBACK_COMPLETE:
                Log.i(LOG_TAG,"playback complete");
                if (mCurrentState == MEDIA_PLAYER_IDLE) {
                    Log.e(LOG_TAG,"playback complete in idle state");
                }
                if (!mLoop) {
                    mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
                }
                break;
            case MEDIA_ERROR:
                // Always log errors.
                // ext1: Media framework error code.
                // ext2: Implementation dependant error code.
                Log.e(LOG_TAG,"error (%d, %d)"+":"+ext1+":"+ ext2);
                mCurrentState = MEDIA_PLAYER_STATE_ERROR;
                if (mPrepareSync)
                {
                    Log.i(LOG_TAG,"signal application thread");
                    mPrepareSync = false;
                    mPrepareStatus = ext1;
                    mSignal.signal();
                    send = false;
                }
                break;
            case MEDIA_INFO:
                // ext1: Media framework error code.
                // ext2: Implementation dependant error code.
                if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
                    Log.w(LOG_TAG,"info/warning (%d, %d)"+":"+ext1+":"+ ext2);
                }
                break;
            case MEDIA_SEEK_COMPLETE:
                Log.i(LOG_TAG,"Received seek complete");
                if (mSeekPosition != mCurrentPosition) {
                    Log.i(LOG_TAG,"Executing queued seekTo(%d) "+mSeekPosition);
                    mSeekPosition = -1;
                    seekTo_l(mCurrentPosition);
                }
                else {
                    Log.i(LOG_TAG,"All seeks complete - return to regularly scheduled program");
                    mCurrentPosition = mSeekPosition = -1;
                }
                break;
            case MEDIA_BUFFERING_UPDATE:
                Log.i(LOG_TAG,"buffering %d"+ ext1);
                break;
            case MEDIA_SET_VIDEO_SIZE:
                Log.i(LOG_TAG,"New video size %d x %d"+":"+ext1+":"+ ext2);
                mVideoWidth = ext1;
                mVideoHeight = ext2;
                break;
            case MEDIA_TIMED_TEXT:
                Log.i(LOG_TAG,"Received timed text message");
                break;
            case MEDIA_SUBTITLE_DATA:
                Log.i(LOG_TAG,"Received subtitle data message");
                break;
            case MEDIA_META_DATA:
                Log.i(LOG_TAG,"Received timed metadata message");
                break;
            default:
                Log.i(LOG_TAG,"unrecognized message: (%d, %d, %d) :"+ msg+":"+ext1+":"+ ext2);
                break;
            }
        
            MediaPlayerListener listener = mListener;
            if (locked) mLock.unlock();
        
            // this prevents re-entrant calls into client code
            if ((listener != null) && send) {
                mNotifyLock.lock();
                Log.i(LOG_TAG,"callback application");
                listener.notify(msg, ext1, ext2, null == obj?null:obj.getParcel());
                mNotifyLock.unlock();
            }

    }

}




IMyMediaPlayerService.aidl

package com.example.demo;


import com.example.demo.IMediaPlayer;
import com.example.demo.IMediaPlayerClient;
import com.example.demo.IOMX;
import com.example.demo.ICrypto;
import com.example.demo.IDrm;
import com.example.demo.IHDCP;
import com.example.demo.IMediaCodecList;


import android.view.Surface;

interface IMyMediaPlayerService {


        IMediaPlayer create(in IMediaPlayerClient client,  int audioSessionId);

        IOMX            getOMX();
        ICrypto         makeCrypto();
        IDrm            makeDrm();
        IHDCP           makeHDCP( boolean createEncryptionModule);
        IMediaCodecList getCodecList();
}

public class MyMediaPlayerService extends Service {
    private static final String LOG_TAG = MyMediaPlayerService.class.getName()
            + "";

    public static void instantiate() {
        Log.i(LOG_TAG, "instantiate call");
    }

    // For battery usage tracking purpose
    class BatteryUsageInfo {
        // how many streams are being played by one UID
        int refCount;
        // a temp variable to store the duration(ms) of audio codecs
        // when we start a audio codec, we minus the system time from
        // audioLastTime
        // when we pause it, we add the system time back to the audioLastTime
        // so after the pause, audioLastTime = pause time - start time
        // if multiple audio streams are played (or recorded), then
        // audioLastTime
        // = the total playing time of all the streams
        int audioLastTime;
        // when all the audio streams are being paused, we assign audioLastTime
        // to
        // this variable, so this value could be provided to the battery app
        // in the next pullBatteryData call
        int audioTotalTime;

        int videoLastTime;
        int videoTotalTime;
    };

    HashMap<Integer, BatteryUsageInfo> mBatteryData = null;

    private static final int SPEAKER = 0;
    private static final int OTHER_AUDIO_DEVICE = 1;
    private static final int SPEAKER_AND_OTHER = 2;
    private static final int NUM_AUDIO_DEVICES = 3;

 

    //

    ReentrantLock mLock = new ReentrantLock();
    Vector<SoftReference<MediaPlayerBn>> mClients = new Vector<SoftReference<MediaPlayerBn>>();
    int mNextConnId = 0;
    AtomicInteger tmp = new AtomicInteger(mNextConnId);
    IOMX mOMX;
    ICrypto mCrypto;

    @SuppressLint("NewApi")
    private final IMyMediaPlayerService.Stub mBinder = new IMyMediaPlayerService.Stub() {
// 创建与IMediaPlayerClient相对的IMediaPlayer,互粉并加入一个软引用向量管理对应关系。
        @Override
        public IMediaPlayer create(IMediaPlayerClient client, int audioSessionId)
                throws RemoteException {
            // TODO Auto-generated method stub

            long pid = Binder.getCallingPid();

            int connId = tmp.getAndIncrement();

            MediaPlayerBn c = new MediaPlayerBn(MyMediaPlayerService.this, pid,
                    connId, client, audioSessionId, Binder.getCallingUid());

            Log.i(LOG_TAG, "Create new client("+connId+") from pid "+pid+", uid "+getCallingUid()+", ");

            SoftReference<MediaPlayerBn> w = new SoftReference<MediaPlayerBn>(c);
            {
                mLock.lock();
                mClients.add(w);
                mLock.unlock();
            }
            return c;
        }

 }

}

IMediaPlayer.aidl:

package com.example.demo;

import android.view.Surface;
import com.example.demo.IMediaHTTPService;
import com.example.demo.AudioPlaybackRate;
import com.example.demo.AVSyncSettings;
import com.example.demo.ParcelableParcel;
import android.os.Messenger;
 

interface IMediaPlayer  {
        //void playLoadedVideo_iadl(in  Surface  surface);
        
 void            disconnect();

int        setDataSource(in IMediaHTTPService httpService, String url, String header /*HashMap<String,String> headers*/);

//int        setDataSource(int fd, long offset, long length);
//int        setDataSource(in  IStreamSource source);
//int        setDataSource(in  IDataSource source);
int        setVideoSurfaceTexture(in  Surface  surface);
int        prepareAsync();
int        start();
int        stop();
int        pause();
int        isPlaying(boolean state);
int        setPlaybackSettings(in  AudioPlaybackRate rate);
int        getPlaybackSettings(in  AudioPlaybackRate rate /* nonnull */);
int        setSyncSettings(in AVSyncSettings sync, float videoFpsHint);
int        getSyncSettings(in AVSyncSettings sync /* nonnull */,     float videoFps /* nonnull */);
int        seekTo(int msec) ;
int        getCurrentPosition(int msec);
int        getDuration(int msec);
int        reset();
/*typedef enum {
 
    AUDIO_STREAM_DEFAULT          = -1,
    AUDIO_STREAM_MIN              = 0,
    AUDIO_STREAM_VOICE_CALL       = 0,
    AUDIO_STREAM_SYSTEM           = 1,
    AUDIO_STREAM_RING             = 2,
    AUDIO_STREAM_MUSIC            = 3,
    AUDIO_STREAM_ALARM            = 4,
    AUDIO_STREAM_NOTIFICATION     = 5,
    AUDIO_STREAM_BLUETOOTH_SCO    = 6,
    AUDIO_STREAM_ENFORCED_AUDIBLE = 7,
    AUDIO_STREAM_DTMF             = 8,
    AUDIO_STREAM_TTS              = 9,  
    AUDIO_STREAM_BOOT              = 10,
    AUDIO_STREAM_VIBSPK            = 11,
    AUDIO_STREAM_ACCESSIBILITY    = 12,
    AUDIO_STREAM_REROUTING        = 13,
    AUDIO_STREAM_PATCH            = 14,
    AUDIO_STREAM_PUBLIC_CNT       = AUDIO_STREAM_VIBSPK + 1,
    AUDIO_STREAM_CNT              = AUDIO_STREAM_PATCH + 1,
} audio_stream_type_t;*/
int        setAudioStreamType(/*audio_stream_type_t type*/int type);
int        setLooping(boolean loop) ;
int        setVolume(float leftVolume, float rightVolume) ;
int        setAuxEffectSendLevel(float level);
int        attachAuxEffect(int effectId) ;
int        setParameter(int key,in ParcelableParcel request);
int        getParameter(int key,in  ParcelableParcel reply);
int        setRetransmitEndpoint0(String endpoint /*const struct sockaddr_in* endpoint*/);
int        getRetransmitEndpoint1(String endpoint /*struct sockaddr_in* endpoint*/);
int        setNextPlayer(in IMediaPlayer next);


int        setMetadataFilter(in ParcelableParcel filter);


int        getMetadata(boolean update_only,   boolean apply_filter,in ParcelableParcel metadata);
 

}



package com.example.demo;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.concurrent.locks.ReentrantLock;

import android.annotation.SuppressLint;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Binder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;

@SuppressLint("NewApi")
public class MediaPlayerBn extends IMediaPlayer.Stub {
    private static final String LOG_TAG = MediaPlayerBn.class.getName();

    private static final int NO_INIT = 0;
    private static final int AUDIO_ATTRIBUTES_TAGS_MAX_SIZE = 64/* TODO */;

    class audio_attributes_t {
        /*
         * TODO audio_content_type_t content_type; audio_usage_t usage;
         * audio_source_t source; audio_flags_mask_t flags; char
         * tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; UTF8
         */
    };

    ReentrantLock mLock;
    /* MediaPlayerBase mPlayer; */
    MediaPlayer mPlayer;
    MyMediaPlayerService mService;
    IMediaPlayerClient mClient;
    AudioOutput mAudioOutput;
    int mPid;
    int mStatus;
    boolean mLoop;
    int mConnId;
    int mAudioSessionId;
    audio_attributes_t mAudioAttributes;
    long mUID;
    Surface mConnectedWindow;
    Binder mConnectedWindowBinder;
    String mRetransmitEndpoint;
    boolean mRetransmitEndpointValid;
    MediaPlayerBn mNextClient;

    // Metadata filters.
    /* media::Metadata::Filter */Object mMetadataAllow; // protected by mLock
    /* media::Metadata::Filter */Object mMetadataDrop; // protected by mLock

    // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
    // notification we try to update mMetadataUpdated which is a
    // set: no duplicate.
    // getMetadata clears this set.
    /* media::Metadata::Filter */Object mMetadataUpdated; // protected by mLock

    /*
     * TODO #if CALLBACK_ANTAGONIZER Antagonizer* mAntagonizer; #endif
     */

    Object mAntagonizer;
    OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
        
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 100, what, extra, null);
            return false;
        }
    };
    OnInfoListener  mInfoListener = new MediaPlayer.OnInfoListener() {
        
        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 200, what, extra, null);
            return false;
        }
    };
    OnBufferingUpdateListener  mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
        
        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 3, 3, percent, null);
        }
    };
    OnCompletionListener  mCompletionListener = new MediaPlayer.OnCompletionListener() {
        
        @Override
        public void onCompletion(MediaPlayer mp) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 2, 2, 0, null);
        }
    };
    
    OnPreparedListener  mPreparedListener = new MediaPlayer.OnPreparedListener() {
        
        @Override
        public void onPrepared(MediaPlayer mp) {
            // TODO Auto-generated method stub
            Log.i(LOG_TAG,"mPreparedListener.onPrepared() ");
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 1, 1, 0, null);
        }
    };
    OnSeekCompleteListener  mSeekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
        
        @Override
        public void onSeekComplete(MediaPlayer mp) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 4, 4, 0, null);
        }
    };
    OnVideoSizeChangedListener  mVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
        
        @Override
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            // TODO Auto-generated method stub
            MediaPlayerBn.this.notify(MediaPlayerBn.this, 5, 5, 0, null);
        }
    };
    public MediaPlayerBn(MyMediaPlayerService service, long pid, int connId,
            IMediaPlayerClient client, int audioSessionId, long uid) {
        Log.i(LOG_TAG, "Client(%d) constructor" + connId);
        mPid = (int) pid;
        mConnId = connId;
        mService = service;
        mClient = client;
        mLoop = false;
        mStatus = NO_INIT;
        mAudioSessionId = audioSessionId;
        mUID = uid;
        mRetransmitEndpointValid = false;
        mAudioAttributes = null;
        mLock = new ReentrantLock();
        Log.i(LOG_TAG, "create Antagonizer is null");
        mAntagonizer = null;
        mPlayer = new MediaPlayer();
        mPlayer.setOnErrorListener(mErrorListener);
        mPlayer.setOnInfoListener(mInfoListener);
        mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
        mPlayer.setOnCompletionListener(mCompletionListener);
        mPlayer.setOnPreparedListener(mPreparedListener);
        mPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
        mPlayer.setOnVideoSizeChangedListener(mVideoSizeChangedListener);
    }

    public void desdroy() {
        Log.i(LOG_TAG, "Client(%d) destructor pid = %d" + mConnId + ":" + mPid);
        mAudioOutput = null;
        SoftReference<MediaPlayerBn> client = new SoftReference<MediaPlayerBn>(
                this);
        try {
            disconnect();
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

// destory 的时候删除引用

        mService.removeClient(client);

        if (mAudioAttributes != null) {
            /* TODO free(mAudioAttributes); */
            mAudioAttributes = null;
        }
    }


    @Override
    public void disconnect() throws RemoteException {
        // TODO Auto-generated method stub
        Log.i(LOG_TAG, "disconnect(%d) from pid %d" + mConnId + ":" + mPid);

        // grab local reference and clear main reference to prevent future
        // access to object
        MediaPlayer p;
        {
            mLock.lock();
            p = mPlayer;
            mLock.unlock();
        }
        mPlayer = null;

        // clear the notification to prevent callbacks to dead client
        // and reset the player. We assume the player will serialize
        // access to itself if necessary.
        if (p != null) {
            /* TODO p.setNotifyCallback(0, 0); */
            p.reset();
        }
        /* TODOdisconnectNativeWindow(); */

        /* TODO IPCThreadState::self()->flushCommands(); */
    }

    @Override
    public int setDataSource(IMediaHTTPService httpService, String url,
            String header) throws RemoteException {
        // TODO Auto-generated method stub

        Log.i(LOG_TAG, "setDataSource(%s) " + url);

        try {

            mPlayer.setDataSource(url);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return 0;

    }

}


客户端多实例调用

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.example.demo;

import java.io.IOException;
import java.util.logging.Logger;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

@SuppressLint("NewApi")
public class MediaPlayer_Surface_iadl_MultThread_TestBase extends Activity  {

    private static final String LOG_TAG = MediaPlayer_Surface_iadl_MultThread_TestBase.class
            .getName() + "liyl add";
    protected static final int SLEEP_TIME = 1000;
    protected static final int LONG_SLEEP_TIME = 6000;
    protected static final int STREAM_RETRIES = 1;
    protected static boolean sUseScaleToFitMode = false;



    /*
     * protected Monitor mOnVideoSizeChangedCalled = new Monitor(); protected
     * Monitor mOnVideoRenderingStartCalled = new Monitor(); protected Monitor
     * mOnBufferingUpdateCalled = new Monitor(); protected Monitor
     * mOnPrepareCalled = new Monitor(); protected Monitor mOnSeekCompleteCalled
     * = new Monitor(); protected Monitor mOnCompletionCalled = new Monitor();
     * protected Monitor mOnInfoCalled = new Monitor(); protected Monitor
     * mOnErrorCalled = new Monitor();
     */

    protected SurfaceHolder mSurfaceHolder1 = null;
    protected SurfaceHolder mSurfaceHolder2 = null;

    private SurfaceHolder mHolder1;
    private SurfaceHolder mHolder2;
    
    protected MediaPlayer_Surface_iadl_MultThread_TestBase mActivity;

    private boolean mIsRemoteBound = false;

    private static IMyMediaPlayerService mRemoteService = null;
    
    private MediaPlayerClientWrapper mPlayerWrapper1;
    private MediaPlayerClientWrapper mPlayerWrapper2;
    
    public static IMyMediaPlayerService getRemoteMediaPlayerServiceInstance() {
        if(mRemoteService == null) {
            Log.e(LOG_TAG,"not should be here!!!");
            return mRemoteService;
        }
        return mRemoteService;
    }
    
    protected class MediaPlayerClientWrapper implements MediaPlayerListener {
        public MediaPlayerClientWrapper() {
            super();
            this.mPlayerClient = new MediaPlayerClientBn();
        }

        private MediaPlayerClientBn mPlayerClient;
        
        public MediaPlayerClientBn getmPlayerClient() {
            return mPlayerClient;
        }
        @Override
        public void notify(int msg, int ext1, int ext2, Parcel obj) {
            // TODO Auto-generated method stub
            Log.e(LOG_TAG,"msg = "+msg+" ext1 = "+ext1+" ext2 = "+ext2+" obj = "+obj);
            if(msg == 1/*MEDIA_PREPARED*/) {
            mPlayerClient.start();
            }
        }
        public void desdroy() {
            this.mPlayerClient = null;
        }
        
    }
    



    private ServiceConnection mRemoteConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            mRemoteService = IMyMediaPlayerService.Stub.asInterface(service);
            Log.i(LOG_TAG,"mRemoteService == null is "+(mRemoteService == null));
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            mRemoteService = null;
        }
    };

    public MediaPlayer_Surface_iadl_MultThread_TestBase() {
        super();
    }

    protected void setUp() {
        mSurfaceHolder1 = getSurfaceHolder1();
        mSurfaceHolder2 = getSurfaceHolder2();

        if (!mIsRemoteBound) {


            Intent mIntent = new Intent();
            mIntent.setAction("com.example.demo.IMyMediaPlayerService");//你定义的service的action
            mIntent.setPackage(getPackageName());//这里你需要设置你应用的包名
            //startService(mIntent);


            bindService(mIntent,
                    mRemoteConnection, Context.BIND_AUTO_CREATE);
            mIsRemoteBound = !mIsRemoteBound;
        }
        mPlayerWrapper1 = new MediaPlayerClientWrapper();
        mPlayerWrapper2 = new MediaPlayerClientWrapper();
        mPlayerWrapper1.getmPlayerClient().setListener(mPlayerWrapper1);
        mPlayerWrapper2.getmPlayerClient().setListener(mPlayerWrapper2);
    }

    public SurfaceHolder getSurfaceHolder1() {
        return mHolder1;
    }
    public SurfaceHolder getSurfaceHolder2() {
        return mHolder2;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.mediaplayermultsurface);

        mActivity = this;

        SurfaceView surfaceV1 = (SurfaceView) findViewById(R.id.surface1);
        mHolder1 = surfaceV1.getHolder();
        SurfaceView surfaceV2 = (SurfaceView) findViewById(R.id.surface2);
        mHolder2 = surfaceV2.getHolder();

        setUp();

    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        tearDown();

    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();

        if(mRemoteService == null) {
            Log.w(LOG_TAG,"mRemoteService is null");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        mSurfaceHolder1.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub
                mSurfaceHolder1 = arg0;
            }

            @Override
            public void surfaceCreated(SurfaceHolder arg0) {
                // TODO Auto-generated method stub
                try {
                    
                    
                    mPlayerWrapper1.getmPlayerClient().setDataSource(null,"http://10.154.250.32:8081/share/mediatest/normal/hls/1080p/desc.m3u8", null);
                    mPlayerWrapper1.getmPlayerClient().setVideoSurfaceTexture(mActivity.getSurfaceHolder1()
                            .getSurface());
                    mPlayerWrapper1.getmPlayerClient().prepare();


                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder arg0) {
                // TODO Auto-generated method stub
                mSurfaceHolder1 = null;
            }

        });
 
        mSurfaceHolder2.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub
                mSurfaceHolder2 = arg0;
            }

            @Override
            public void surfaceCreated(SurfaceHolder arg0) {
                // TODO Auto-generated method stub
                try {


                    
                    
                    mPlayerWrapper2.getmPlayerClient().setDataSource(null,"http://10.154.250.32:8081/share/mediatest/normal/hls/1080p/desc.m3u8", null);
                    mPlayerWrapper2.getmPlayerClient().setVideoSurfaceTexture(mActivity.getSurfaceHolder2()
                            .getSurface());
                    mPlayerWrapper2.getmPlayerClient().prepare();


                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder arg0) {
                // TODO Auto-generated method stub
                mSurfaceHolder2 = null;
            }

        });
        
            Log.w(LOG_TAG,"Sleep 5 s");
/*            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/



    }
    private void clear() {
        mPlayerWrapper1.desdroy();
        mPlayerWrapper2.desdroy();
    }
    protected void tearDown() {
        clear();
        if (!mIsRemoteBound) {
            unbindService(mRemoteConnection);
            mIsRemoteBound = !mIsRemoteBound;
        }

    }



    // //

   



}

转载于:https://my.oschina.net/u/269082/blog/647380

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 获取service_Java service层获取HttpServletRequest工具类的方法

Java service层获取HttpServletRequest工具类的方法大家都知道 能在Controller/action层获取HttpServletRequest&#xff0c;但是这里给大家备份的是从代码内部service层获取HttpServletRequest工具类。具体如下&#xff1a;package com.base.common.sessionutils;import javax…

Linux使用jstat命令查看jvm的GC情况

2019独角兽企业重金招聘Python工程师标准>>> 命令格式 jstat命令命令格式&#xff1a; jstat [Options] vmid [interval] [count] 参数说明&#xff1a; Options&#xff0c;选项&#xff0c;我们一般使用 -gcutil 查看gc情况 vmid&#xff0c;VM的进程号&#x…

python写一段脚本代码自动完成输入(目录下的所有)文件的数据替换(修改数据和替换数据都是输入的)【转】...

转自&#xff1a;http://blog.csdn.net/lixiaojie1012/article/details/23628129 初次尝试python语言&#xff0c;感觉用着真舒服&#xff0c;简单明了&#xff0c;库函数一调用就OK了[python] view plain copy 在CODE上查看代码片派生到我的代码片 import sys,os,os.path de…

java混合分页_坑,MySQL中 order by 与 limit 混用,分页会出现问题!

在Mysql中我们常常用order by来进行排序&#xff0c;使用limit来进行分页&#xff0c;当需要先排序后分页时我们往往使用类似的写法select * from 表名 order by 排序字段 limt M,N。但是这种写法却隐藏着较深的使用陷阱。在排序字段有数据重复的情况下&#xff0c;会很容易出现…

OSG开发概览

1 OSG基础知识 OSG是Open Scene Graphic 的缩写&#xff0c;OSG于1997年诞生于以为滑翔机爱好者之手&#xff0c;Don burns 为了对滑翔机的飞行进行模拟&#xff0c;对openGL的库进行了封装&#xff0c;osg的雏形就这样诞生了&#xff0c;1998年Don burns 遇到了同样喜欢滑翔…

hbuilder php xdebug,Hbuilder使用xdebug配置php断点调试

2019独角兽企业重金招聘Python工程师标准>>>##1. 背景不得不说Hbuilder是免费的前端开发工具中比较好用的&#xff0c;而且配合aptana开发php也马马虎虎(毕竟写前端的时候多些)。本人原是搞java的&#xff0c;后来打算用php做些个人项目(因为服务器成本低)&#xff0c…

mx播放器有没有投屏功能_无线投屏、即插即用,投影仪其实可以更智能:明基 E580T...

无论是简单的办公室会议还是小型的线下活动&#xff0c;投影仪都是必不可少的利器&#xff1a;既能有不错的显示效果&#xff0c;也不用受屏幕尺寸的约束。尽管越来越多的智能电视可供电脑连接&#xff0c;但真正派上用场的时候&#xff0c;拎箱就走的投影仪显然是最佳选择。很…

特殊矩阵-对角矩阵

2019独角兽企业重金招聘Python工程师标准>>> 挖坑。 转载于:https://my.oschina.net/aslanjia/blog/651503

vs运行时候冒了这个错:无法启动IIS Express Web 服务器~Win10

后期会在博客首发更新&#xff1a;http://dnt.dkill.net 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 网上的方法多种&#xff0c;有让安装扩展插件的&#xff0c;有让在程序里面添加Http系列的组件&#xff0c;有其它其它的&#xff0c;可是。。。…

matlab脚本 定时停止_一触即发是什么软件?它是手机上极其强大的一款脚本辅助精灵...

一触即发app是手机上极其强大的一款免root的脚本辅助软件&#xff0c;堪称一键秒杀脚本精灵&#xff0c;除自动化、运行、管理外&#xff0c;还提供了脚本制作文字教程/视频教程&#xff0c;学习社区和图色处理、定时执行、王者荣耀、变量等命令参数和多点找色、多点找图、京东…

笔记本电脑处理器_高通提示低成本5G芯片更强大的笔记本电脑处理器

高通公司总裁克里斯蒂亚诺阿蒙(Cristiano Amon)在今天的柏林IFA贸易展览会的虚拟主题演讲中说&#xff0c;我们将很快看到更便宜的5G手机&#xff0c;以及更多具有更好应用兼容性的Windows-on-Snapdragon笔记本电脑。欧洲主要的电子产品展览会IFA今年被分成​​几个小组活动&am…

为什么6lowpan 要有四个地址_大型监控网络系统如何规划ip地址

本文转自网络对于监控项目来说&#xff0c;很多故障的原因都是跟ip地址设置不当有关&#xff0c;如ip冲突&#xff0c;或者有几路监控图像没有显示等&#xff0c;都是跟ip有一定关联&#xff0c;合理的分配ip地址十分重要。一、为什么要合理分配IP对于小型监控项目来说&#xf…

JAVA中的命令模式实例教程

原文链接 作者&#xff1a;Pankaj Kumar 译者&#xff1a;f0tlo <1357654289qq.com> 命令模式是一种行为模式&#xff0c;因此&#xff0c;它处理的是对象的行为。命令模式为系统中不同的对象提供中性化的交流媒介。根据GoF的定义&#xff0c;命令模式是&#xff1a; 通…

bugku 管理员系统 后台代码_不会吧,这也行?iOS后台锁屏监听摇一摇

[toc] 背景介绍 一般情况下&#xff0c;出于省电、权限、合理性等因素考虑&#xff0c;给人的感觉是很多奇怪的需求安卓可以实现&#xff0c;但是iOS就无法实现&#xff01;今天要介绍的需求也有这种感觉&#xff0c;就是“当 APP 处于后台或锁屏状态时&#xff0c;依旧可以监听…

windows php5.3升级,Windows10系统将PHPNOW升级PHP版本为5.3.5

Windows 10发布很久了&#xff0c;现在大多数人都在使用&#xff0c;在WIN10中使用PHPNOW&#xff0c;觉得自带的PHP版本有点低&#xff0c;所以就想升级下&#xff0c;在网上搜索了一些方法&#xff0c;然后结合自己的实际操作&#xff0c;在这里分享下。1、首先要下载PHP5.3.…

igs无法分配驱动器映射表_硬盘无法使用,用DiskPart进行分区和格式化,非常简单...

如果计算机硬盘出现问题&#xff0c;有时不是硬件上出现了错误&#xff0c;很可能只是逻辑上出现了问题&#xff0c;这时就可以使用DiskPart来快速解决。在Windows 10上&#xff0c;当外部存储(例如U盘、可移动硬盘或SD卡)由于数据损坏或其他问题而停止工作时&#xff0c;可以使…

硬件nat关闭还是开启_超能课堂(173):AfterBurner不止超频,还是绝佳的游戏伴侣...

微星AfterBurner软件可以说是一个相当好用的显卡工具&#xff0c;它好用的超频功能估计都不用我多说了吧&#xff1f;微星并没有把这款软件限制在自己品牌的显卡能用&#xff0c;各个品牌的显卡都能用&#xff0c;无论A卡还是N卡都可以用AfterBurner来超频&#xff0c;软件在超…

mx350显卡天梯图_CPU天梯图与显卡天梯图2020年最新版

最新CPU天梯图较之以往没有太大的变化&#xff0c;前十位置还是那几款。但是继阿里之后&#xff0c;腾讯也开始准备自己制作芯片了&#xff0c;毕竟自研AI芯片的诱惑还是很大的&#xff0c;2020年有不少的厂商都推出了新鲜美味的显卡&#xff0c;有些是老卡翻新做性价比。有的则…

matlab写字,Matlab实现鼠标写字代码

类型&#xff1a;编程工具大小&#xff1a;1.5M语言&#xff1a;中文 评分&#xff1a;1.2标签&#xff1a;立即下载最早的程序&#xff0c;实在忘了从哪里下载的了。能够实现鼠标的手写输入&#xff0c;但是一些不连续的点。tmouse.mfunction tmouse(action)% TMOUSE 本例展示…

from rfc 2068 hypertext怎么解决_你好,打工人!用英语怎么表达“打工人”?可别直接说 worker...

打工人&#xff0c;打工魂&#xff0c;打工人是人上人&#xff01;最近&#xff0c;「打工人」这个词火了&#xff01;几乎一夜之间&#xff0c;很多人在和朋友打招呼时&#xff0c;都自称“打工人”。那“打工人”是什么意思&#xff1f;这里的“打工人”&#xff0c;其实是对…