พื้นผิวพื้นผิว

SurfaceTexture คือการผสมผสานระหว่างพื้นผิวและพื้นผิว OpenGL ES (GLES) อินสแตนซ์ SurfaceTexture ใช้เพื่อจัดเตรียมพื้นผิวที่ส่งออกไปยังพื้นผิว GLES

SurfaceTexture มีอินสแตนซ์ของ BufferQueue ที่แอปเป็นผู้บริโภค โทรกลับ onFrameAvailable() จะแจ้งเตือนแอปเมื่อผู้ผลิตเข้าคิวบัฟเฟอร์ใหม่ จากนั้น แอปจะเรียก updateTexImage() ซึ่งจะปล่อยบัฟเฟอร์ที่เก็บไว้ก่อนหน้านี้ รับบัฟเฟอร์ใหม่จากคิว และทำการเรียก EGL เพื่อให้บัฟเฟอร์พร้อมใช้งานสำหรับ GLES ในรูปแบบพื้นผิวภายนอก

พื้นผิว GLES ภายนอก

พื้นผิว GLES ภายนอก ( GL_TEXTURE_EXTERNAL_OES ) แตกต่างจากพื้นผิว GLES แบบดั้งเดิม ( GL_TEXTURE_2D ) ในลักษณะต่อไปนี้:

  • พื้นผิวภายนอกจะแสดงรูปหลายเหลี่ยมที่มีพื้นผิวโดยตรงจากข้อมูลที่ได้รับจาก BufferQueue
  • ตัวแสดงพื้นผิวภายนอกได้รับการกำหนดค่าแตกต่างจากตัวแสดงพื้นผิว GLES แบบดั้งเดิม
  • พื้นผิวภายนอกไม่สามารถทำกิจกรรมพื้นผิว GLES แบบดั้งเดิมได้ทั้งหมด

ประโยชน์หลักของพื้นผิวภายนอกคือความสามารถในการเรนเดอร์โดยตรงจากข้อมูล BufferQueue อินสแตนซ์ SurfaceTexture ตั้งค่าแฟล็กการใช้งานของผู้บริโภคเป็น GRALLOC_USAGE_HW_TEXTURE เมื่อสร้างอินสแตนซ์ BufferQueue สำหรับพื้นผิวภายนอก เพื่อให้แน่ใจว่า GLES จะจดจำข้อมูลในบัฟเฟอร์ได้

เนื่องจากอินสแตนซ์ SurfaceTexture โต้ตอบกับบริบท EGL แอปจึงสามารถเรียกใช้เมธอดของมันได้เท่านั้น ในขณะที่บริบท EGL ที่เป็นเจ้าของพื้นผิวนั้นเป็นปัจจุบันบนเธรดการเรียก สำหรับข้อมูลเพิ่มเติม โปรดดูเอกสารประกอบคลาส SurfaceTexture

การประทับเวลาและการเปลี่ยนแปลง

อินสแตนซ์ SurfaceTexture ประกอบด้วยเมธอด getTimeStamp() ซึ่งดึงข้อมูลการประทับเวลา และเมธอด getTransformMatrix() ซึ่งดึงข้อมูลเมทริกซ์การแปลง การเรียก updateTexImage() จะตั้งค่าทั้งการประทับเวลาและเมทริกซ์การแปลง แต่ละบัฟเฟอร์ที่ BufferQueue ส่งผ่านจะมีพารามิเตอร์การแปลงและการประทับเวลา

พารามิเตอร์การแปลงมีประโยชน์สำหรับประสิทธิภาพ ในบางกรณี ข้อมูลต้นฉบับอาจอยู่ในการวางแนวที่ไม่ถูกต้องสำหรับผู้ใช้ทั่วไป แทนที่จะหมุนเวียนข้อมูลก่อนที่จะส่งไปยังผู้บริโภค ให้ส่งข้อมูลในทิศทางที่มีการแปลงที่แก้ไข เมทริกซ์การแปลงสามารถรวมเข้ากับการแปลงอื่น ๆ ได้เมื่อใช้ข้อมูล เพื่อลดค่าใช้จ่ายให้เหลือน้อยที่สุด

การประทับเวลามีประโยชน์สำหรับแหล่งบัฟเฟอร์ที่ขึ้นอยู่กับเวลา ตัวอย่างเช่น เมื่อ setPreviewTexture() เชื่อมต่ออินเทอร์เฟซของผู้ผลิตเข้ากับเอาต์พุตของกล้อง คุณจะสามารถใช้เฟรมจากกล้องเพื่อสร้างวิดีโอได้ แต่ละเฟรมจะต้องมีการประทับเวลาการนำเสนอจากเวลาที่เฟรมถูกจับ ไม่ใช่เวลาที่แอปได้รับเฟรม รหัสกล้องจะตั้งค่าการประทับเวลาที่มาพร้อมกับบัฟเฟอร์ ส่งผลให้ชุดการประทับเวลาสอดคล้องกันมากขึ้น

กรณีศึกษา: การจับภาพอย่างต่อเนื่องของ Grafika

การจับภาพอย่างต่อเนื่องของ Grafika เกี่ยวข้องกับการบันทึกเฟรมจากกล้องของอุปกรณ์และการแสดงเฟรมเหล่านั้นบนหน้าจอ หากต้องการบันทึกเฟรม ให้สร้างพื้นผิวด้วยเมธอด createInputSurface() ของคลาส MediaCodec แล้วส่งพื้นผิวไปยังกล้อง หากต้องการแสดงเฟรม ให้สร้างอินสแตนซ์ของ SurfaceView และส่งพื้นผิวไปที่ setPreviewDisplay() โปรดทราบว่าการบันทึกเฟรมและการแสดงพร้อมกันนั้นเป็นกระบวนการที่เกี่ยวข้องมากกว่า

กิจกรรม การถ่ายภาพต่อเนื่อง จะแสดงวิดีโอจากกล้องในขณะที่กำลังบันทึกวิดีโอ ในกรณีนี้ วิดีโอที่เข้ารหัสจะถูกเขียนลงในบัฟเฟอร์แบบวงกลมในหน่วยความจำซึ่งสามารถบันทึกลงในดิสก์ได้ตลอดเวลา

โฟลว์นี้เกี่ยวข้องกับคิวบัฟเฟอร์สามคิว:

  • App — แอปใช้อินสแตนซ์ SurfaceTexture เพื่อรับเฟรมจากกล้อง โดยแปลงเป็นพื้นผิว GLES ภายนอก
  • SurfaceFlinger — แอปประกาศอินสแตนซ์ SurfaceView เพื่อแสดงเฟรม
  • MediaServer — กำหนดค่าตัวเข้ารหัส MediaCodec ด้วยพื้นผิวอินพุตเพื่อสร้างวิดีโอ

ในภาพด้านล่าง ลูกศรแสดงถึงการแพร่กระจายข้อมูลจากกล้อง อินสแตนซ์ BufferQueue เป็นแบบสี (ตัวสร้างเป็นสีน้าน ส่วนผู้บริโภคเป็นสีเขียว)

กิจกรรมการจับภาพต่อเนื่องของ Grafika

รูปที่ 1 กิจกรรมการจับอย่างต่อเนื่องของ Grafika

วิดีโอ H.264 ที่เข้ารหัสจะไปที่บัฟเฟอร์แบบวงกลมใน RAM ในกระบวนการของแอป เมื่อผู้ใช้กดปุ่มจับภาพ คลาส MediaMuxer จะเขียนวิดีโอที่เข้ารหัสลงในไฟล์ MP4 บนดิสก์

อินสแตนซ์ BufferQueue ทั้งหมดได้รับการจัดการด้วยบริบท EGL เดียวในแอป ในขณะที่ดำเนินการ GLES บนเธรด UI การจัดการข้อมูลที่เข้ารหัส (การจัดการบัฟเฟอร์แบบวงกลมและการเขียนลงดิสก์) จะดำเนินการบนเธรดที่แยกจากกัน

เมื่อใช้คลาส SurfaceView การโทรกลับของ surfaceCreated() จะสร้างอินสแตนซ์ EGLContext และ EGLSurface สำหรับจอแสดงผลและตัวเข้ารหัสวิดีโอ เมื่อมีเฟรมใหม่มาถึง SurfaceTexture จะดำเนินการสี่กิจกรรม:
  1. รับเฟรม.
  2. ทำให้กรอบพร้อมใช้งานเป็นพื้นผิว GLES
  3. เรนเดอร์เฟรมด้วยคำสั่ง GLES
  4. ส่งต่อการแปลงและการประทับเวลาสำหรับแต่ละอินสแตนซ์ของ EGLSurface

เธรดตัวเข้ารหัสจะดึงเอาต์พุตที่เข้ารหัสจาก MediaCodec และเก็บไว้ในหน่วยความจำ

การเล่นวิดีโอพื้นผิวที่ปลอดภัย

Android รองรับการประมวลผลหลัง GPU ของเนื้อหาวิดีโอที่มีการป้องกัน ซึ่งช่วยให้แอปใช้ GPU สำหรับเอฟเฟกต์วิดีโอที่ซับซ้อนและไม่เชิงเส้น (เช่น การบิดงอ) การแมปเนื้อหาวิดีโอที่ได้รับการป้องกันบนพื้นผิวเพื่อใช้ในฉากกราฟิกทั่วไป (เช่น การใช้ GLES) และความเป็นจริงเสมือน (VR)

การเล่นวิดีโอพื้นผิวที่ปลอดภัย

รูปที่ 2 การเล่นวิดีโอพื้นผิวที่ปลอดภัย

การสนับสนุนเปิดใช้งานโดยใช้ส่วนขยายสองรายการต่อไปนี้:

  • ส่วนขยาย EGL — ( EGL_EXT_protected_content ) ช่วยให้สามารถสร้างบริบทและพื้นผิว GL ที่ได้รับการป้องกัน ซึ่งสามารถดำเนินการกับเนื้อหาที่มีการป้องกันได้
  • ส่วนขยาย GLES — ( GL_EXT_protected_textures ) เปิดใช้งานการแท็กพื้นผิวที่มีการป้องกัน เพื่อให้สามารถใช้เป็นไฟล์แนบพื้นผิวเฟรมบัฟเฟอร์ได้

Android เปิดใช้งาน SurfaceTexture และ ACodec ( libstagefright.so ) เพื่อส่งเนื้อหาที่มีการป้องกัน แม้ว่าพื้นผิวของหน้าต่างจะไม่เข้าคิวกับ SurfaceFlinger และจัดเตรียมพื้นผิววิดีโอที่ได้รับการป้องกันเพื่อใช้ภายในบริบทที่ได้รับการป้องกัน สิ่งนี้ทำได้โดยการตั้งค่าบิตผู้บริโภคที่ได้รับการป้องกัน ( GRALLOC_USAGE_PROTECTED ) บนพื้นผิวที่สร้างขึ้นในบริบทที่ได้รับการป้องกัน (ตรวจสอบโดย ACodec)

การเล่นวิดีโอพื้นผิวที่ปลอดภัยจะวางรากฐานสำหรับการนำ DRM ไปใช้ในสภาพแวดล้อม OpenGL ES หากไม่มีการนำ DRM มาใช้อย่างเข้มงวด เช่น Widevine ระดับ 1 ผู้ให้บริการเนื้อหาหลายรายจะไม่อนุญาตให้เรนเดอร์เนื้อหาที่มีมูลค่าสูงของตนในสภาพแวดล้อม OpenGL ES ซึ่งจะป้องกันกรณีการใช้งาน VR ที่สำคัญ เช่น การรับชมเนื้อหาที่มีการป้องกัน DRM ใน VR

AOSP มีโค้ดเฟรมเวิร์กสำหรับการเล่นวิดีโอพื้นผิวที่ปลอดภัย การสนับสนุนไดรเวอร์ขึ้นอยู่กับ OEM ผู้ใช้อุปกรณ์ต้องใช้ส่วนขยาย EGL_EXT_protected_content และ GL_EXT_protected_textures extensions เมื่อใช้ไลบรารีตัวแปลงสัญญาณของคุณเอง (เพื่อแทนที่ libstagefright ) ให้สังเกตการเปลี่ยนแปลงใน /frameworks/av/media/libstagefright/SurfaceUtils.cpp ที่อนุญาตให้บัฟเฟอร์ที่ทำเครื่องหมายด้วย GRALLOC_USAGE_PROTECTED ถูกส่งไปยัง ANativeWindow (แม้ว่า ANativeWindow จะไม่เข้าคิวโดยตรงไปยัง window composer) ตราบใดที่บิตการใช้งานของผู้บริโภคมี GRALLOC_USAGE_PROTECTED สำหรับเอกสารโดยละเอียดเกี่ยวกับการใช้ส่วนขยาย โปรดดูที่รีจิสทรี Khronos ( EGL_EXT_protected_content และ GL_EXT_protected_textures )