คลาส TextureView คือออบเจ็กต์ View ที่รวม View เข้ากับ 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 มีบทบาทคล้ายกันและเป็นส่วนหนึ่งของ ลำดับชั้นของ View อย่างไรก็ตาม SurfaceView และ TextureView มีการใช้งานที่แตกต่างกัน SurfaceView ใช้พารามิเตอร์เดียวกับ View อื่นๆ แต่เนื้อหา SurfaceView จะโปร่งใสเมื่อแสดงผล
TextureView มีการจัดการอัลฟ่าและการหมุนที่ดีกว่า SurfaceView แต่ SurfaceView มีข้อดีด้านประสิทธิภาพเมื่อจัดองค์ประกอบองค์ประกอบ UI ที่ซ้อนทับ วิดีโอ เมื่อไคลเอ็นต์แสดงผลด้วย SurfaceView ไคลเอ็นต์จะได้รับเลเยอร์การจัดองค์ประกอบแยกต่างหาก จาก SurfaceView SurfaceFlinger จะสร้างเลเยอร์แยกต่างหากเป็นฮาร์ดแวร์โอเวอร์เลย์หากอุปกรณ์รองรับ เมื่อไคลเอ็นต์แสดงผลด้วย TextureView ชุดเครื่องมือ UI จะรวมเนื้อหาของ TextureView เข้ากับลำดับชั้นของ View ด้วย 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 รายการ ที่เล่นควบคู่กัน ซึ่งจำลองแอปการประชุมทางวิดีโอ เมื่อการวางแนว ของหน้าจอเปลี่ยนไปและกิจกรรมรีสตาร์ท ตัวถอดรหัส 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 เธรด
การใช้การถอดรหัสคู่ของ Grafika กับ SurfaceView นั้นยากกว่าการใช้กับ TextureView เนื่องจากออบเจ็กต์ SurfaceView จะทำลายพื้นผิว ระหว่างการเปลี่ยนการวางแนว นอกจากนี้ การใช้ออบเจ็กต์ SurfaceView ยังเพิ่มเลเยอร์ 2 ชั้น ซึ่งไม่เหมาะเนื่องจากข้อจำกัดเกี่ยวกับจำนวนการซ้อนทับ ที่พร้อมใช้งานในฮาร์ดแวร์