3

我正在使用 android 手机在延迟容忍网络上进行视频流处理。对于那个我试图根据袖珍旅程给出的教程来实现渐进式视频下载

http://blog.infidian.com/2008/04/04/tutorial-custom-media-streaming-for-androids-mediaplayer/

在创建新的媒体播放器时,prepareAsync 函数会阻止视频显示,使流式传输无法忍受。有没有办法在媒体播放器准备好时显示一些东西?

我正在使用 SurfaceView 和 SUrfaceHolder 来显示 API 媒体演示中建议的视频。

private MediaPlayer createMediaPlayer(File mediaFile)
throws IOException {
    MediaPlayer mPlayer = new MediaPlayer();
    mPlayer.setOnErrorListener(
            new MediaPlayer.OnErrorListener() {
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    Log.e(TAG, "Error in MediaPlayer: (" + what +") with extra (" +extra +")" );
                    return true;
                }
            });

    //  It appears that for security/permission reasons, it is better to pass a FileDescriptor rather than a direct path to the File.
    //  Also I have seen errors such as "PVMFErrNotSupported" and "Prepare failed.: status=0x1" if a file path String is passed to
    //  setDataSource().  So unless otherwise noted, we use a FileDescriptor here.
    FileInputStream fis = new FileInputStream(mediaFile);
    mPlayer.setDataSource(fis.getFD());
    mPlayer.setDisplay(holder);
    mPlayer.prepareAsync();
    return mPlayer;
}

/**
 * Transfer buffered data to the MediaPlayer.
 * NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so 
 * this method should always be called using a Handler.
 */  
private void transferBufferToMediaPlayer() {
    try {
        // First determine if we need to restart the player after transferring data...e.g. perhaps the user pressed pause
        final boolean wasPlaying = mediaPlayer.isPlaying();
        final int curPosition = mediaPlayer.getCurrentPosition();
        Log.e(TAG, "Current position: "+curPosition);
        final MediaPlayer temp = mediaPlayer;

        // Copy the currently downloaded content to a new buffered File.  Store the old File for deleting later. 
        File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".dat");
        File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat");

        //  This may be the last buffered File so ask that it be delete on exit.  If it's already deleted, then this won't mean anything.  If you want to 
        // keep and track fully downloaded files for later use, write caching code and please send me a copy.
        bufferedFile.deleteOnExit();   
        moveFile(downloadingMediaFile,bufferedFile);

        // Pause the current player now as we are about to create and start a new one.  So far (Android v1.5),
        // this always happens so quickly that the user never realized we've stopped the player and started a new one
        if(wasPlaying){
            Log.e(TAG, "mediaPlayer paused");
            mediaPlayer.pause();
        }
        //mediaPlayer.release();

        // Create a new MediaPlayer rather than try to re-prepare the prior one.
        mediaPlayer = createMediaPlayer(bufferedFile);

        mediaPlayer.setOnPreparedListener(
                new MediaPlayer.OnPreparedListener() {

                    @Override
                    public void onPrepared(MediaPlayer mPlayer) {
                        // TODO Auto-generated method stub
                        mediaPlayer.seekTo(curPosition);

                        //  Restart if at end of prior buffered content or mediaPlayer was previously playing.  
                        //  NOTE:  We test for < 1second of data because the media player can stop when there is still
                        //  a few milliseconds of data left to play
                        int mediaLength = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition();
                        boolean atEndOfFile = mediaLength >= 1000;
                        Log.e(TAG, "MediaLen:"+mediaLength);
                        if (wasPlaying || atEndOfFile){
                            Log.e(TAG, "starting new player");
                            temp.release();
                            mediaPlayer.start();
                        }
                    }
                });


        // Lastly delete the previously playing buffered File as it's no longer needed.
        oldBufferedFile.delete();

    }catch (Exception e) {
        Log.e(TAG, "Error updating to newly loaded content.", e);                   
    }
}
4

1 回答 1

0

考虑使用 exoplayer

http://developer.android.com/guide/topics/media/exoplayer.html

它在构建时考虑了文档中的流式传输:

ExoPlayer 支持 MediaPlayer 当前未提供的功能,包括基于 HTTP 的动态自适应流式传输 (DASH)、SmoothStreaming 和持久缓存。ExoPlayer 可以扩展以处理其他媒体格式,并且因为您将其作为应用程序代码的一部分包含在内,您可以将其与您的应用程序一起更新。

于 2015-04-25T05:29:37.750 回答