媒体播放器 prepare() 方法上的 IllegalStateException
IllegalStateException on mediaplayer prepare() method
我正在使用 SurfaceView
和 MediaPlayer
从 RTSP
流式传输视频,而 MJPEG 两种协议都独立工作,即当我仅从 RTSP
或 MJPEG over HTTP
只有。我遇到的问题是当我尝试从 MJPEG 协议切换到其他协议时 prepare()
方法抛出 IllegalStateException
。
对于 RTSP 流,我使用 MediaPlayer
class,因为它默认支持 RTSP
流。对于 MJPEG
,我有一个调用 HTTP url 和 returns JPEG
的 AsyncTask,我用它来设置 SurfaceView
s SurfaceHolder
Canvas
。当我尝试解锁 SurfaceHolder
Canvas
时,我认为问题出在某个地方
当我尝试将流从 MJPEG 更改为 RTSP 时的第一步:
MjpegThread.isRunning = false;
mediaPlayer.release();
mediaPlayer = null;
setMediaPlayer();
MjpegThread
是发出 HTTP
请求并在停止 AsyncTask
后更新 SurfaceHolder
的 Canvas
我调用的 doInBackground
方法结束
surfaceHolder.unlockCanvasAndPost(canvas);
该过程的最后一步是显示 RTSP 流,这是我的代码:
mediaPlayer.setDisplay(vidHolder);
mediaPlayer.setDataSource(OZOptions.RTSP_URL);
mediaPlayer.prepare(); // <- IllegalStateException HERE
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
上面的代码在我最初使用 RTSP
机器人时有效,但在我从 MJPEG
切换到 RTSP
时无效。
unlockCanvasAndPost
用于通过软件渲染到 Surface。 MediaPlayer 想要将帧直接发送到 Surface。由于 Android 的 Surface class 的限制,一旦您执行了软件渲染,您就无法对 Surface 执行任何其他操作。 (如果 Surface 上已经附加了其他东西,您也无法进行软件渲染。)
您没有在问题中显示 logcat 输出,但这是一个很常见的问题。 (这类似于人们询问在播放视频后擦除 SurfaceView Surface 的其他问题,例如 this one。)
您有两个选择:
使用多个 SurfaceView。将视频播放到一个,将 MJPEG 帧写入另一个,并使非活动的透明。使用 setZOrderMediaOverlay()
将一个放在另一个之上。
使用 SurfaceView 的两个部分。使用 invalidate()
和 onDraw()
渲染您的 MJPEG,就像 custom View。这类似于 #1 但可能更有效,因为自定义视图可以硬件加速。完成 MJPEG 后,将视图清除为透明以显示表面内容。
您还可以使用单独的自定义视图,并使用 FrameLayout 将其与 SurfaceView 重叠。
我正在使用 SurfaceView
和 MediaPlayer
从 RTSP
流式传输视频,而 MJPEG 两种协议都独立工作,即当我仅从 RTSP
或 MJPEG over HTTP
只有。我遇到的问题是当我尝试从 MJPEG 协议切换到其他协议时 prepare()
方法抛出 IllegalStateException
。
对于 RTSP 流,我使用 MediaPlayer
class,因为它默认支持 RTSP
流。对于 MJPEG
,我有一个调用 HTTP url 和 returns JPEG
的 AsyncTask,我用它来设置 SurfaceView
s SurfaceHolder
Canvas
。当我尝试解锁 SurfaceHolder
Canvas
当我尝试将流从 MJPEG 更改为 RTSP 时的第一步:
MjpegThread.isRunning = false;
mediaPlayer.release();
mediaPlayer = null;
setMediaPlayer();
MjpegThread
是发出 HTTP
请求并在停止 AsyncTask
后更新 SurfaceHolder
的 Canvas
我调用的 doInBackground
方法结束
surfaceHolder.unlockCanvasAndPost(canvas);
该过程的最后一步是显示 RTSP 流,这是我的代码:
mediaPlayer.setDisplay(vidHolder);
mediaPlayer.setDataSource(OZOptions.RTSP_URL);
mediaPlayer.prepare(); // <- IllegalStateException HERE
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
上面的代码在我最初使用 RTSP
机器人时有效,但在我从 MJPEG
切换到 RTSP
时无效。
unlockCanvasAndPost
用于通过软件渲染到 Surface。 MediaPlayer 想要将帧直接发送到 Surface。由于 Android 的 Surface class 的限制,一旦您执行了软件渲染,您就无法对 Surface 执行任何其他操作。 (如果 Surface 上已经附加了其他东西,您也无法进行软件渲染。)
您没有在问题中显示 logcat 输出,但这是一个很常见的问题。 (这类似于人们询问在播放视频后擦除 SurfaceView Surface 的其他问题,例如 this one。)
您有两个选择:
使用多个 SurfaceView。将视频播放到一个,将 MJPEG 帧写入另一个,并使非活动的透明。使用
setZOrderMediaOverlay()
将一个放在另一个之上。使用 SurfaceView 的两个部分。使用
invalidate()
和onDraw()
渲染您的 MJPEG,就像 custom View。这类似于 #1 但可能更有效,因为自定义视图可以硬件加速。完成 MJPEG 后,将视图清除为透明以显示表面内容。
您还可以使用单独的自定义视图,并使用 FrameLayout 将其与 SurfaceView 重叠。