คลาส TextureView
คือออบเจ็กต์มุมมองที่รวมมุมมองกับ SurfaceTexture
แสดงผลด้วย OpenGL ES
ออบเจ็กต์ TextureView จะห่อหุ้ม SurfaceTexture โดยตอบกลับการเรียกกลับและ
รับบัฟเฟอร์ใหม่ เมื่อออบเจ็กต์ TextureView ได้บัฟเฟอร์ใหม่ TextureView
จะส่งคำขอให้ลบล้างมุมมองและวาดโดยใช้เนื้อหาของบัฟเฟอร์ล่าสุด
เป็นแหล่งข้อมูล ซึ่งจะแสดงผลทุกที่และทุกเมื่อตามที่สถานะมุมมอง
ระบุ
OpenGL ES (GLES) สามารถ
แสดงผลบนออบเจ็กต์ TextureView ได้โดยการส่ง
SurfaceTexture ไปยังการเรียกการสร้าง EGL แต่การทำเช่นนี้จะทำให้เกิดปัญหา เมื่อ GLES
แสดงผลใน TextureView ผู้ผลิตและผู้ใช้ BufferQueue จะอยู่ในเธรดเดียวกัน
ซึ่งอาจทำให้การเรียกใช้การสลับบัฟเฟอร์หยุดชะงักหรือล้มเหลว ตัวอย่างเช่น หาก
โปรดิวเซอร์ส่งบัฟเฟอร์หลายรายการติดต่อกันอย่างรวดเร็วจากเทรด UI การเรียกใช้การสลับบัฟเฟอร์ EGL จะต้องนำบัฟเฟอร์ออกจากคิว BufferQueue อย่างไรก็ตาม เนื่องจากผู้บริโภคและผู้ผลิตอยู่ในเธรดเดียวกัน จึงจะไม่มีบัฟเฟอร์
และจะทำให้การเรียกใช้การสลับค้างหรือล้มเหลว
BufferQueue ต้องมีบัฟเฟอร์พร้อมใช้งานเสมอสำหรับการนำออกจากคิวเพื่อป้องกันไม่ให้การสลับบัฟเฟอร์หยุดชะงัก โดย BufferQueue จะทิ้งเนื้อหาของบัฟเฟอร์ที่ได้มาก่อนหน้านี้เมื่อมีการจัดคิวบัฟเฟอร์ใหม่ นอกจากนี้ ยังกำหนดข้อจำกัดเกี่ยวกับจำนวนบัฟเฟอร์ขั้นต่ำและสูงสุดเพื่อป้องกันไม่ให้ผู้ใช้ใช้บัฟเฟอร์ทั้งหมดพร้อมกัน
เลือก SurfaceView หรือ TextureView
SurfaceView และ TextureView มีบทบาทคล้ายกันและเป็นส่วนหนึ่งของ ลำดับชั้นการแสดงผล อย่างไรก็ตาม SurfaceView และ TextureView มีการใช้งานที่แตกต่างกัน
SurfaceView ออบเจ็กต์ใช้พารามิเตอร์เดียวกับวิวอื่นๆ แต่เนื้อหา SurfaceView จะโปร่งใสเมื่อแสดงผล
TextureView มีการจัดการอัลฟ่าและการหมุนที่ดีกว่า SurfaceView แต่
SurfaceView มีข้อได้เปรียบด้านประสิทธิภาพเมื่อคอมโพสิตองค์ประกอบ UI ที่ซ้อนทับ
วิดีโอ เมื่อไคลเอ็นต์แสดงผลด้วยออบเจ็กต์ SurfaceView SurfaceView จะจัดหาเลเยอร์การคอมโพสแยกต่างหากให้กับไคลเอ็นต์ SurfaceFlinger จะสร้างเลเยอร์แยกเป็นโอเวอร์เลย์ฮาร์ดแวร์หากอุปกรณ์รองรับ เมื่อไคลเอ็นต์แสดงผลด้วย TextureView ชุดเครื่องมือ UI จะคอมโพสิตเนื้อหาของออบเจ็กต์ TextureView ลงในลำดับชั้นการแสดงผลด้วย GPU การอัปเดตเนื้อหาอาจทำให้องค์ประกอบมุมมองอื่นๆ วาดใหม่ เช่น หากมุมมองอื่นๆ อยู่เหนือ TextureView หลังจากที่การแสดงผลวิวเสร็จสมบูรณ์แล้ว SurfaceFlinger จะรวมเลเยอร์ UI ของแอปและเลเยอร์อื่นๆ ทั้งหมด เพื่อให้พิกเซลที่มองเห็นได้ทุกพิกเซลได้รับการรวม 2 ครั้ง
กรณีศึกษา: วิดีโอเล่นของ Grafika
วิดีโอเพลเยอร์ของ Grafika มีวิดีโอเพลเยอร์ 2 ตัว ตัวหนึ่ง
ใช้ TextureView และอีกตัวใช้ SurfaceView ส่วนการถอดรหัสวิดีโอของกิจกรรมจะส่งเฟรมจาก MediaCodec ไปยัง Surface สำหรับทั้ง TextureView และ SurfaceView ความแตกต่างที่สำคัญที่สุดระหว่างการติดตั้งใช้งานคือขั้นตอนที่จำเป็นในการแสดงสัดส่วนภาพที่ถูกต้อง
การปรับขนาด SurfaceView ต้องมีการติดตั้งใช้งาน FrameLayout ที่กำหนดเอง
WindowManager ต้องส่งค่าตำแหน่งและขนาดใหม่ของหน้าต่างไปยัง SurfaceFlinger
การปรับขนาด SurfaceTexture ของออบเจ็กต์ TextureView ต้องกำหนดค่าเมทริกซ์การเปลี่ยนรูปแบบด้วย TextureView#setTransform()
หลังจากแสดงสัดส่วนภาพที่ถูกต้องแล้ว การติดตั้งใช้งานทั้ง 2 แบบจะใช้รูปแบบเดียวกัน
เมื่อ SurfaceView หรือ TextureView สร้าง Surface โค้ดของแอป
จะเปิดใช้การเล่น เมื่อผู้ใช้แตะเล่น ระบบจะเริ่มเธรดการถอดรหัสวิดีโอโดยมี Surface เป็นเป้าหมายเอาต์พุต หลังจากนั้น โค้ดของแอปจะไม่ทำอะไรเลย โดย SurfaceFlinger (สำหรับ SurfaceView) หรือ TextureView จะจัดการการเขียนและการแสดงผล
กรณีศึกษา: การถอดรหัส 2 ชั้นของ Grafika
Double Decode ของ Grafika แสดงให้เห็นการดัดแปลง SurfaceTexture ภายใน TextureView
Double Decode ของ Grafika ใช้ออบเจ็กต์ TextureView 2 รายการเพื่อแสดงวิดีโอ 2 รายการ
ที่เล่นควบคู่กัน ซึ่งจำลองแอปการประชุมทางวิดีโอ เมื่อการวางแนว
ของหน้าจอเปลี่ยนไปและกิจกรรมรีสตาร์ท ตัวถอดรหัส MediaCodec จะไม่
หยุดทำงาน ซึ่งจำลองการเล่นสตรีมวิดีโอแบบเรียลไทม์ ไคลเอ็นต์ควรเปิดพื้นผิวไว้เพื่อปรับปรุงประสิทธิภาพ
Surface คือแฮนเดิลของอินเทอร์เฟซ Producer
ใน BufferQueue ของ SurfaceTexture เนื่องจากออบเจ็กต์ TextureView จัดการ SurfaceTexture ไคลเอ็นต์จึงต้องรักษา SurfaceTexture ให้ใช้งานได้เพื่อรักษาพื้นผิวให้ใช้งานได้
Double Decode ของ Grafika จะรับข้อมูลอ้างอิงไปยัง SurfaceTexture จากออบเจ็กต์ TextureView และบันทึกไว้ในฟิลด์แบบคงที่เพื่อรักษา SurfaceTexture ให้ใช้งานได้
จากนั้น Double Decode ของ Grafika จะส่งคืน false จาก
TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed() ไปยัง
เพื่อป้องกันไม่ให้ SurfaceTexture เสียหาย TextureView จากนั้นจะส่ง
SurfaceTexture ไปยัง onSurfaceTextureDestroyed() ซึ่งสามารถ
คงไว้ได้เมื่อมีการเปลี่ยนแปลงการกำหนดค่ากิจกรรม ซึ่งไคลเอ็นต์จะส่งไปยัง
ออบเจ็กต์ TextureView ใหม่ผ่าน setSurfaceTexture()
เธรดแยกจะขับเคลื่อนตัวถอดรหัสวิดีโอแต่ละตัว Mediaserver จะส่งบัฟเฟอร์ที่มีเอาต์พุตที่ ถอดรหัสแล้วไปยัง SurfaceTexture ซึ่งเป็นผู้ใช้ BufferQueue ออบเจ็กต์ TextureView จะทำการแสดงผลและดำเนินการในเธรด UI
การใช้ Double Decode ของ Grafika กับ SurfaceView นั้นยากกว่าการใช้กับ TextureView เนื่องจากออบเจ็กต์ SurfaceView จะทำลายพื้นผิว
ระหว่างการเปลี่ยนการวางแนว นอกจากนี้ การใช้วัตถุ SurfaceView จะเพิ่มเลเยอร์ 2 ชั้น ซึ่งไม่เหมาะเนื่องจากข้อจำกัดเกี่ยวกับจำนวนภาพซ้อน
ที่พร้อมใช้งานในฮาร์ดแวร์