SurfaceTexture
là sự kết hợp giữa bề mặt và kết cấu OpenGL ES (GLES) . Các phiên bản SurfaceTexture
được sử dụng để cung cấp các bề mặt xuất ra kết cấu GLES.
SurfaceTexture
chứa một phiên bản BufferQueue
dành cho ứng dụng nào là người tiêu dùng. Lệnh gọi lại onFrameAvailable()
sẽ thông báo cho ứng dụng khi nhà sản xuất xếp hàng bộ đệm mới. Sau đó, các ứng dụng gọi updateTexImage()
để giải phóng bộ đệm đã giữ trước đó, lấy bộ đệm mới từ hàng đợi và thực hiện lệnh gọi EGL để cung cấp bộ đệm cho GLES dưới dạng kết cấu bên ngoài.
Kết cấu GLES bên ngoài
Họa tiết GLES bên ngoài ( GL_TEXTURE_EXTERNAL_OES
) khác với họa tiết GLES truyền thống ( GL_TEXTURE_2D
) theo các cách sau:
- Kết cấu bên ngoài hiển thị đa giác có kết cấu 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 truyền thống.
- Họa tiết bên ngoài không thể thực hiện tất cả các hoạt động họa tiết GLES truyền thống.
Lợi ích chính của kết cấu bên ngoài là khả năng hiển thị 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 tiêu dùng thành GRALLOC_USAGE_HW_TEXTURE
khi nó tạo các phiên bản BufferQueue
cho kết cấu bên ngoài để đảm bảo rằng GLES có thể nhận dạng được dữ liệu trong bộ đệm.
Vì các phiên bản SurfaceTexture
tương tác với ngữ cảnh EGL nên ứng dụng chỉ có thể gọi các phương thức của nó trong khi ngữ cảnh EGL sở hữu kết cấu đó hiện có trên luồng gọi. Để biết thêm thông tin, hãy xem tài liệu lớp SurfaceTexture
.
Dấu thời gian và chuyển đổi
Các phiên bản 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. Gọi updateTexImage()
đặt cả dấu thời gian và ma trận chuyển đổi. Mỗi bộ đệm mà BufferQueue
chuyển qua bao gồm các tham số biến đổi và dấu thời gian.
Các tham số chuyển đổi rất hữu ích cho hiệu quả. Trong một số trường hợp, dữ liệu nguồn có thể được định hướng không chính xác cho người tiêu dùng. Thay vì xoay dữ liệu trước khi gửi đến người tiêu dùng, hãy gửi dữ liệu theo hướng của nó bằng một phép biến đổi để sửa nó. Ma trận chuyể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ảm thiểu chi phí.
Dấu thời gian rất 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 nhà sản xuất với đầu ra của máy ảnh, các khung hình từ máy ảnh có thể được sử dụng để tạo video. Mỗi khung hình cần có dấu thời gian trình bày kể từ khi khung hình được chụp chứ không phải từ khi ứng dụng nhận được khung hình. Mã camera đặt dấu thời gian được cung cấp cùng với bộ đệm, dẫn đến chuỗi dấu thời gian nhất quán hơn.
Nghiên cứu điển hình: Việc Grafika bị bắt liên tục
Tính năng chụp liên tục của Grafika bao gồm việc ghi lại các khung hình từ camera của thiết bị và hiển thị những khung hình đó trên màn hình. Để ghi lại các khung hình, hãy tạo một bề mặt bằng phương thức createInputSurface()
của lớp MediaCodec và chuyển bề mặt đó tới máy ảnh. Để hiển thị các khung, hãy tạo một phiên bản SurfaceView
và chuyển bề mặt đó cho setPreviewDisplay()
. Lưu ý rằng việc ghi các khung hình và hiển thị chúng cùng lúc là một quá trình phức tạp hơn.
Hoạt động chụp liên tục hiển thị video từ camera khi video đang được ghi. Trong trường hợp này, video được mã hóa được ghi vào bộ đệm tròn trong bộ nhớ có thể được lưu vào đĩa bất kỳ lúc nào.
Luồng này bao gồm ba hàng đợi bộ đệm:
-
App
— Ứng dụng sử dụng phiên bảnSurfaceTexture
để nhận khung hình từ máy ảnh, chuyển đổi chúng thành kết cấu GLES bên ngoài. -
SurfaceFlinger
- Ứng dụng khai báo một phiên bảnSurfaceView
để hiển thị các khung. -
MediaServer
- Định cấu hình bộ mã hóaMediaCodec
với bề mặt đầu vào để tạo video.
Trong hình bên dưới, các mũi tên biểu thị việc truyền dữ liệu từ camera. Các phiên bản BufferQueue
có màu (nhà sản xuất có màu xanh mòng két, người tiêu dùng có màu xanh lá cây).
Video H.264 được mã hóa sẽ chuyển đến bộ đệm tròn trong RAM trong quá trình xử lý ứng dụng. Khi người dùng nhấn nút chụp, lớp MediaMuxer
sẽ ghi video được mã hóa vào tệp MP4 trên đĩa.
Tất cả các phiên bản 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ã hóa (quản lý bộ đệm tròn và ghi nó vào đĩa) được thực hiện trên một luồng riêng biệt.
SurfaceView
, hàm gọi lại surfaceCreated()
sẽ tạo các phiên bản EGLContext
và EGLSurface
cho màn hình và bộ mã hóa video. Khi có khung hình mới, SurfaceTexture
thực hiện bốn hoạt động:- Có được khung.
- Làm cho khung có sẵn dưới dạng kết cấu GLES.
- Hiển thị khung bằng lệnh GLES.
- Chuyển tiế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ã hóa sẽ kéo đầu ra được mã hóa từ MediaCodec
và lưu nó vào bộ nhớ.
Phát lại video kết cấu an toàn
Android hỗ trợ xử lý hậu kỳ GPU cho nội dung video được bảo vệ. Điều này cho phép các ứng dụng sử dụng GPU để tạo ra các hiệu ứng video phi tuyến tính phức tạp (chẳng hạn như làm cong), ánh xạ nội dung video được bảo vệ lên các kết cấu để sử dụng trong các cảnh đồ họa thông thường (ví dụ: sử dụng GLES) và thực tế ảo (VR).
Hỗ trợ được bật bằng hai tiện ích mở rộng sau:
- Tiện ích mở rộng EGL — (
EGL_EXT_protected_content
) Cho phép tạo bối cảnh và bề mặt 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 mở rộng GLES - (
GL_EXT_protected_textures
) Cho phép gắn thẻ họa tiết là được bảo vệ để chúng có thể được sử dụng làm tệp đính kèm kết cấu 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 tới SurfaceFlinger
và cung cấp bề mặt video được bảo vệ để sử dụng trong bối cảnh được bảo vệ. Điều này được thực hiện bằng cách đặt bit tiêu dùng được bảo vệ ( GRALLOC_USAGE_PROTECTED
) trên các bề mặt được tạo trong bối cảnh được bảo vệ (được xác minh bởi ACodec).
Tính năng phát lại video có kết cấu an toàn đặt nền tảng cho việc triển khai DRM mạnh mẽ trong môi trường OpenGL ES. Nếu không 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 không cho phép hiển thị nội dung có giá trị cao của họ trong môi trường OpenGL ES, ngăn cản các trường hợp sử dụng VR quan trọng như xem nội dung được bảo vệ DRM trong VR.
AOSP bao gồm mã khung để phát lại video có kết cấu an toàn. Hỗ trợ trình điều khiển tùy thuộc vào OEM. Người triển khai thiết bị phải triển khai các tiện ích mở rộng EGL_EXT_protected_content
và GL_EXT_protected_textures extensions
. 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 các bộ đệm được đánh dấu bằng GRALLOC_USAGE_PROTECTED
được gửi tới ANativeWindow
(ngay cả khi ANativeWindow
không xếp hàng trực tiếp vào trình soạn thảo cửa sổ) miễn là các bit sử dụng của người tiêu dùng chứa GRALLOC_USAGE_PROTECTED
. Để biết tài liệu chi tiết về cách triển khai tiện ích mở rộng, hãy tham khảo cơ quan đăng ký Khronos ( EGL_EXT_protected_content
và GL_EXT_protected_textures
).