BufferQueue và Gralloc

Lớp BufferQueue kết nối các thành phần tạo vùng đệm dữ liệu đồ hoạ (trình tạo) với các thành phần chấp nhận dữ liệu để hiển thị hoặc xử lý thêm (người dùng). Hầu hết mọi hoạt động di chuyển vùng đệm của dữ liệu đồ hoạ thông qua hệ thống đều dựa vào BufferQueue.

Trình phân bổ bộ nhớ Gralloc thực hiện việc phân bổ vùng đệm và được triển khai thông qua hai giao diện HIDL dành riêng cho nhà cung cấp (xem hardware/interfaces/graphics/allocator/hardware/interfaces/graphics/mapper/). Hàm allocate() nhận các đối số dự kiến (chiều rộng, chiều cao, định dạng pixel) cũng như một tập hợp cờ sử dụng.

Nhà sản xuất và người tiêu dùng BufferQueue

Người dùng tạo và sở hữu cấu trúc dữ liệu BufferQueue và có thể tồn tại trong các quy trình khác với nhà sản xuất. Khi cần bộ đệm, thực thể tạo sẽ yêu cầu bộ đệm trống từ BufferQueue bằng cách gọi dequeueBuffer(), chỉ định chiều rộng, chiều cao, định dạng pixel và cờ sử dụng của bộ đệm. Sau đó, thực thể tạo sẽ điền sẵn bộ đệm và trả về bộ đệm đó cho hàng đợi bằng cách gọi queueBuffer(). Tiếp theo, trình tiêu thụ sẽ lấy vùng đệm bằng acquireBuffer() và sử dụng nội dung vùng đệm. Khi hoàn tất, trình tiêu thụ sẽ trả về vùng đệm vào hàng đợi bằng cách gọi releaseBuffer(). Khung đồng bộ hoá kiểm soát cách các vùng đệm di chuyển qua quy trình đồ hoạ Android.

Một số đặc điểm của BufferQueue, chẳng hạn như số lượng vùng đệm tối đa mà nó có thể chứa, được xác định chung bởi nhà sản xuất và người tiêu dùng. Tuy nhiên, BufferQueue sẽ phân bổ bộ đệm khi cần. Các vùng đệm được giữ lại trừ khi các đặc điểm thay đổi; ví dụ: nếu một trình tạo yêu cầu các vùng đệm có kích thước khác, các vùng đệm cũ sẽ được giải phóng và các vùng đệm mới sẽ được phân bổ theo yêu cầu.

BufferQueue không bao giờ sao chép nội dung của vùng đệm vì việc di chuyển nhiều dữ liệu như vậy sẽ không hiệu quả. Thay vào đó, vùng đệm luôn được truyền qua một tay điều khiển.

Theo dõi BufferQueue bằng Systrace

Để hiểu cách vùng đệm đồ hoạ di chuyển, hãy sử dụng Systrace, một công cụ ghi lại hoạt động của thiết bị trong một khoảng thời gian ngắn. Mã đồ hoạ cấp hệ thống được đo lường tốt, cũng như nhiều mã khung ứng dụng liên quan.

Để sử dụng Systrace, hãy bật các thẻ gfx, viewsched. Các đối tượng BufferQueue sẽ xuất hiện trong dấu vết. Ví dụ: nếu bạn theo dõi trong khi video phát của Grafika (SurfaceView) đang chạy, thì hàng có nhãn SurfaceView sẽ cho bạn biết số lượng vùng đệm đã được đưa vào hàng đợi tại bất kỳ thời điểm nào.

Giá trị này tăng lên trong khi ứng dụng đang hoạt động, kích hoạt quá trình kết xuất khung hình bằng bộ giải mã MediaCodec. Giá trị này giảm trong khi SurfaceFlinger đang hoạt động và tiêu thụ vùng đệm. Khi hiển thị video ở tốc độ 30 khung hình/giây, giá trị của hàng đợi sẽ thay đổi từ 0 đến 1 vì màn hình ~60 khung hình/giây có thể theo kịp nguồn. SurfaceFlinger chỉ thức khi có công việc cần làm, chứ không phải 60 lần mỗi giây. Hệ thống sẽ cố gắng tránh làm việc và tắt VSYNC nếu không có nội dung nào cập nhật màn hình.

Nếu chuyển sang video Play của Grafika (TextureView) và lấy một dấu vết mới, bạn sẽ thấy một hàng có nhãn com.android.grafika / com.android.grafika.PlayMovieActivity. Đây là lớp giao diện người dùng chính, cũng là một BufferQueue khác. Vì TextureView kết xuất vào lớp giao diện người dùng thay vì một lớp riêng biệt, nên tất cả các bản cập nhật do video điều khiển đều hiển thị tại đây.

Gralloc

Trình phân bổ Gralloc HAL hardware/libhardware/include/hardware/gralloc.h thực hiện việc phân bổ vùng đệm thông qua cờ sử dụng. Cờ sử dụng bao gồm các thuộc tính như:

  • Tần suất truy cập bộ nhớ từ phần mềm (CPU)
  • Tần suất truy cập bộ nhớ từ phần cứng (GPU)
  • Liệu bộ nhớ có được dùng làm hoạ tiết OpenGL ES (GLES) hay không
  • Bộ mã hoá video có sử dụng bộ nhớ hay không

Ví dụ: nếu định dạng vùng đệm của nhà sản xuất chỉ định RGBA_8888 pixel và nhà sản xuất cho biết rằng vùng đệm sẽ được truy cập từ phần mềm (nghĩa là ứng dụng sẽ chạm vào các pixel trên CPU), thì Gralloc sẽ tạo một vùng đệm có 4 byte cho mỗi pixel theo thứ tự R-G-B-A. Thay vào đó, nếu nhà sản xuất chỉ định vùng đệm của mình sẽ chỉ được truy cập từ phần cứng và dưới dạng kết cấu GLES, thì Gralloc có thể làm mọi thứ mà trình điều khiển GLES muốn, chẳng hạn như thứ tự BGRA, bố cục được đảo ngược phi tuyến tính và các định dạng màu thay thế. Việc cho phép phần cứng sử dụng định dạng ưu tiên có thể cải thiện hiệu suất.

Một số giá trị không thể kết hợp trên một số nền tảng nhất định. Ví dụ: cờ bộ mã hoá video có thể yêu cầu các pixel YUV, vì vậy, việc thêm quyền truy cập vào phần mềm và chỉ định RGBA_8888 sẽ không thành công.

Bạn có thể truyền handle do Gralloc trả về giữa các quy trình thông qua Binder.

Vùng đệm được bảo vệ

Cờ sử dụng Gralloc GRALLOC_USAGE_PROTECTED cho phép chỉ hiển thị vùng đệm đồ hoạ thông qua một đường dẫn được bảo vệ bằng phần cứng. Các lớp phủ này là cách duy nhất để hiển thị nội dung DRM (SurfaceFlinger hoặc trình điều khiển OpenGL ES không thể truy cập vào vùng đệm được bảo vệ bằng DRM).

Video được bảo vệ bằng DRM chỉ có thể hiển thị trên một mặt phẳng lớp phủ. Bạn phải triển khai trình phát video hỗ trợ nội dung được bảo vệ bằng SurfaceView. Phần mềm chạy trên phần cứng không được bảo vệ không thể đọc hoặc ghi vùng đệm; các đường dẫn được bảo vệ bằng phần cứng phải xuất hiện trên lớp phủ Trình tổng hợp phần cứng (tức là video được bảo vệ sẽ biến mất khỏi màn hình nếu Trình tổng hợp phần cứng chuyển sang thành phần OpenGL ES).

Để biết thông tin chi tiết về nội dung được bảo vệ, hãy xem phần DRM.