ผมชื่อ Dale Curtis เป็นหัวหน้าทีมวิศวกรรมด้านการเล่นสื่อใน Chromium ทีมของฉันมีหน้าที่ดูแล API สำหรับเว็บในการเล่นวิดีโอ เช่น MSE และ WebCodecs รวมถึงระบบภายในเฉพาะแพลตฟอร์มที่เกี่ยวข้องกับการลดทรัพยากร ถอดรหัส ตลอดจนแสดงผลเสียงและวิดีโอ
ในบทความนี้ เราจะแนะนำสถาปัตยกรรมการแสดงผลวิดีโอของ Chromium แม้ว่ารายละเอียดบางอย่างเกี่ยวกับความสามารถในการขยายการใช้งานมักจะมีไว้สำหรับ Chromium แต่แนวคิดและการออกแบบส่วนใหญ่ที่กล่าวถึงในที่นี้จะนำไปใช้กับเครื่องมือแสดงผลอื่นๆ และแม้แต่แอปการเล่นแบบเนทีฟ
สถาปัตยกรรมการเล่นของ Chromium ได้เปลี่ยนแปลงไปอย่างมากในช่วงหลายปีที่ผ่านมา แม้ว่าเราจะไม่ได้เริ่มต้นด้วยแนวคิดของพีระมิดแห่งความสำเร็จตามที่อธิบายไว้ในโพสต์แรกในซีรีส์นี้ แต่ท้ายที่สุดแล้ว เราได้ทำตามขั้นตอนที่คล้ายกัน คือ ความน่าเชื่อถือ ประสิทธิภาพ และความสามารถในการขยาย
ในช่วงเริ่มต้น การแสดงผลวิดีโอค่อนข้างง่าย โดยใช้เพียงการวนซ้ำเพื่อเลือกซอฟต์แวร์ที่จะถอดรหัสเฟรมวิดีโอเพื่อส่งไปยังผู้ทำองค์ประกอบ สำหรับหลายปี เรื่องนี้มีความเสถียรมากพอ แต่เมื่อเว็บมีความซับซ้อนมากขึ้น ความต้องการประสิทธิภาพและประสิทธิภาพที่เพิ่มขึ้นทำให้เกิดการเปลี่ยนแปลงทางสถาปัตยกรรม การปรับปรุงหลายอย่างต้องอาศัยพื้นฐานเฉพาะของระบบปฏิบัติการ ดังนั้น สถาปัตยกรรมของเราจึงต้องขยายตัวเพิ่มมากขึ้นเพื่อเข้าถึงทุกแพลตฟอร์มของ Chromium
การแสดงภาพวิดีโออาจแบ่งออกได้เป็น 2 ขั้นตอน ได้แก่ การเลือกสิ่งที่จะแสดงและแสดงข้อมูลอย่างมีประสิทธิภาพ เพื่อให้อ่านได้ง่าย ฉันจะพูดถึงเรื่องการนำส่งที่มีประสิทธิภาพก่อนเจาะลึกว่า Chromium เลือกวิธีที่จะแสดงผลอย่างไร
คำศัพท์และเลย์เอาต์บางส่วน
เนื่องจากบทความนี้มุ่งเน้นไปที่การแสดงผล ฉันขอเล่าสั้นๆ ถึงแง่มุมเรื่องการลดจำนวนและถอดรหัสของไปป์ไลน์
การถอดรหัสและการลดความซับซ้อนในโลกที่คำนึงถึงความปลอดภัยสมัยใหม่ของเราต้องใช้ความระมัดระวังพอสมควร โปรแกรมแยกวิเคราะห์ไบนารีคือสภาพแวดล้อมเป้าหมายที่สมบูรณ์และการเล่นสื่อจะเต็มไปด้วยการแยกวิเคราะห์ไบนารี ด้วยเหตุนี้ ปัญหาด้านความปลอดภัยในโปรแกรมแยกวิเคราะห์สื่อจึงเป็นเรื่องปกติ
Chromium นำการป้องกันอย่างเจาะลึกไปใช้เพื่อลดความเสี่ยงที่จะเกิดปัญหาด้านความปลอดภัยต่อผู้ใช้ ในทางปฏิบัติ การถอดรหัสซอฟต์แวร์และการถอดรหัสซอฟต์แวร์จะเกิดขึ้นในกระบวนการที่มีสิทธิพิเศษต่ำเสมอ ในขณะที่การถอดรหัสฮาร์ดแวร์จะเกิดขึ้นในกระบวนการที่มีสิทธิ์เพียงพอที่จะสื่อสารกับ GPU ของระบบ
กลไกการสื่อสารข้ามกระบวนการของ Chromium เรียกว่า Mojo แม้ว่าเราจะไม่ได้กล่าวถึงรายละเอียดของ Mojo ในบทความนี้ เนื่องจากเป็นเลเยอร์ Abstraction ระหว่างกระบวนการต่างๆ ซึ่งถือเป็นรากฐานที่สำคัญของไปป์ไลน์สื่อที่ขยายได้ของ Chromium คุณต้องตระหนักถึงเรื่องนี้ในขณะที่เราเดินไปตามไปป์ไลน์การเล่น เนื่องจากระบบจะบอกกระบวนการที่ซับซ้อนของคอมโพเนนต์แบบข้ามกระบวนการที่โต้ตอบเพื่อรับ ถอดรหัส ถอดรหัส และแสดงสื่อในท้ายที่สุด
มีหลายบิตมาก
การทำความเข้าใจไปป์ไลน์การแสดงผลวิดีโอในปัจจุบันต้องอาศัยความรู้ว่าเหตุใดวิดีโอจึงมีความพิเศษ ซึ่งก็คือแบนด์วิดท์ การเล่นความละเอียด 3840x2160 (4K) ที่ 60 เฟรมต่อวินาที จะใช้แบนด์วิดท์หน่วยความจำระหว่าง 9-12 กิกะบิต/วินาที แม้ว่าระบบสมัยใหม่อาจมีแบนด์วิดท์สูงสุดเป็นจำนวนหลายร้อยกิกะบิตต่อวินาที การเล่นวิดีโอยังคงเป็นสัดส่วนที่ค่อนข้างสูง หากไม่ระวัง แบนด์วิดท์ทั้งหมดจะเพิ่มขึ้นได้ง่ายเนื่องจากมีการคัดลอกหรือย้ายระหว่าง GPU กับหน่วยความจำของ CPU
เป้าหมายของเครื่องมือเล่นวิดีโอสมัยใหม่โดยคำนึงถึงประสิทธิภาพ คือการลดแบนด์วิดท์ระหว่างตัวถอดรหัสและขั้นตอนการแสดงผลขั้นสุดท้าย ด้วยเหตุนี้ การแสดงภาพวิดีโอจึงแยกออกจากไปป์ไลน์การแสดงผลหลักของ Chromium จากมุมมองของไปป์ไลน์การแสดงภาพหลักของเรา วิดีโอจะเป็นเพียงรูขนาดคงที่ที่มีความทึบแสง Chromium บรรลุเป้าหมายนี้โดยใช้แนวคิดที่เรียกว่า Surfaces ซึ่งแต่ละวิดีโอจะสื่อสารกับ Viz โดยตรง
เนื่องจากความนิยมของการประมวลผลบนอุปกรณ์เคลื่อนที่ พลังและประสิทธิภาพกลายเป็นสิ่งที่ให้ความสำคัญอย่างมากในรุ่นปัจจุบัน ผลที่ได้คือ การถอดรหัสและการแสดงผลมีการเชื่อมโยงกันมากขึ้นในระดับฮาร์ดแวร์ ส่งผลให้วิดีโอดูเหมือนเป็นรูที่มีความทึบแสง แม้แต่กับระบบปฏิบัติการเองก็ตาม ตัวถอดรหัสระดับแพลตฟอร์มมักจะให้เฉพาะบัฟเฟอร์ทึบแสงที่ Chromium ผ่านไปยังระบบประกอบระดับแพลตฟอร์มในรูปแบบของการวางซ้อน
ทุกแพลตฟอร์มมีรูปแบบการวางซ้อนที่ API การถอดรหัสแพลตฟอร์มทำงานอย่างสอดคล้องกัน Windows มี องค์ประกอบโดยตรงและ Media Foundation Transforms, macOS มี CoreAnimation Layers และ VideoToolbox, Android มี SurfaceView และ MediaCodec และ Linux มี VASurfaces และ VA-API นามธรรมของ Chromium สําหรับแนวคิดเหล่านี้ได้รับการจัดการโดยอินเทอร์เฟซ OverlayProcessor และ mojo::VideoDecoder ตามลำดับ
ในบางกรณี บัฟเฟอร์เหล่านี้สามารถแมปไปยังหน่วยความจำของระบบได้ เพื่อไม่ให้เป็นส่วนที่ทึบและไม่กินแบนด์วิดท์จนกว่าจะเข้าถึง โดย Chromium จะเรียกบัฟเฟอร์เหล่านี้ว่า GpuMemoryBuffers บน Windows จะมีบัฟเฟอร์ DXGI ใน macOS IOSurfaces ใน Android AHardwareBuffers และบัฟเฟอร์ DMA ของ Linux แม้ว่าโดยทั่วไปการเล่นวิดีโอจะไม่ต้องมีสิทธิ์เข้าถึงนี้ แต่บัฟเฟอร์เหล่านี้มีความสำคัญต่อการจับภาพวิดีโอเพื่อให้มีแบนด์วิดท์ระหว่างอุปกรณ์บันทึกกับโปรแกรมเปลี่ยนไฟล์สุดท้ายน้อยที่สุด
เนื่องจาก GPU มักจะเป็นทั้งการถอดรหัสและการแสดง ตามที่ได้กล่าวไปก่อนหน้า การรักษาข้อมูลใน GPU เป็นสิ่งสำคัญอย่างมากต่อประสิทธิภาพ โดยเฉพาะที่ความละเอียดและอัตราเฟรมสูง
ยิ่งเราสามารถใช้ประโยชน์จากพื้นฐานของระบบปฏิบัติการ เช่น การซ้อนทับและบัฟเฟอร์ GPU มากเท่าไร ระบบก็จะยิ่งใช้แบนด์วิดท์สับเปลี่ยนไบต์ของวิดีโอน้อยลงโดยไม่จำเป็น การเก็บทุกอย่างไว้ในที่เดียว ตั้งแต่การถอดรหัสไปจนถึงการแสดงภาพจะช่วยประหยัดพลังงานอย่างไม่น่าเชื่อ ตัวอย่างเช่น เมื่อ Chromium เปิดใช้การวางซ้อนใน macOS การใช้พลังงานระหว่างการเล่นวิดีโอแบบเต็มหน้าจอลดลงครึ่งหนึ่ง! บนแพลตฟอร์มอื่นๆ เช่น Windows, Android และ ChromeOS เราสามารถใช้การวางซ้อนแม้ในเคสที่ไม่ใช่เต็มหน้าจอ ซึ่งทำให้ประหยัดพื้นที่ได้ถึง 50% ในเกือบทุกที่
การแสดงผล
ตอนนี้เราก็ได้พูดถึงกลไกการนำส่งที่ดีที่สุดกันแล้ว เราสามารถพูดคุยถึงวิธีที่ Chromium เลือกสิ่งที่จะแสดง ชุดการเล่นของ Chromium ใช้สถาปัตยกรรมแบบ "พุล" ซึ่งหมายความว่าแต่ละคอมโพเนนต์ในสแต็กจะขออินพุตจากคอมโพเนนต์ที่อยู่ด้านล่างตามลำดับ ที่ด้านบนของสแต็กคือการแสดงภาพเฟรมเสียงและวิดีโอ ส่วนถัดไปที่อยู่ด้านล่างคือการถอดรหัส ตามด้วยการแยกหน้าจอ และสุดท้ายคือ I/O เฟรมเสียงที่แสดงผลแต่ละเฟรมจะเลื่อนไปยังนาฬิกาที่ใช้เลือกเฟรมวิดีโอสำหรับการแสดงผลเมื่อรวมกับช่วงเวลาการนำเสนอ
ในแต่ละช่วงการนำเสนอ (รีเฟรชจอแสดงผลแต่ละครั้ง) ระบบจะขอให้ตัวแสดงผลวิดีโอระบุเฟรมวิดีโอโดยใช้ CompositorFrameSink ที่แนบอยู่กับ SurfaceLayer ที่กล่าวถึงไปก่อนหน้านี้ สำหรับเนื้อหาที่มีอัตราเฟรมต่ำกว่าอัตราการแสดงผล ซึ่งหมายถึงการแสดงเฟรมเดียวกันมากกว่า 1 ครั้ง ในขณะที่อัตราเฟรมสูงกว่าอัตราการแสดงผล เฟรมบางรายการจะไม่แสดงเลย
การซิงค์เสียงและวิดีโอในแบบที่น่าพึงพอใจสำหรับผู้ชมยังมีอีกมากมาย ดู Project Butter สำหรับการพูดคุยเพิ่มเติมเกี่ยวกับการทำให้วิดีโอราบรื่นที่สุดใน Chromium ซึ่งอธิบายวิธีการแบ่งการแสดงผลของวิดีโอออกเป็นลำดับที่เหมาะสม ซึ่งแสดงถึงจำนวนครั้งที่ควรแสดงแต่ละเฟรม ตัวอย่างเช่น "1 เฟรมทุกๆ ช่วงเวลาการแสดงผล ([1], 60 FPS ใน 60 Hz)", "1 เฟรมทุกๆ 2 ช่วงเวลา ([2], 30 fps ใน 60 Hz)" หรือรูปแบบที่ซับซ้อนกว่าอย่าง [2:3:2:3:2] (25 fps ใน 60 Hz) โดยครอบคลุมหลายเฟรม และครอบคลุมหลายเฟรม ยิ่งตัวแสดงผลวิดีโอใกล้เคียงกับรูปแบบในอุดมคตินี้มากเท่าใด ผู้ใช้ก็มีแนวโน้มที่จะรู้สึกว่าการเล่นลื่นไหลมากขึ้นเท่านั้น
แม้ว่าแพลตฟอร์ม Chromium ส่วนใหญ่จะแสดงผลแบบเฟรมต่อเฟรม แต่ไม่ใช่ทั้งหมด สถาปัตยกรรมที่ยืดหยุ่นได้ของเราทำให้สามารถแสดงผลเป็นแบบกลุ่มได้เช่นกัน การแสดงผลแบบกลุ่มเป็นเทคนิคประสิทธิภาพที่ระบบแจ้งตัวจัดวางองค์ประกอบระดับระบบปฏิบัติการเกี่ยวกับหลายเฟรมล่วงหน้า และจัดการกับการปล่อยเฟรมเหล่านั้นตามกำหนดการเวลาที่แอปพลิเคชันระบุไว้
อนาคตคืออะไร
เรามุ่งเน้นที่วิธีที่ Chromium ใช้ประโยชน์จากพื้นฐานของระบบปฏิบัติการเพื่อมอบประสบการณ์การเล่นที่ดีที่สุด แล้วเว็บไซต์ที่ต้องการมากกว่าการเล่นวิดีโอแบบพื้นฐานล่ะ เราจะนำเสนอข้อมูลพื้นฐานที่ทรงประสิทธิภาพแบบเดียวกับที่ Chromium เองใช้ในการนําไปสู่เนื้อหาเว็บรุ่นใหม่ได้หรือไม่
เราคิดว่าคำตอบคือใช่ การขยายการใช้งานคือหัวใจสำคัญของความคิดเกี่ยวกับแพลตฟอร์มเว็บในปัจจุบัน เราได้ทำงานร่วมกับเบราว์เซอร์และนักพัฒนาซอฟต์แวร์อื่นๆ เพื่อสร้างเทคโนโลยีใหม่ๆ เช่น WebGPU และ WebCodecs เพื่อให้นักพัฒนาเว็บสามารถใช้แบบพื้นฐานที่ Chromium ทำเช่นกันเมื่อพูดกับระบบปฏิบัติการ WebGPU รองรับบัฟเฟอร์ GPU และ WebCodecs นำการถอดรหัสแพลตฟอร์มและการเข้ารหัสพื้นฐานที่เข้ากันได้กับการวางซ้อนและระบบบัฟเฟอร์ GPU ที่กล่าวถึงข้างต้น
สิ้นสุดสตรีม
ขอขอบคุณที่อ่าน ผมหวังว่าคุณจะเข้าใจระบบการเล่นที่ทันสมัยยิ่งขึ้น และรู้ว่า Chromium ช่วยเพิ่มเวลาในการรับชมหลายร้อยล้านชั่วโมงในแต่ละวันได้อย่างไร หากต้องการอ่านเพิ่มเติมเกี่ยวกับตัวแปลงรหัสและวิดีโอบนเว็บแบบใหม่ เราขอแนะนำ H.264 is Magic โดย Sid Bala, How Modern Video Players Work โดย Erica Beaves และการจัดแพ็กเกจรายการที่ได้รับรางวัลด้วยเทคโนโลยีที่ได้รับรางวัล โดย Cyril Concolato
ภาพหนึ่ง (สวยดีนะ) โดย Una Kravets