1

У меня возникли проблемы с решением эффективного решения. Есть несколько проблем, я предвидя, первые из которых ...Что было бы самым эффективным способом буферизации последних X минут MediaProjection

Профилактика ООГО

Если бы я хотел последние 30 секунд или даже 5 минут это выполнимо, но что, если я хотел за последние 30 минут или полный час, или, может быть, ВСЁ? Хранение байтового буфера означает его хранение в ОЗУ. Сохранение более ста мегабайт звучит как самоубийство виртуальной памяти.

Хорошо, так что, если мы храним Y некоторое количество времени, скажем, 30 секунд, ранее записанного носителя на диск в некотором tmp-файле. Это потенциально может работать, и я могу использовать библиотеку, такую ​​как mp4 parser, чтобы объединить их все, когда закончите. Однако ...

Если у нас есть 30 минут, это около 60 30-секундных клипов. Это похоже на отличный способ записи через SD-карту, и даже если это не проблема, я не могу представить время, необходимое для объединения более ста файлов в один.

Из того, что я исследовал, я думал об использовании локальных сокетов, чтобы сделать что-то вроде ...

MediaRecorder -> setOutputFile (LocalSocket.getFD())

Тогда в локальный сокет ...

LocalSocket -> FileOutputStream -> запись (данные, должность, BUFSIZ) -> вровень()

Где фоновый поток обрабатывает письма и отслеживание позиции, и буфер.

Это чисто псевдокод, и я еще недостаточно далеко, чтобы проверить это, схожу ли я в правильном направлении? Из того, что я думаю, это только сохраняет один файл, который перезаписывается. Поскольку он записывается только один раз за каждые Y секунд, он минимизирует накладные расходы IO, а также минимизирует объем RAM, который он ест.

видео Длина размера буфера

Как бы я получить размер буфера должен быть от требуемого размера видео. Это странно, так как я вижу несколько длинных видеороликов, которые представляют собой небольшие, но короткие видеоролики, которые огромны. Поэтому я не знаю, как точно это определить. Кто-нибудь знает, как я могу это предсказать, если знаю длину видео, кодировку и т. Д., Которые настроены из Media Recorder?

Примеры

Кто-нибудь знает какие-либо примеры этого? Я не думаю, что идея полностью оригинальна, но я не вижу ее много, и если она делает это, то она закрыта. Пример долгий путь.

Заранее спасибо

ответ

1

«непрерывным захвата» активность в Grafika делает это, используя MediaCodec, а не MediaRecorder. Он сохраняет последние N секунд видео в круговом буфере в памяти и записывает их на диск по запросу пользователя.

CircularEncoder constructor оценивает требования к памяти на основе целевой скорости передачи. По разумной цене (скажем, 4 Мбит/с) вам понадобится 1,8 ГБ для хранения видеочаса в час, так что он не будет вписываться в ОЗУ на текущих устройствах.Пять минут - 150 МБ, что подталкивает границы хороших манер. Вероятно, необходимо намазать файл на диск.

Передача данных через сокет не покупает вам ничего, что вы не получаете из соответствующей структуры данных java.util.concurrent. Вы просто включаете ОС в копию данных.

Одним из подходов было бы создать файл с отображением памяти и просто рассматривать его так же, как CircularEncoder обрабатывает свой круговой буфер. В Grafika данные кадра попадают в один большой байтовый буфер, а метаданные (которые сообщают вам, например, где начинается и заканчивается каждый пакет), находятся в параллельном массиве. Вы можете сохранить данные кадра на диске и сохранить метаданные в памяти. Картирование памяти будет работать для пятиминутного случая, но, как правило, не для полного часового случая, так как получение смежного диапазона виртуальных адресов может быть проблематичным.

Без ввода-вывода с отображением памяти подход практически одинаков, но вам нужно искать/читать/писать с помощью вызовов ввода-вывода файлов. Опять же, сохраните метаданные фрейма в памяти.

Дополнительный буферный этап может потребоваться, если дисковый ввод-вывод останавливается. При записи видеоданных через MediaMuxer я видел периодические односекундные киоски, которые больше буферизуются, чем MediaCodec, что приводит к отбрасыванию кадров. Вы можете отложить решение этого вопроса, пока не убедитесь, что на самом деле у вас есть проблема.

Есть несколько дополнительных данных, которые необходимо учитывать, например, сбрасывание кадров в начале, чтобы обеспечить, чтобы ваше видео начиналось на кадре синхронизации, но вы можете видеть, как Grafika решила их.

+0

Хорошо, конечно, не ожидал ответа так подробно. Я не могу прямо комментировать контент прямо сейчас, но я должен поблагодарить вас за объем усилий. Я прочту позже и вернусь к вашему сообщению. –

+0

Просто комментируя, чтобы сказать, что я не забыл этот ответ, однако прямо сейчас у меня есть другие вещи, которые необходимо реализовать сначала. Прежде чем я смогу работать над этой реализацией, у меня есть несколько базовых вопросов: 1) Могу ли я предположительно использовать поверхность, полученную MediaProjection, непосредственно с MediaRecorder? Если да, то это замена? 2) Принесут ли он лучшие результаты и/или производительность, если я это сделаю с JNI/NDK? Я знаком с чтением-записью в формате mmap и C, поможет ли это? Раньше я никогда не делал JNI/NDK, но мне всегда хотелось оправдать его. –

+0

(1) MediaCodec и MediaRecorder предоставляют Поверхность, когда ее спрашивают. Вы передаете это вызову 'createVirtualDisplay()' MediaProjection'. Работает одинаково для любого из них, или SurfaceView. (2) Вы делаете очень мало вычислений в своем коде. Ваше приложение просто направляет трафик, поэтому нет никакой пользы в использовании NDK. Может существовать преимущество в использовании встроенного ввода-вывода, если эквиваленты Java-языка не подходят, что потенциально позволяет избежать дополнительной копии, но я настоятельно рекомендую, чтобы он работал сначала без NDK. – fadden