使用Android媒体播放器进行渐进式视频下载

3
我正在使用安卓手机研究延迟容忍网络上的视频流媒体。为此,我正在尝试根据Pocket Journey提供的教程实现渐进式视频下载。

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);                   
    }
}
1个回答

0

考虑使用ExoPlayer

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

从文档来看,它是以流式传输为主要考虑因素构建的:

ExoPlayer 支持目前由 MediaPlayer 不支持的功能,包括动态自适应流媒体(DASH)、SmoothStreaming 和持久性缓存。ExoPlayer 可以扩展以处理其他媒体格式,而且因为你将它包含在应用代码中,所以可以随着应用程序一起更新。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接