SurfaceTexture

SurfaceTexture là sự kết hợp giữa một nền tảng và một kết cấu OpenGL ES (GLES). Các thực thể SurfaceTexture được dùng để cung cấp các vùng hiển thị xuất ra kết cấu GLES.

SurfaceTexture chứa một thực thể của BufferQueue mà ứng dụng là đối tượng sử dụng. Lệnh gọi lại onFrameAvailable() sẽ thông báo cho các ứng dụng khi nhà sản xuất đưa một vùng đệm mới vào hàng đợi. Sau đó, các ứng dụng sẽ gọi updateTexImage(), thao tác này sẽ giải phóng bộ đệm đã giữ trước đó, lấy bộ đệm mới từ hàng đợi và thực hiện các lệnh gọi EGL để cung cấp bộ đệm cho GLES dưới dạng một hoạ tiết bên ngoài.

Kết cấu GLES bên ngoài

Kết cấu GLES bên ngoài (GL_TEXTURE_EXTERNAL_OES) khác với kết cấu GLES tiêu chuẩn (GL_TEXTURE_2D) ở những điểm sau:

  • Các hoạ tiết bên ngoài kết xuất các đa giác có hoạ tiết trực tiếp từ dữ liệu nhận được từ BufferQueue.
  • Trình kết xuất kết cấu bên ngoài được định cấu hình khác với trình kết xuất kết cấu GLES tiêu chuẩn.
  • Các hoạ tiết bên ngoài không thể thực hiện tất cả các hoạt động hoạ tiết GLES tiêu chuẩn.

Lợi ích chính của các hoạ tiết bên ngoài là khả năng kết xuất trực tiếp từ dữ liệu BufferQueue. Các phiên bản SurfaceTexture đặt cờ sử dụng của người dùng thành GRALLOC_USAGE_HW_TEXTURE khi tạo các phiên bản BufferQueue cho các hoạ tiết bên ngoài để xác minh rằng GLES có thể nhận dạng dữ liệu trong vùng đệm.

Vì các thực thể SurfaceTexture tương tác với một ngữ cảnh EGL, nên ứng dụng chỉ có thể gọi các phương thức của thực thể này trong khi ngữ cảnh EGL sở hữu hoạ tiết hiện tại trên luồng gọi. Để biết thêm thông tin, hãy xem tài liệu về lớp SurfaceTexture.

Dấu thời gian và các phép biến đổi

Các thực thể SurfaceTexture bao gồm phương thức getTimeStamp() (truy xuất dấu thời gian) và phương thức getTransformMatrix() (truy xuất ma trận biến đổi). Khi gọi updateTexImage(), bạn sẽ đặt cả dấu thời gian và ma trận biến đổi. Mỗi vùng đệm mà BufferQueue truyền sẽ bao gồm các tham số biến đổi và dấu thời gian.

Các thông số biến đổi rất hữu ích để tăng hiệu quả. Trong một số trường hợp, dữ liệu nguồn có thể có hướng không phù hợp với người tiêu dùng. Thay vì xoay dữ liệu trước khi gửi cho người dùng, hãy gửi dữ liệu theo hướng của dữ liệu đó bằng một phép biến đổi để điều chỉnh. Ma trận biến đổi có thể được hợp nhất với các phép biến đổi khác khi dữ liệu được sử dụng, giúp giảm thiểu chi phí phát sinh.

Dấu thời gian hữu ích cho các nguồn bộ đệm phụ thuộc vào thời gian. Ví dụ: khi setPreviewTexture() kết nối giao diện của nhà sản xuất với đầu ra của camera, các khung hình từ camera có thể được dùng để tạo video. Mỗi khung hình cần có dấu thời gian trình chiếu kể từ thời điểm khung hình được ghi lại, chứ không phải kể từ thời điểm ứng dụng nhận được khung hình. Mã máy ảnh đặt dấu thời gian được cung cấp cùng với vùng đệm, dẫn đến một chuỗi dấu thời gian nhất quán hơn.

Nghiên cứu điển hình: Tính năng chụp liên tục của Grafika

Tính năng chụp liên tục của Grafika liên quan đến việc ghi lại các khung hình từ camera của thiết bị và hiển thị các khung hình đó trên màn hình. Để ghi lại khung hình, hãy tạo một nền tảng bằng phương thức createInputSurface() của lớp MediaCodec rồi chuyển nền tảng đó đến camera. Để hiển thị khung hình, hãy tạo một thực thể của SurfaceView và truyền nền tảng đó đến setPreviewDisplay(). Xin lưu ý rằng việc ghi lại khung hình và hiển thị chúng cùng một lúc là một quy trình phức tạp hơn.

Hoạt động chụp liên tục hiển thị video từ camera trong khi video đang được quay. Trong trường hợp này, video được mã hoá sẽ được ghi vào một vùng đệm vòng trong bộ nhớ và có thể được lưu vào ổ đĩa bất cứ lúc nào.

Quy trình này bao gồm 3 hàng đợi đệm:

  • App – Ứng dụng dùng một thực thể SurfaceTexture để nhận các khung hình từ camera, chuyển đổi các khung hình đó thành một hoạ tiết GLES bên ngoài.
  • SurfaceFlinger – Ứng dụng khai báo một thực thể SurfaceView để hiển thị các khung hình.
  • MediaServer – Định cấu hình bộ mã hoá MediaCodec bằng một bề mặt đầu vào để tạo video.

Trong hình sau, các mũi tên cho biết quá trình truyền dữ liệu từ camera. Các phiên bản BufferQueue sẽ xuất hiện, với các chỉ báo trực quan phân biệt nhà sản xuất (màu xanh mòng két) với người tiêu dùng (màu xanh lục).

Hoạt động chụp liên tục của Grafika

Hình 1. Hoạt động chụp liên tục của Grafika

Video được mã hoá H.264 sẽ chuyển đến một vùng đệm vòng trong RAM trong quy trình ứng dụng. Khi người dùng nhấn nút chụp, lớp MediaMuxer sẽ ghi video đã mã hoá vào một tệp MP4 trên đĩa.

Tất cả các thực thể BufferQueue đều được xử lý bằng một ngữ cảnh EGL duy nhất trong ứng dụng trong khi các thao tác GLES được thực hiện trên luồng giao diện người dùng. Việc xử lý dữ liệu được mã hoá (quản lý bộ đệm vòng và ghi dữ liệu đó vào ổ đĩa) được thực hiện trên một luồng riêng biệt.

Khi sử dụng lớp SurfaceView, lệnh gọi lại surfaceCreated() sẽ tạo các thực thể EGLContextEGLSurface cho màn hình và bộ mã hoá video. Khi một khung hình mới đến, SurfaceTexture sẽ thực hiện 4 hoạt động:

  1. Thu nhận khung hình.
  2. Cung cấp khung hình dưới dạng cấu trúc bề mặt GLES.
  3. Kết xuất khung hình bằng các lệnh GLES.
  4. Chuyển tiếp phép biến đổi và dấu thời gian cho từng phiên bản của EGLSurface.

Sau đó, luồng bộ mã hoá sẽ kéo đầu ra đã mã hoá từ MediaCodec và lưu trữ đầu ra đó trong bộ nhớ.

Phát video có kết cấu bảo mật

Android hỗ trợ hoạt động xử lý hậu kỳ GPU đối với nội dung video được bảo vệ. Điều này cho phép các ứng dụng sử dụng GPU cho các hiệu ứng video phức tạp, phi tuyến tính (chẳng hạn như hiệu ứng biến dạng), ánh xạ nội dung video được bảo vệ lên các hoạ tiết để sử dụng trong các cảnh đồ hoạ chung (ví dụ: sử dụng GLES) và thực tế ảo (VR).

Phát video kết cấu bảo mật

Hình 2. Phát video có kết cấu bảo mật

Tính năng hỗ trợ được bật bằng cách sử dụng 2 tiện ích sau:

  • Tiện ích EGL – (EGL_EXT_protected_content) Cho phép tạo các ngữ cảnh và nền tảng GL được bảo vệ, cả hai đều có thể hoạt động trên nội dung được bảo vệ.
  • Tiện ích GLES – (GL_EXT_protected_textures) Cho phép gắn thẻ các hoạ tiết là được bảo vệ để có thể dùng làm tệp đính kèm hoạ tiết bộ đệm khung.

Android cho phép SurfaceTexture và ACodec (libstagefright.so) gửi nội dung được bảo vệ ngay cả khi bề mặt của cửa sổ không xếp hàng vào SurfaceFlinger và cung cấp một bề mặt video được bảo vệ để sử dụng trong một bối cảnh được bảo vệ. Việc này được thực hiện bằng cách đặt bit người dùng được bảo vệ (GRALLOC_USAGE_PROTECTED) trên các vùng hiển thị được tạo trong một ngữ cảnh được bảo vệ (được ACodec xác minh).

Tính năng phát video kết cấu an toàn đặt nền tảng cho việc triển khai tính năng Quản lý quyền kỹ thuật số (DRM) mạnh mẽ trong môi trường OpenGL ES. Nếu không có một chế độ triển khai DRM mạnh mẽ (chẳng hạn như Widevine Cấp 1), nhiều nhà cung cấp nội dung sẽ không cho phép kết xuất nội dung có giá trị cao của họ trong môi trường OpenGL ES, ngăn chặn các trường hợp sử dụng VR quan trọng như xem nội dung được bảo vệ bằng DRM trong VR.

Dự án nguồn mở Android (AOSP) bao gồm mã khung để phát video có kết cấu bảo mật. Việc hỗ trợ trình điều khiển là tuỳ thuộc vào các nhà sản xuất thiết bị gốc (OEM). Người triển khai thiết bị phải triển khai các tiện ích EGL_EXT_protected_contentGL_EXT_protected_textures. Khi sử dụng thư viện codec của riêng bạn (để thay thế libstagefright), hãy lưu ý những thay đổi trong /frameworks/av/media/libstagefright/SurfaceUtils.cpp cho phép gửi các vùng đệm được đánh dấu bằng GRALLOC_USAGE_PROTECTED đến ANativeWindow (ngay cả khi ANativeWindow không xếp hàng trực tiếp vào trình kết hợp cửa sổ) miễn là các bit sử dụng của người dùng chứa GRALLOC_USAGE_PROTECTED. Để biết tài liệu chi tiết về cách triển khai các tiện ích, hãy tham khảo các sổ đăng ký Khronos ( EGL_EXT_protected_content) và ( GL_EXT_protected_textures).