###前提・実現したいこと
Androidでネット上のmp4ファイルをストリーミング再生したいと考えています。MediaPlayerでSurfaceViewに投影する方法を用いました。プロトコルはhttpです。
###発生している問題・エラーメッセージ
再生することには成功しているのですが5~10分立つと以下のエラーで再生が停止します。
W/MediaHTTPConnection: readAt 24551039 / 24961 => java.net.ProtocolException: unexpected end of stream E/MediaPlayer: error (1, -1004) E/MediaPlayer: Error (1,-1004) E/MediaPlayer: error (1, -1004) E/MediaPlayer: Error (1,-1004)
###該当のソースコード
こちら を参照して作成しました。(ほぼそのままですが)
Java
1 2public class SurfacePlayer extends Activity implements SurfaceHolder.Callback ,MediaController.MediaPlayerControl{ 3 private static final String TAG = "VideoPlayer"; 4 5 private SurfaceHolder mHolder; 6 private SurfaceView mPreview; 7 private MediaPlayer mMediaPlayer = null; 8 private MediaController mMediaController; 9 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 super.onCreate(savedInstanceState); 13 setContentView(R.layout.surfaceplayer); 14 15 mPreview = (SurfaceView) findViewById(R.id.surface); 16 mHolder = mPreview.getHolder(); 17 mHolder.addCallback(this); 18 19 // MediaPlayerを利用する 20 mMediaPlayer = new MediaPlayer(); 21 // MediaControllerを利用する 22 mMediaController = new MediaController(this); 23 mMediaController.setMediaPlayer(this); 24 mMediaController.setAnchorView(mPreview); 25 26 mPreview.setOnClickListener(new View.OnClickListener() { 27 @Override 28 public void onClick(View view) { 29 if(mMediaController.isShowing()){ 30 mMediaController.hide(); 31 }else{ 32 mMediaController.show(); 33 } 34 } 35 }); 36 37 38 } 39 40 public boolean onDestroy(MediaPlayer mp, int what, int extra) { 41 Log.d(TAG, "onDestroy"); 42 if (mp != null) { 43 mp.release(); 44 mp = null; 45 } 46 return false; 47 } 48 49 @Override 50 public void surfaceCreated(SurfaceHolder paramSurfaceHolder) { 51 Log.d(TAG, "surfaceCreated"); 52 // URLの先にある動画を再生する 53 Uri mediaPath = Uri.parse("http://xxxxx.com/xxxx.mp4"); 54 try { 55 mMediaPlayer.setDataSource(this, mediaPath); 56 mMediaPlayer.setDisplay(paramSurfaceHolder); 57 mMediaPlayer.prepare(); 58 mMediaPlayer.start(); 59 } catch (IllegalArgumentException e) { 60 e.printStackTrace(); 61 } catch (IllegalStateException e) { 62 e.printStackTrace(); 63 } catch (IOException e) { 64 e.printStackTrace(); 65 } 66 67 } 68 69 @Override 70 public void surfaceChanged(SurfaceHolder paramSurfaceHolder, int paramInt1, 71 int paramInt2, int paramInt3) { 72 } 73 74 @Override 75 public void surfaceDestroyed(SurfaceHolder paramSurfaceHolder) { 76 Log.d(TAG, "surfaceDestroyed"); 77 if (mMediaPlayer != null) { 78 mMediaPlayer.release(); 79 mMediaPlayer = null; 80 } 81 } 82 83 // ここから先はMediaController向け -------------------------- 84 @Override 85 public boolean dispatchKeyEvent(KeyEvent event) { 86 Log.d(TAG, "KeyCode:"+ event.getKeyCode()); 87 if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) { 88 if (!mMediaController.isShowing()){ 89 mMediaController.show(); 90 } else { 91 mMediaController.hide(); 92 } 93 } 94 return super.dispatchKeyEvent(event); 95 } 96 @Override 97 public void start() { 98 mMediaPlayer.start(); 99 } 100 @Override 101 public void pause() { 102 mMediaPlayer.pause(); 103 } 104 @Override 105 public int getDuration() { 106 return mMediaPlayer.getDuration(); 107 } 108 @Override 109 public int getCurrentPosition() { 110 return mMediaPlayer.getCurrentPosition(); 111 } 112 @Override 113 public void seekTo(int pos) { 114 mMediaPlayer.seekTo(pos); 115 } 116 @Override 117 public boolean isPlaying() { 118 return mMediaPlayer.isPlaying(); 119 } 120 @Override 121 public int getBufferPercentage() { 122 return 0; 123 } 124 @Override 125 public boolean canPause() { 126 return true; 127 } 128 @Override 129 public boolean canSeekBackward() { 130 return true; 131 } 132 @Override 133 public boolean canSeekForward() { 134 return true; 135 } 136 @Override 137 public int getAudioSessionId() { 138 return 0; 139 } 140}
###試したこと
このページに書いてある
Java
1System.setProperty("http.keepAlive", "false");
を追加する方法を試してみましたが変化がありませんでした。
stack overflowもあさってみましたが、同じような質問は未解決状態でした。
また、動画のコーデックや相手サーバー、ネットワークの問題かと思ったため、
ローカルに動作テスト用に立ててあるApacheサーバーのフォルダにh.264でエンコードしたmp4を突っ込んで試しましたが、同じエラーが発生しました。
###VideoViewでの挙動
動画を再生する他の方法としてVideoViewを使用する方法がありますが、こちらも5~10分再生した後「動画は再生できません」とダイアログが表示されます。
###テスト環境
Nexus6(2014) Android7.0
エミュレーター Android6.0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。