Entry tags:
Видео (1)
Построение экранного изображения, в принципе, довольно примитивное занятие. Если отбросить все безумные подробности, X11 и OpenGL, то дело сводится к наличию некоторого количества фрагментов памяти (буферов), имеющих разную структуру (глубина цвета, цветовое пространство, упаковка пикселов) и к механизму смешивания этих буферов. В конце концов, в контроллер дисплея попадает один или несколько буферов, представляющих растр, которые по довольно простым правилам смешиваются между собой. Скажем, в N900, таких аппаратных буферов три. Называются они планами -- графический и два видео-плана -- и по сути дела ничего, кроме этих планов в N900 и не важно. То, что имеется еще "трехмерный ускоритель", ситуацию особенно не меняет -- в конце концов, трехмерный ускоритель выдает "на гора" растровый буфер, который используется для заполнения графического плана.
Конечно, масса деталей затрудняет попытки представить все очень простым и легким. Буфера планов не используются приложениями напрямую, свое содержимое они рисуют как средствами X11, так и через OpenGL, а если приложение не работает в полноэкранном режиме, то и рисует оно не сразу на графический план, а только во вспомогательный буфер, которым пользуется композитный менеджер, чтобы смешать содержимое окон разных приложений в один графический план. Особенно хорошо это видно при просмотре application grid -- панели задач, где каждая задача показывается в виде такого маленького прямоугольника, внутри которого идет активная приложенческая жизнь.
Если содержимое окон меняется очень быстро, например, при отображении видео, у приложений остается не так-то и много вариантов. Если пропускная способность контроллера памяти и графического контроллера, а также производительности процессора достаточно для перемещения кадра за время, меньшее определенного интервала, то можно все сделать по-черному: просто представляем видео-кадр картинкой и выводим ее на экран. Проблемы с этим вариантом возникают сразу. Во-первых, модель рисования приложения через X11 предполагает, что рисует всегда сервер -- XPutImage/XShmPutImage передают изображение на сервер, а он уже доводит эту картинку до графического плана. Фактически, в идеальном случае это означает минимум одну-две копии картинки до момента, как она попадет на экран. Если вывод одного кадра занимает, скажем, 2мс, а его копирование -- 3мс, то при двух-трех копированиях мы можем добиться теоретически картинки с частотой 100Гц. Это все большое ЕСЛИ. X-протокол не гарантирует, что выполняемые действия будут произведены с абсолютной временной точностью. X-протокол работает только с изображениями в RGB-совместимых форматах, а видео-поток из себя представляет чаще всего разновидность YUV, что требует как минимум одно дополнительное копирование для преобразования цветового пространства.
Для решения этой проблемы было придумано расширение XVideo. Смысл его состоит в том, что графический ускоритель предоставляет альтернативный путь смешивания на экране видео-потока, а XVideo реализует его в рамках X-протокола. Альтернативный путь я уже упоминал выше -- те самые видео-планы. Фактически, нам говорят: "у нас тут есть еще несколько буферов размером с экран в заначке и можно рисовать на них специальным образом". В N900 таких дополнительны буферов два, а в nVidia Quadro NVS 140M, который стоит в T61, на котором я сейчас пишу этот текст, поддерживает 32 таких буфера. При выводе в эти буфера можно не конвертировать данные из YUV, вот что говорит по поводу поддерживаемых форматов NVS 140M:
В N900 в видео-планы можно писать и RGB. В целом, путь неплохой и хотя все равно возникает как минимум одно копирование, это практически прямой путь к достижению хорошей производительности видео. Нужно только помнить, что количество буферов (портов в терминологии XVideo) ограничено и отличается от устройства к устройству, да и набор поддерживаемых форматов и дополнительных параметров тоже не стандартизирован.
Однако в случае использования XVideo получается некоторая нестыковка. Конечная картинка, которую мы видим, представляет собой смешивание данных со всех планов. Для того, чтобы смешать графический и видео-планы, дисплейной подсистеме необходимо знать, как пропускать пикселы с одного плана и брать их из другого. В XVideo для этого введено понятие color key. Приложение зарисовывает средствами X11 те пикселы в drawable, которые должны быть заменены на пикселы из видео-планов. То есть, помимо передачи каждого кадра для отрисовки командами XvPutImage/XvShmPutImage необходимо также на каждое событие, приводящее к перерисовке drawable, его перерисовывать с использованием color key. Асинхронность операций в X-протоколе может привести к тому, что рисование color key и кадра будут рассинхронизированы и пользователь увидит color key -- обычно это magenta, как единственный цвет, который отсутствует в естественном световом потоке.
Если у нас есть OpenGL и мы все равно рисуем весь интерфейс средставим OpenGL, может появиться желание вместо XVideo рисовать видеокадры как текстуры. На декстопе (и даже иногда на лаптопах и нетбуках) такое может сработать, потому что пропускная способность контроллера памяти, да и частота на которой работает графический ускоритель, вполне себе позволяет добиться 24Гц-60Гц. Но OpenGL API не рассчитано на такое использование. Во-первых, текстуры в конечном итоге должны быть в RGB-совместимом формате. Во вторых, ускорители OpenGL рассчитаны на динамически изменяемую сцены с относительно статическим набором ресурсов, среди которых и текстуры. Для эффективной работы текстуры при заливке внутрь ускорителя преобразуются во внутренний формат (twiddling). В случае видео "текстуры" у нас одноразовые, они не нужны после формирования кадра, а сцена, наоборот, статическая. Получается, что для изображения видео в рамках традиционного OpenGL мы тратим ресурсы как основного процессора, так и ускорителя на то, что потребуется лишь однажды. Если учесть, что графический ускоритель требует чаще всего DMA для перекачки данных, а при использовании системной памяти как видео-памяти (типичная ситуация для встроенных ускорителей Intel или в случае N900) придется еще озаботиться сбросами кэша памяти. Результат -- использование "в лоб" текстурирования для показа видео приводит к производительности вроде 6-15 кадров в секунду на N900.
Для решения этой проблемы производители графических трехмерных ускорителей придумали свои нестандартные расширения. Как бы они не назывались, суть их одна -- они позволяют обойти стандартный путь представления данных для текстур и прикрепления текстуры к контексту рисования для таких одноразовых кадров. Традиционное название этого процесса -- texture streaming. При этом, фактически, речь идет о том, что графический ускоритель выделяет несколько буферов для приложения и говорит: "складывай свои данные в эти буфера, а я их помогу тебе представить в виде текстур". Если мы сразу кладем наш видеокадр в такой буфер, то можем его использовать после этого в виде текстуры. Такой путь позволяет достичь хорошей производительности за счет энергопотребления. Скажем, на N900 я наблюдал отображение предварительно раскодированного потока 720p с масштабированием на полный экран (получалось 800х480 из оригинальных 1280х720) с потреблением 7-9% CPU. Энергопотребление возрастало по сравнению с XVideo на несколько процентов. Понятно, что декодирование видеопотока в этом случае займет в несколько раз больше. Вывод этого же потока через XVideo потреблял 20% CPU, то есть все же CPU мы разгружаем прилично.
Получилось довольно большое введение. Зачем оно надо -- в следующей заметке.
Конечно, масса деталей затрудняет попытки представить все очень простым и легким. Буфера планов не используются приложениями напрямую, свое содержимое они рисуют как средствами X11, так и через OpenGL, а если приложение не работает в полноэкранном режиме, то и рисует оно не сразу на графический план, а только во вспомогательный буфер, которым пользуется композитный менеджер, чтобы смешать содержимое окон разных приложений в один графический план. Особенно хорошо это видно при просмотре application grid -- панели задач, где каждая задача показывается в виде такого маленького прямоугольника, внутри которого идет активная приложенческая жизнь.
Если содержимое окон меняется очень быстро, например, при отображении видео, у приложений остается не так-то и много вариантов. Если пропускная способность контроллера памяти и графического контроллера, а также производительности процессора достаточно для перемещения кадра за время, меньшее определенного интервала, то можно все сделать по-черному: просто представляем видео-кадр картинкой и выводим ее на экран. Проблемы с этим вариантом возникают сразу. Во-первых, модель рисования приложения через X11 предполагает, что рисует всегда сервер -- XPutImage/XShmPutImage передают изображение на сервер, а он уже доводит эту картинку до графического плана. Фактически, в идеальном случае это означает минимум одну-две копии картинки до момента, как она попадет на экран. Если вывод одного кадра занимает, скажем, 2мс, а его копирование -- 3мс, то при двух-трех копированиях мы можем добиться теоретически картинки с частотой 100Гц. Это все большое ЕСЛИ. X-протокол не гарантирует, что выполняемые действия будут произведены с абсолютной временной точностью. X-протокол работает только с изображениями в RGB-совместимых форматах, а видео-поток из себя представляет чаще всего разновидность YUV, что требует как минимум одно дополнительное копирование для преобразования цветового пространства.
Для решения этой проблемы было придумано расширение XVideo. Смысл его состоит в том, что графический ускоритель предоставляет альтернативный путь смешивания на экране видео-потока, а XVideo реализует его в рамках X-протокола. Альтернативный путь я уже упоминал выше -- те самые видео-планы. Фактически, нам говорят: "у нас тут есть еще несколько буферов размером с экран в заначке и можно рисовать на них специальным образом". В N900 таких дополнительны буферов два, а в nVidia Quadro NVS 140M, который стоит в T61, на котором я сейчас пишу этот текст, поддерживает 32 таких буфера. При выводе в эти буфера можно не конвертировать данные из YUV, вот что говорит по поводу поддерживаемых форматов NVS 140M:
maximum XvImage size: 2046 x 2046 Number of image formats: 4 id: 0x32595559 (YUY2) guid: 59555932-0000-0010-8000-00aa00389b71 bits per pixel: 16 number of planes: 1 type: YUV (packed) id: 0x32315659 (YV12) guid: 59563132-0000-0010-8000-00aa00389b71 bits per pixel: 12 number of planes: 3 type: YUV (planar) id: 0x59565955 (UYVY) guid: 55595659-0000-0010-8000-00aa00389b71 bits per pixel: 16 number of planes: 1 type: YUV (packed) id: 0x30323449 (I420) guid: 49343230-0000-0010-8000-00aa00389b71 bits per pixel: 12 number of planes: 3 type: YUV (planar)
В N900 в видео-планы можно писать и RGB. В целом, путь неплохой и хотя все равно возникает как минимум одно копирование, это практически прямой путь к достижению хорошей производительности видео. Нужно только помнить, что количество буферов (портов в терминологии XVideo) ограничено и отличается от устройства к устройству, да и набор поддерживаемых форматов и дополнительных параметров тоже не стандартизирован.
Однако в случае использования XVideo получается некоторая нестыковка. Конечная картинка, которую мы видим, представляет собой смешивание данных со всех планов. Для того, чтобы смешать графический и видео-планы, дисплейной подсистеме необходимо знать, как пропускать пикселы с одного плана и брать их из другого. В XVideo для этого введено понятие color key. Приложение зарисовывает средствами X11 те пикселы в drawable, которые должны быть заменены на пикселы из видео-планов. То есть, помимо передачи каждого кадра для отрисовки командами XvPutImage/XvShmPutImage необходимо также на каждое событие, приводящее к перерисовке drawable, его перерисовывать с использованием color key. Асинхронность операций в X-протоколе может привести к тому, что рисование color key и кадра будут рассинхронизированы и пользователь увидит color key -- обычно это magenta, как единственный цвет, который отсутствует в естественном световом потоке.
Если у нас есть OpenGL и мы все равно рисуем весь интерфейс средставим OpenGL, может появиться желание вместо XVideo рисовать видеокадры как текстуры. На декстопе (и даже иногда на лаптопах и нетбуках) такое может сработать, потому что пропускная способность контроллера памяти, да и частота на которой работает графический ускоритель, вполне себе позволяет добиться 24Гц-60Гц. Но OpenGL API не рассчитано на такое использование. Во-первых, текстуры в конечном итоге должны быть в RGB-совместимом формате. Во вторых, ускорители OpenGL рассчитаны на динамически изменяемую сцены с относительно статическим набором ресурсов, среди которых и текстуры. Для эффективной работы текстуры при заливке внутрь ускорителя преобразуются во внутренний формат (twiddling). В случае видео "текстуры" у нас одноразовые, они не нужны после формирования кадра, а сцена, наоборот, статическая. Получается, что для изображения видео в рамках традиционного OpenGL мы тратим ресурсы как основного процессора, так и ускорителя на то, что потребуется лишь однажды. Если учесть, что графический ускоритель требует чаще всего DMA для перекачки данных, а при использовании системной памяти как видео-памяти (типичная ситуация для встроенных ускорителей Intel или в случае N900) придется еще озаботиться сбросами кэша памяти. Результат -- использование "в лоб" текстурирования для показа видео приводит к производительности вроде 6-15 кадров в секунду на N900.
Для решения этой проблемы производители графических трехмерных ускорителей придумали свои нестандартные расширения. Как бы они не назывались, суть их одна -- они позволяют обойти стандартный путь представления данных для текстур и прикрепления текстуры к контексту рисования для таких одноразовых кадров. Традиционное название этого процесса -- texture streaming. При этом, фактически, речь идет о том, что графический ускоритель выделяет несколько буферов для приложения и говорит: "складывай свои данные в эти буфера, а я их помогу тебе представить в виде текстур". Если мы сразу кладем наш видеокадр в такой буфер, то можем его использовать после этого в виде текстуры. Такой путь позволяет достичь хорошей производительности за счет энергопотребления. Скажем, на N900 я наблюдал отображение предварительно раскодированного потока 720p с масштабированием на полный экран (получалось 800х480 из оригинальных 1280х720) с потреблением 7-9% CPU. Энергопотребление возрастало по сравнению с XVideo на несколько процентов. Понятно, что декодирование видеопотока в этом случае займет в несколько раз больше. Вывод этого же потока через XVideo потреблял 20% CPU, то есть все же CPU мы разгружаем прилично.
Получилось довольно большое введение. Зачем оно надо -- в следующей заметке.
no subject
либо что?
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
а можно поподробнее, или где можно почитать на тему того что magenta отсутствует в естественном?
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
(no subject)
(no subject)
(no subject)
(no subject)