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 npm install_npm install不构建供应商可执行文件

TL; DR&#xff1a;为什么npm不构建依赖项的二进制可执行文件&#xff0c;如何在没有显式构建它们的情况下构建它们&#xff1f;我的项目在常规的package.json中描述了它的依赖项 . 当我运行 npm install 时&#xff0c;所有软件包都按预期安装在node_modules中 . 但是&#xf…

JDBC第三次学习

这是我的JDBC第三次学习了&#xff0c;在学习的过程中&#xff0c;老是会忘掉一些知识&#xff0c;不记下笔记实在不行啊&#xff01; 使用JDBC调用存储过程 (1)关于如何使用Navicat(11.1.13) for MySQL如何创建存储过程。我在另一篇文章写过&#xff0c;在此不赘述了。 使用Na…

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…

Java中lastValue_在Logstash中为sql_last_value使用表的ID?

我jdbc在logstash输入的插件中有这样的MySQL语句。statement > "SELECT * from TEST where id > :sql_last_value"我的表没有任何date或datetime字段。因此&#xff0c;我尝试通过使用来检查scheduler每一分钟&#xff0c;以更新索引&#xff0c;是否在表中添加…

ssm中java实现树状结构_java ssm使用递归写树形结构

实体类:private String dspId;private String parentId; //父类idprivate String dataName;private Integer sortingNumber;private String remarks;private Date createTime;private Date updateTime;private Date deleteTime;private Integer dataFlag;private Integer anId…

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;会很容易出现…

Git 单机版

简介&#xff1a; Git 是一款开源的分布式版本控制系统&#xff0c;是当今最流行、先进的版本控制软件&#xff0c;没有之一。 Git 是一个分布式的版本控制系统&#xff0c;相反 SVN 就是一个集中式的版本控制系统了。SVN 每修改完一个文件要提交到服务端进行保存&#xff0c;而…

java中的Attribute类_java培训技术ModelAttribute注解修饰POJO类型的入参

RequestMapping(“/testModelAttribute”)//public String testModelAttribute(User user){public String testModelAttribute(ModelAttribute(“abc”) User user){System.out.println(“修改 user”user);return “success”;}/*** ModelAttribute 注解也可以来修饰目标方法 …

php a链接怎么传id_PHP函数参数的传递

PHP 支持两种参数传递方式&#xff0c;分别是按值传递(默认)和按引用传递。另外&#xff0c;PHP 还支持默认参数和可变长度参数列表。参数传递方式在调用函数时需要向函数传递参数&#xff0c;被传入的参数称作实参&#xff0c;而函数定义的参数为形参。PHP 中函数参数传递有 2…

VMware converte报错记录

物理机&#xff1a;centos7.2虚拟化&#xff1a;esxi6.0在进行P2V的时候&#xff0c;尝试了最新的VMware converte6.1及5.5均失败告终。最后在VMware converte6.0中解决迁移问题。转载于:https://blog.51cto.com/bigpi/1758352

php时区问题,PHP中遇到的时区问题解决方法

最近在学习PHP过程中发现PHP中的格式化时间戳比北京时间晚了8个小时&#xff0c;上网搜索发现原来是时区不对&#xff0c;解决办法是&#xff1a;1、永久修改更改php.ini文件中的data.timezone PRC 这是中国时间。重启Apache服务后生效。2、临时修改在使用格式化输入时间之前…

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…

iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数

iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的,>main>set_private>iw_get_priv_info获取wireless网卡所能处理的所有wlan_private_args类型.dev_ioctl>wext_…

PHP登录表单提交前端验证,form表单提交前先用ajax进行验证(前端)

确 定var csrfToken Yii::$app->request->csrfToken?>;var reg /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;var regNum /^\d{6}$/;function check_form() {n false;//全局变量&#xff0c;以便下面做判断var dirversNum $(#dirversNum).val();var archivesNu…

用鼠标去控制物体移动的方法

using UnityEngine; using System.Collections;public class hero : MonoBehaviour {private bool isMouseDown false;private Vector3 lastMousePositionVector3.zero;void Update () {PlayerControler();}public void PlayerControler(){//将像素位置转换成世界坐标轴的位置…

php获取flash上传视频文件大小,如何获取flash文件(.swf文件)的长度和宽度

Flash文件一般是可以缩放的&#xff0c;但缩放显示会一影响flash的效果&#xff0c;比如动作变慢或变快。要想以最佳状态显示&#xff0c;就需要获取flash文件的长度和宽度&#xff0c;因此要使用方法&#xff1a;引入该文件Require(‘swfheader.class.php’);创建一个类的实例…

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

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