我正在使用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);
}
}
答案 0 :(得分:0)
考虑使用exoplayer
http://developer.android.com/guide/topics/media/exoplayer.html
它是根据文档中的流媒体构建的:
ExoPlayer支持MediaPlayer当前未提供的功能,包括HTTP上的动态自适应流媒体(DASH),SmoothStreaming和持久性缓存。 ExoPlayer可以扩展为处理其他媒体格式,因为您将其作为应用代码的一部分包含在内,您可以将其与应用一起更新。