Tôi là Dale Ipsos, trưởng nhóm kỹ thuật phụ trách phát lại nội dung đa phương tiện trên Chromium. Nhóm của tôi chịu trách nhiệm về các API dành cho nền tảng web để phát video như MSE và WebCodecs, cũng như các nội dung cụ thể của nền tảng liên quan đến việc giảm âm, giải mã và kết xuất âm thanh cũng như video.
Trong bài viết này, tôi sẽ giới thiệu với bạn về cấu trúc kết xuất video của Chromium. Mặc dù một số thông tin về khả năng mở rộng có thể dành riêng cho Chromium, nhưng hầu hết các khái niệm và thiết kế được thảo luận ở đây đều áp dụng cho các công cụ kết xuất khác và thậm chí là ứng dụng phát gốc.
Kiến trúc phát của Chromium đã thay đổi đáng kể trong những năm qua. Mặc dù chúng tôi không bắt đầu với ý tưởng về một kim tự tháp của thành công như mô tả trong bài đăng đầu tiên trong loạt bài này, nhưng cuối cùng, chúng tôi đã làm theo các bước tương tự: độ tin cậy, hiệu suất và khả năng mở rộng.
Ban đầu, quá trình kết xuất video khá đơn giản – chỉ là một vòng lặp for để chọn khung video được giải mã bằng phần mềm để gửi đến trình tổng hợp. Trong nhiều năm, điều này đủ tin cậy, nhưng khi mức độ phức tạp của web tăng lên, nhu cầu tăng hiệu suất và hiệu quả đã dẫn đến những thay đổi về kiến trúc. Nhiều điểm cải tiến đòi hỏi dữ liệu nguyên gốc dành riêng cho hệ điều hành; do đó, kiến trúc của chúng tôi cũng phải trở nên dễ mở rộng hơn để tiếp cận tất cả các nền tảng của Chromium.
Quá trình kết xuất video có thể chia thành hai bước: chọn nội dung cần phân phối và phân phối thông tin đó một cách hiệu quả. Để dễ đọc, tôi sẽ đề cập đến tính năng phân phối hiệu quả trước khi tìm hiểu kỹ cách Chromium chọn nội dung cần phân phối.
Một số thuật ngữ và bố cục
Vì bài viết này tập trung vào việc kết xuất hình ảnh, nên tôi sẽ chỉ đề cập ngắn gọn về các khía cạnh lưu trữ và giải mã của quy trình.
Việc giải mã và ẩn giấu trong thế giới có ý thức bảo mật hiện đại của chúng ta đòi hỏi sự cẩn trọng và hợp lý. Trình phân tích cú pháp nhị phân là môi trường đích nhiều định dạng và hoạt động phát nội dung đa phương tiện chứa đầy đủ các phân tích cú pháp nhị phân. Do đó, vấn đề bảo mật trong các trình phân tích cú pháp nội dung đa phương tiện là cực kỳ phổ biến.
Chromium thực hiện phòng thủ theo chiều sâu để giảm nguy cơ xảy ra các vấn đề bảo mật cho người dùng. Trong thực tế, điều này có nghĩa là quá trình giải mã phần mềm và giảm âm thanh luôn diễn ra trong một quy trình đặc quyền thấp, trong khi quá trình giải mã phần cứng diễn ra trong một quy trình với chỉ đủ đặc quyền để giao tiếp với GPU của hệ thống.
Cơ chế giao tiếp trên nhiều quy trình của Chromium được gọi là Mojo. Mặc dù trong bài viết này, chúng tôi không đi sâu vào chi tiết về Mojo, vì đây là lớp trừu tượng giữa các quy trình, nhưng đây là nền tảng của quy trình nội dung nghe nhìn có thể mở rộng của Chromium. Điều quan trọng là chúng ta phải lưu ý đến điều này khi thực hiện quy trình phát vì quy trình này cung cấp thông tin về cách điều phối phức tạp các thành phần trên nhiều quy trình tương tác để nhận, demux, giải mã và cuối cùng là hiển thị nội dung nghe nhìn.
Quá nhiều bit
Để hiểu rõ quy trình kết xuất video ngày nay, bạn cần phải có kiến thức về lý do khiến video lại đặc biệt: băng thông. Việc phát ở độ phân giải 3840 x 2160 (4K) ở tốc độ 60 khung hình/giây sẽ sử dụng băng thông bộ nhớ có tốc độ từ 9 đến 12 gigabit/giây. Mặc dù các hệ thống hiện đại có thể có băng thông tối đa hàng trăm gigabit/giây, nhưng việc phát video vẫn chiếm một phần đáng kể. Nếu không cẩn thận, tổng băng thông có thể dễ dàng nhân lên do các bản sao hoặc chuyến đi giữa GPU và bộ nhớ CPU.
Mục tiêu của bất kỳ công cụ phát video hiện đại nào có chú trọng đến tính hiệu quả là giảm thiểu băng thông giữa bộ giải mã và bước kết xuất cuối cùng. Vì lý do này, quá trình kết xuất video phần lớn được tách riêng khỏi quy trình kết xuất chính của Chromium. Cụ thể, từ góc độ quy trình kết xuất chính của chúng tôi, video chỉ là một lỗ hổng có kích thước cố định với độ mờ. Chromium thực hiện việc này bằng cách sử dụng một khái niệm có tên là surfaces, trong đó mỗi video sẽ trò chuyện trực tiếp với Viz.
Do sự phổ biến của điện toán di động, sức mạnh và tính hiệu quả đã trở thành một trọng tâm đáng kể trong thế hệ hiện tại. Kết quả của việc này là việc giải mã và kết xuất có liên quan chặt chẽ hơn bao giờ hết ở cấp độ phần cứng, khiến video trông giống như một lỗ hổng với độ mờ, thậm chí đối với chính hệ điều hành! Bộ giải mã cấp nền tảng thường chỉ cung cấp các bộ đệm mờ mà Chromium truyền qua đến hệ thống tổng hợp cấp nền tảng dưới dạng lớp phủ.
Mỗi nền tảng đều có một dạng lớp phủ riêng để API giải mã nền tảng phối hợp với các API giải mã. Windows có Direct Composition (Cấu trúc trực tiếp) và Media Foundation Transforms (Chuyển đổi nền tảng đa phương tiện), macOS có CoreAnimation Layer và VideoToolbox, Android có SurfaceView và MediaCodec, còn Linux có VASurfaces và VA-API. Các thành phần trừu tượng của Chromium cho các khái niệm này được xử lý lần lượt bằng giao diện OverlayProcessor và mojo::VideoDecoder.
Trong một số trường hợp, các vùng đệm này có thể ánh xạ được vào bộ nhớ hệ thống, vì vậy, các vùng đệm này thậm chí không cần phải mờ và không tiêu thụ bất kỳ băng thông nào cho đến khi được truy cập — Chromium gọi các GpuMemoryBuffers này. Trên Windows, các dữ liệu này được hỗ trợ bởi vùng đệmDXGI, trên IOSurfaces của macOS, trên AHardwareBuffers của Android và trên vùng đệm DMA của Linux. Mặc dù việc phát video thường không cần quyền truy cập này, nhưng những vùng đệm này rất quan trọng đối với quá trình quay video để đảm bảo băng thông tối thiểu giữa thiết bị quay và các bộ mã hoá cuối cùng.
Vì GPU thường chịu trách nhiệm giải mã và hiển thị, nên việc sử dụng các bộ đệm mờ này (cũng thường xuyên) giúp đảm bảo rằng dữ liệu video băng thông cao không thực sự rời khỏi GPU. Như chúng ta đã thảo luận trước đó, việc lưu giữ dữ liệu trên GPU có vai trò cực kỳ quan trọng đối với tính hiệu quả; đặc biệt là ở độ phân giải và tốc độ khung hình cao.
Chúng ta càng tận dụng được các dữ liệu nguyên gốc của hệ điều hành như lớp phủ và bộ đệm GPU, thì càng ít băng thông dành cho việc xáo trộn các byte video một cách không cần thiết. Việc giữ mọi thứ ở một nơi từ giải mã đến kết xuất có thể mang lại hiệu quả năng lượng đáng kinh ngạc. Ví dụ: khi Chromium bật lớp phủ trên macOS, mức tiêu thụ pin trong khi phát video ở chế độ toàn màn hình đã giảm một nửa! Trên các nền tảng khác như Windows, Android và ChromeOS, chúng tôi có thể sử dụng lớp phủ ngay cả trong các trường hợp không phải toàn màn hình, giúp tiết kiệm tới 50% gần như mọi nơi.
Kết xuất
Giờ đây, khi đã đề cập đến các cơ chế phân phối tối ưu, chúng ta có thể thảo luận về cách Chromium chọn cơ chế phân phối. Ngăn xếp phát của Chromium sử dụng cấu trúc dựa trên "kéo", nghĩa là mỗi thành phần trong ngăn xếp yêu cầu dữ liệu đầu vào từ thành phần bên dưới nó theo thứ tự phân cấp. Ở trên cùng của ngăn xếp là kết xuất khung hình âm thanh và video, phần thấp hơn tiếp theo là giải mã, sau đó là giảm âm thanh và cuối cùng là I/O. Mỗi khung âm thanh được kết xuất sẽ tiến một bước cho một đồng hồ dùng để chọn khung hình video nhằm kết xuất khi kết hợp với một khoảng thời gian trình chiếu.
Trên mỗi khoảng thời gian trình chiếu (mỗi làm mới màn hình), trình kết xuất video được yêu cầu cung cấp một khung hình video bằng một CompositorFrameSink được đính kèm vào SurfaceLayer nêu trên. Đối với nội dung có tốc độ khung hình thấp hơn tốc độ hiển thị, tức là hiện cùng một khung hình nhiều lần, trong khi nếu tốc độ khung hình lớn hơn tốc độ hiển thị, thì một số khung hình sẽ không bao giờ xuất hiện.
Còn có rất nhiều phương pháp khác để đồng bộ hoá âm thanh và video theo cách làm hài lòng người xem. Xem Project but (Dự án butter) để thảo luận dài hơn về cách đạt được độ mượt mà video tối ưu trong Chromium. Nó giải thích cách phân chia quá trình kết xuất video thành các trình tự lý tưởng thể hiện số lần mỗi khung hình sẽ xuất hiện. Ví dụ: "1 khung hình cho mỗi khoảng thời gian hiển thị ([1], 60 khung hình/giây ở 60 Hz)", "1 khung hình mỗi 2 khoảng thời gian ([2], 30 khung hình/giây ở 60 Hz)" hoặc các mẫu phức tạp hơn như [2:3:2:3:2] (25 khung hình/giây trong 60 Hz) bao gồm nhiều khung hình và khoảng thời gian hiển thị riêng biệt. Trình kết xuất video càng bám sát mẫu lý tưởng này thì người dùng càng có nhiều khả năng cảm thấy quá trình phát là mượt mà.
Mặc dù hầu hết các nền tảng Chromium đều kết xuất từng khung hình, nhưng không phải tất cả đều làm được. Kiến trúc mở rộng của chúng tôi cũng cho phép kết xuất hàng loạt. Kết xuất hàng loạt là một kỹ thuật hiệu quả, trong đó trình tổng hợp cấp hệ điều hành được thông báo trước về nhiều khung hình và xử lý việc phát hành các khung hình đó theo lịch biểu thời gian do ứng dụng cung cấp.
Tương lai là bây giờ?
Chúng tôi tập trung vào cách Chromium tận dụng các dữ liệu nguyên gốc của hệ điều hành để mang lại trải nghiệm phát tốt nhất. Nhưng còn các trang web không chỉ muốn phát video cơ bản thì sao? Chúng tôi có thể cung cấp cho họ những nguyên tắc mạnh mẽ tương tự mà chính Chromium sử dụng để mở ra thế hệ nội dung web tiếp theo không?
Chúng tôi cho rằng câu trả lời là có! Khả năng mở rộng là yếu tố cốt lõi trong cách chúng tôi xem xét nền tảng web hiện nay. Chúng tôi đã và đang làm việc với các trình duyệt và nhà phát triển khác để tạo ra các công nghệ mới như WebGPU và WebCodecs, nhờ đó, các nhà phát triển web có thể sử dụng các công nghệ giống như Chromium khi sử dụng hệ điều hành. WebGPU hỗ trợ vùng đệm GPU và WebCodecs cung cấp tính năng giải mã nền tảng và mã hoá dữ liệu gốc tương thích với các hệ thống lớp phủ và vùng đệm GPU nêu trên.
Hết sự kiện phát trực tiếp
Cảm ơn bạn đã đọc! Tôi hy vọng bạn đã hiểu rõ hơn về các hệ thống phát hiện đại cũng như cách Chromium cung cấp hàng trăm triệu giờ xem mỗi ngày. Nếu muốn tìm hiểu thêm về các bộ mã hoá và giải mã (codec) và video hiện đại trên web, bạn nên xem H.264 là phép thuật của Sid Bala, How Modern Video Viewers Work (Cách những trình phát video hiện đại hoạt động của Erica Beaves) và Cyril Concolato (Đóng gói các chương trình đạt giải thưởng bằng công nghệ giành giải thưởng) của Cyril Concolato.
Một hình minh hoạ (hình minh hoạ đẹp mắt!) của Una Kravets.