/NoFFmpeg

Primary LanguageJava

Исследовательский проект для поиска наиболее быстрого способа редактирования видео на Android

Работает это так:

  1. MediaExtractor парсит заголовок входного файла, достаёт информацию об ориентации видео, и, если есть, о фреймрейте
  2. MediaCodec декодирует входной файл
  3. На каждый кадр их входного файла MediaCodec выдаёт Picture в формате YUV, это очень общее обозначение, есть множество частных случаев, как каналы этого изображения будут представлены в памяти.
  4. Picture для каждого канала Y,U,V содержит адрес в памяти, а так же шаг между пикселями и строками, в таком виде информация поступает в модуль на JNI, который копирует эти данные в буфер кодировщика. Прямое копирование буферов горахдо быстрее происходит, но на некторых девайсах приводит к искажениям видео, т.к. порядок байт на выходе декодера и на входе кодера могут не совпадать.
  5. Для отрисовки изображений поверх видео используется отрисовка сразу в YUV, для этого анимированные изображения или обычные изображения сначала перекодируются в YUV, затем рисуются в JNI модуле. Таким образом, все пиксели исходного изображения, которые не перекрываются добавленными картинками, попадают в кодировщик в неизменном виде. Это обеспечивает высокую производительность, особенно в случае, если добавленные картинки занимают небольшую часть видео. Это гораздо быстрее обычного подхода, когда создаётся промежуточное RGB изображение. Кроме того, теоретически, при одинаковых настройках квантования в кодировщике исходного видео и кодировщике редактора возможна ситуция, когда пискели входного и выходного видео совпадают абсолютно без увеличения размера видео.
  6. Для чтения анимированных GIF изображений используется оптимизированная под андроид C библиотека, так что декодирование GIF довольно быстро происходит, примерно на порядок быстрее найденных java библиотек, которые вносили заметные лаги. Декодированные кадры из GIF также кэшируются, так что декодирование вносит задержку только во время первого цикла анимации. Это визуально видно по прогресс-бару.
  7. Так же возможно добавление видео в видео, но тут ещё подумать надо, либо ввести ограничение по размеру видео, и хранить все декодированные кадрые в памяти (подошло бы для стикеров в видео, они так гораздо меньше места будут занимать), либо декодировать исходное видео и добавленное одновременно и ничего не кэшировать. Но это будет дольше, и в интернетах пишут что на некоторых устройствах нельзя более 1 видео через аппаратный кодек играть, иначе краш будет. Проверить это для меня затруднительно, так что пока отключил эту возможность.
  8. Кодируются кадры видео также через MediaCodec
  9. Битрейт кодирвщика вычисляется по формуле frameRate * width * height * bitsPerPixel. Например, для видео 1920*1080 30к/с bitsPerPixel = 0.1 битрейт будет 6 мбит/с. Такое качество выглядит достаточным для видео, снятого на камеру телефона. Минута видео при этом занимает 45 МБайт.
  10. После заверешения перекодирования видео в выходной файл копируется звуковая дорожка без перекодирования.