2014-07-23 153 views
3

我有MediaPlayer渲染視頻到TextureView。這是行得通的。MediaPlayer無法渲染到圖像渲染後的TextureView

現在,我想在此TextureView上顯示靜態圖像一段時間,然後獲取MediaPlayer將視頻渲染到相同的TextureView

這裏是我的代碼來呈現位圖:

Canvas canvas = mTextureView.lockCanvas(); 
canvas.drawBitmap(sourceBitmap, matrix, new Paint()); 
mTextureView.unlockCanvasAndPost(canvas); 

在此之後,任何嘗試播放視頻導致ERROR_INVALID_OPERATION(1-38)被從視頻播放器觸發。

我試着評論打電話給drawBitmap,並且錯誤仍然發生。看起來簡單的調用lockCanvas後跟unlockCanvasAndPost的行爲導致TextureView不適合MediaPlayer使用。

是否有某種方法可以將TextureView重置爲允許MediaPlayer使用它的狀態?

我正在使用Android 4.2.2。

回答

8

由於Android應用程序框架的限制(至少Android 4.4以上版本),您無法執行此操作。

TextureView底層的SurfaceTexture是一個緩衝區使用者。 MediaPlayer是緩衝區生成器的一個例子,Canvas是另一個例子。一旦你附加了一個製作人,你必須先分離它,然後才能附加第二個製作人。

問題在於無法分離基於軟件的(Canvas)緩衝區生產者。可能有,但不是。所以一旦你用Canvas畫畫,你就會陷入困境。 (有關於此效果的說明here。)

可以分離GLES生產者。例如,在Grafika的視頻播放器類中,您可以找到一個使用GLES將表面清除爲黑色的方法clearSurface()。請注意,EGL上下文和窗口是在方法範圍內創建並顯式釋放的。您可以擴展該方法來顯示圖像。

+0

如果我有一個MediaPlayer作爲緩衝區製作者,那麼將我的表面清除爲黑色最簡單的方法是什麼? – Gilbert

+0

@Gilbert:你應該把它當作一個新問題發佈。解決這個問題的方法通常有三種形式:(1)讓MediaPlayer去做,也許是通過播放單幀黑色視頻; (2)斷開MediaPlayer,用GLES清除它,重新連接MediaPlayer; (3)在它前面放置一個不透明的黑色視圖,其尺寸相同。第三個是TextureView相當簡單,因爲與SurfaceView不同,它與其他視圖很好。 – fadden

+0

@fadden我們可以使用兩種方法在SurfaceView上繪製位圖,只需使用Canvas.drawBitmap()API並使用opengl手動繪製即可。兩者都是硬件加速,但速度更快? 我覺得用opengl手動繪圖需要內存複製,我們首先應該使用texImage2D API將位圖上傳到紋理。 – dragonfly

0

我最近遇到類似問題。我的意圖是直接將視頻縮略圖顯示到TextureView,然後使用相同的TextureView播放視頻,而不使用另一個ImageView來顯示視頻縮略圖。

我在@ fadden的評論中實現了第二種方法,使用EGL將視頻縮略圖繪製到相同的TextureView中。

另外,我們還可以使用GLSurfaceView中的兩個紋理來實現相同的目標。一個外部OES紋理播放連續視頻,另一個2D紋理顯示視頻縮略圖。

完整的演示可以在這個github項目中找到EGLPoster

希望這對任何到達這裏的人都有幫助。