Дальше три модуля текстовые немасштабируемые: uf1, uf2 - прокладки для работы с файлами разных файловых систем, VGinput - ввод имени файла для анимированного гифа.
И потом идет модуль Video3GP
Ревизия окна Video3GP
До этого окна в паинткаде можно добраться если захотеть извлечь кадр из видео-файла. А делается это так (на эмуляторе сименса оно работает, видео проигрывает, останавливает, но кадры почему-то не снимает, видимо, потому что эмулятор. Эмуляторы, бывало, глючили на некоторых функциях, а реальные телефоны работали):
1) в главном меню выбрать "0"-"Обработка"-"Снять 3GP/MP4 кадр"
2) прочитать подготовительное сообщение что сейчас надо будет выбрать файл с видео
3) выбрать в файловом менеджере файл (подложил эмулятору какой-то старый 3GP из 2006 года)
4) прочитать еще одно сообщение про управление окном
5) появится окно Video3GP - оно будет пустое (можно рассмотреть что тут можно отмасштабировать)
6) и потом, когда видео загрузится в плеер, появится видеовывод, который сразу запроигрывается, отрисовываясь прямо от левого верхнего угла (поэтому обычно он сразу закрывал заголовок окна, и в заголовке просто слово-заглушка "Video" поэтому, все равно его никто не видит обычно в процессе проигрывания видео и выбора кадра):
Внизу окна отображается размер видеорастра в пикселях "ширина x высота".
Еще ниже - текущий файл. При съемке по "5", судя по коду, должно произойти следующее:
1) если открывали, например, 0:/Videos/test.3gp, то имя снятого кадра будет выбрано как 0:/Videos/test-0.jpg для сименса и 0:/Videos/test-0.png для всех других моделей
2) в этот файл, в ту же папку где был видеофайл, с запросом у плеера "encoding=jpeg" будет сохранен кадр из видеопотока
3) логика этого окна была в том, чтобы нащелкать много кадров, и они бы сохранялись бы по очереди в test-0.jpg, test-1.jpg, test-2.jpg и т.д. Кнопкой "# - в начало" можно было сбросить счетчик кадров и снова начать сохранять с нулевого (перезаписывая предыдущие сохраненные файлы)
Но после съемки первого кадра вписан выход из окошка в главное окно рисования с показом сообщения:
Снимок
сохранен
под именем
0:/Videos/test-0.jpg
Т.е. больше одного кадра оно не снимало. Поэтому номер кадра всегда был 0. И сохраняемый файл всегда был бы в данном случае 0:/Videos/test-0.jpg.
Наверное, плеер не хотел снимать больше одного кадра. Поэтому чтоб снять еще один приходилось закрыть плеер и открыть новый (снова выбрав файл и т.д.).
Попробовал запустил эту же функцию "Снять 3GP/MP4 кадр" на другом эмуляторе сименса побольше (EL71, 240x320). Он зашел подальше - после нажатия кнопки съемки он спрашивает разрешения на съемку. Но после этого ничего не сохраняет. Можно только выйти из окошка по левому софту:
Есть подозрение что enconding=jpeg почему-то не работает в эмуляторе. Эмулятор даже скриншоты сохраняет в tga, а не в png/jpg. Может JPEG это была платная технология и ее не стали добавлять в эмулятор. Или работает супермедленно и чутко, так что надо не дышать и ничего не нажимать в этот момент чтобы его не спугнуть)
Как оно должно работать теперь понятно.
Для начала отмасштабируем строчки, разместив их над панелью софт-клавиш чтобы в обоих сименсах (да и на других телефонах) их было видно.
(на сименсе с экраном покрупней эмулятор сначала рисует видеопоток из файла пониже, а потом прыгает вверх, оставляя внизу статично нарисованным один из первых кадров, поэтому такая двойная картинка. На реальном телефоне, насколько помню, такого не было)
Т.к. явовские плееры в microemu не реализованы, то сделаем свой плеер. Для андроида сделаем отдельный модуль Video3GP2 (прямо как в функции съемки фото с камеры), в заголовок окошек Video3GP и Video3GP2 вместо Video впишем название. Получается такое пустое окошко Video3GP2:
Для доставания кадров из видео в андроиде есть, например, android.media.MediaMetadataRetriever. Написано, что появился он в API level 10 - т.е. Android 2.3.3. Подходит вроде.
Создаем новый MediaMetadataRetriever и передаем туда пусть и имя файла в строке fnam, выбранные в файловом менеджере:
Код: Выделить всё
import android.media.MediaMetadataRetriever;
...
mdr = new MediaMetadataRetriever();
mdr.setDataSource(fnam);
Теперь запросим кадр по смещению во времени. Запросим самый первый кадр, смещение = 0 микросекунд. Если он не null - значит что-то там есть внутри. Запакуем его в JPG и превратим в массив байтов, который уже передадим паинткаду. Такой массив можно и загрузить в Image для показа на экране, и просто сохранить в файл (когда пользователь запросит сохранение в файл). Можно даже сразу загрузить в паинткад на рисунок (можно будет добавить еще и эту опцию, чтоб сразу доставать кадр и загружать на текущий рисунок, без сохранения в JPG-файл):
Код: Выделить всё
long toff = 0;
Bitmap bmp = mdr.getFrameAtTime(toff, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
if (bmp!=null)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
ssphoto = baos.toByteArray();
}
И вот какой первый кадр видео рисуется в окошке - оно работает, по крайней мере, на Android 15 (должно по описанию на с 2.3.3 и новей работать, потом надо будет проверить на всех телефонах). Информации никакой еще не рисуется, только картинка для теста, поэтому пишет 0x0:
Теперь осталось накрутить туда интерфейс, сенсорное управление и посмотреть с какой скоростью этот MediaMetadataRetriever достает кадры из видео.
Сначала сделаем чтоб кадр рисовался в пределах области окна, не залезая на информацию. Обрисуем кадр (или его часть, попадающую в активную область окна) рамкой толщиной 1 виртуальный пиксель.
На видео, параметры которого
Video: S263 128x96 12.5fps 51kbps [V: English [eng] (h263, yuv420p, 128x96, 51 kb/s)]
Audio: AMR 8000Hz mono 12kbps [A: SoundHandler [eng] (amr_nb, 8000 Hz, mono, 12 kb/s)]
вывод кадра такой:
Еще на большом видео, снятом на самом смартфоне, с параметрами
Video: MPEG4 Video (H264) 1920x1080 30fps 18400kbps [V: VideoHandle [eng] (h264 high L4.1, yuv420p, 1920x1080, 18400 kb/s)]
Audio: AAC 48000Hz stereo 320kbps [A: SoundHandle [eng] (aac lc, 48000 Hz, stereo, 320 kb/s)]
вывод кадра такой (причем в видео, видимо, записан поворот телефона с гироскопа, как в JPG-снимках бывает подобное, поэтому MediaMetadataRetriever загружает его правильно, повернутым):
Интересно что кадр 128x96 пикселей MediaMetadataRetriever масштабировал сам до 320x240. Интересно почему. Но он масштабировал со сглаживанием, ничего так.
Уберем это придумывание имен кадров, и сделаем отсчет с первого кадра. Будут просто файлы 1.jpg, 2.jpg и т.д помещаться в папку исходного видео-файла.
Слева внизу отобразим размер (ширину x высоту) кадра, а справа внизу - будущее имя файла для сохранения кадра.
Повыше нарисуем текущее смещение (сначала оно ровно нулю). Андроидовский MediaMetadataRetriever понимает смещения в микросекундах. Но, вообще, при 25 кадрах в секунду каждый кадр будет 1 000 000 мкс / 25 = 40 000 мкс. Поэтому достаточно показывать секунды и миллисекунды, кадры будут лежать по смещениям в 0 секунд, потом в 0.04 секунды, в 0.08 секунды и т.д. Будем показывать их в виде дробного числа секунд с тремя цифрами после запятой. Будем показывать запятую-разделитель целой и дробной частей числа для русского языка и точку для английского.
Получаем:
Теперь попросим у андроида длительность всего загруженного в MediaMetadataRetriever видео чтобы и ее отрисовать на экране рядом с текущим временным положением:
Код: Выделить всё
String dura = mdr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long dur = Long.parseLong(dura);
Теперь в dur у нас длительность. Причем она в миллисекундах.
Нарисуем ее на окошке и проверим в обычном каком-нибудь плеере что все правильно:
И паинткадовский, и обычный плеер показывают 19 секунд. Паинткад показывает до миллисекунд)
Другое видео:
Тоже оба плеера показывают 6 секунд. Теперь паинткад знает длительность видеофайла.
Теперь сделаем вместо просто показа "текущее положение / максимальная длительность" большой слайдер, двигая пальцем по которому можно будет перемещаться в любое место видео. А уже на нем отобразим текущее и максимальное положение. По бокам еще сделаем две стрелки для "покадрового" перемещения (например, по 400 мс за клик). Получаем:
Теперь сделаем стрелки и полоску-слайдер управляемыми. Кнопки 4/6 и влево/вправо сдвигают позицию на 40 мс (40000 мкс). А клик по слайдеру пальцем мгновенно переставляют позицию в указанную.
Оказалось, что
Код: Выделить всё
Bitmap bmp = mdr.getFrameAtTime(toff, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
выдает ближайший "ключевой" кадр, а их там в видео один кадр в полсекунды-секунду.
Заменим эту команду на
Код: Выделить всё
Bitmap bmp = mdr.getFrameAtTime(toff, MediaMetadataRetriever.OPTION_CLOSEST)
это то же самое, но без SYNC, теперь кадров стало гораздо больше. И при каждом перемещении вправо/влево на малые смещения теперь кадр меняется.
3GP видео встроенный в андроид декодер распознает странно, первый кадр - нормально, остальные - в зеленых тонах) глючит, в общем. Ну ладно. Встроенный в андроид плеер тоже рисует этот 3GP в зеленых тонах. И только сторонние плееры (которые, видимо, сами декодируют кадры) рисуют это видео нормально. Проверим потом еще отрисовку этого видео на других андроидах, может там все ок, и это в 15 андроиде такие чудеса с проигрыванием старых 3GP.
По 1 кадру (40 миллисекунд) можно долго мотать видео. Поэтому сделаем такое управление:
1) клик по слайдеру и перемещение его пальцем - переход сразу в указанное место
2) стрелками на экране слева/справа от слайдера текущего положения - по 1 кадру перемотка (40 мс)
А если сенсорного экрана в андроиде нет или хочется переместиться в конкретное место (например, ровно на 5 секунд вперед), то:
3) цифрами 4 и 6, джойстиком Влево и Вправо - тоже по 1 кадру перемотка (40 мс, будем считать что в видео 25 кадров в секунду)
4) цифрами 1 и 3 - по 1 секунде сразу перемотка
5) цифрами 7 и 9 - по 10 секунд перемотка
6) цифрой 2, джойстиком Вверх - перейти в самое начало видео
7) цифрой 8, джойстиком Вниз - перейти в самый конец видео
8) цифрой 5 - перейти в середину видео
Чтобы во всем этом не запутаться - сделаем на виртуальной цифровой клавиатуре другие значки в этом окне съемки кадров из видео.
Обычные стрелки (в других окнах на виртуальной клавиатуре), оказывается, до сих пор рисуются с подложкой (типа тень, а даже, скорее, как будто они объемные и это их бок виден сверху) со сдвигом 2 реальных пикселя. Сделаем эти сдвиги равными одному виртуальному пикселю:
А для съемки кадров нарисуем на виртуальной клавиатуре другие значки: одна стрелка - медленно мотать (40 мс за шаг), две - быстрее (1 секунда за шаг), три - еще быстрее (10 секунд за шаг). Еще сделаем стрелку, упершуюся в границу слева (перемотка в начало видео). Такую же, упершуюся в границу справа (перемотка в конец видео). И еще одну - в середине граница, а по бокам две стрелки ее сжимают (перемотка в середину видео).
С тенями/объемом на центральной кнопке вообще непонятно что делать) Она как бы сверху ровно наблюдается, поэтому пусть левая стрелка отбрасывает объем в одну сторону, а правая в другую, плюс еще поправки на сдвиг объема верха и низа стрелок. По хорошему, на центральной кнопке вообще подложку не надо рисовать. Но если нарисовать, то, в общем, получилось вот так пока что:
Эта же центральная кнопка "5" без сдвигов подложки по вертикали:
И она же без подложки вообще:
Наверное, оставим ее как в последнем варианте - т.е. без подложки.
На виртуальной клавиатуре еще с древних времен на прямоугольных клавишах нарисованы вот эти "блики" и "тени" от выпуклости клавиши. Их ширина - 2 физических пикселя для любых телефонов. Сделаем их масштабируемыми. Чтоб как на мелком, так и на большом экране выглядели одинаково.
Заодно сделаем эти блики чуть побледней чем ярко-белый. И округлим с углов немного.
Получаем на большом экране:
И на экране поменьше (320x480):
Что касается клавиатуры в окне съемки кадров из видео - теперь она будет выглядеть вот так с этими кнопками:
Кнопка перемотки с одной стрелкой мотает на 1 кадр (40 мс), кнопка с двумя стрелками мотает на секунду, а кнопка самой быстрой перемотки (с тремя стрелками) перематывает на 10 секунд. А если видео будет 2-часовое, скачанное с инета, из которого захочется понадергать кадров?
Сделаем кнопку с тремя стрелками такую: перематывает на 5% от длительности видео, но если эти 5% меньше 10 секунд - то перематывает на 10 секунд.
Вот на большом видео (снял для теста больше 200 секунд длительностью) эти 5% будут точно больше 10 секунд - и тогда кнопка с тремя стрелками перематывает на 20-тую часть длительности видео (в данном случае это 11,408 с). За 20 нажатий можно пройти от самого начала до самого конца видео, быстро докатившись до любой части видео, а потом уже кнопками перемотки с двумя или с одной стрелкой точно переместиться на нужный кадр, при любой длительности видео, хоть при двухчасовом фильме:
На кнопку "звездочка", как в других окнах, сделаем масштабирование - тут это будет масштабирование видео под область вывода видео между заголовком окна и слайдером позиции.
При включенном по "*" масштабировании большой кадр видео превращается в маленький и влезает ровно в область вывода видео (это не повлияет на размер снимаемого кадра, сделано только для просмотра всего кадра видео "на весь экран" перед его съемкой и вытаскиванием в паинткад для редактирования или в файл):
А маленький, наоборот, растягивается до большой области вывода видео:
Стартовое сообщение при вызове функции съемки кадра из видео было такое:
Пропишем его поподробнее, т.к. в андроидах помимо 3GP/MP4, бывает (зависит от устройства), что поддерживаются и другие видеоформаты:
На сименсе на мелком экране текст, вроде, влезает нормально на обоих языках:
Попробовал открыть AVI-файлы, с запаковкой кодеками и без - ни один не грузится) Вылетает исключение. Сделаем чтобы при исключениях при открытии файла окошко запоминало что файл не загружен и сообщало об этом. Кнопка "Снимок" тогда будет недоступна. Останутся только софт-клавиши на закрытие окошка и на выбор другого видеофайла. Получилось:
Теперь отцентрируем вывод кадра в активной области. И сообщение об ошибке загрузки тоже отцентрируем. Получилось на мелком видео - без масштабирования по *, с масштабированием по *, и на сообщении об ошибке:
Теоретически могут быть качественные видео (например, пиксельные), которые хорошо бы не пережимать в JPG, а вытащить кадр без потерь качества. Например, сохранять в PNG. Сделаем по кнопке "0" переключение форматов. Сначала внизу пишет "1.jpg":
После нажатия "0" окно переключается на вывод "1.png". При этом обновляет кадр, вытаскивая его через PNG формат, а не через JPG. И все кадры, которые будут вытаскиваться - будут без потерь качества в PNG формате. Для переключения обратно на JPG нужно еще раз нажать "0".
Еще сделаем проигрывание видео, подобно тому как это было в явовском плеере в окошке Video3GP. Сделаем на кнопке "#" включение проигрывания - тогда видеокадры пытаются выводиться каждые 40 мс, но т.к. вытаскиваются они MediaMetadataRetriever-ом медленно, то фпс, конечно, падает. При выводе очередного кадра плеер смотрит сколько прошло времени на вытаскивание и вывод последнего кадра, и вытаскивает следующий кадр уже с этим смещением по времени. Получается, что плеер играет видео в реальном времени (1 секунда видео - за 1 секунду времени), но просто с низким фпс. Чем медленней телефон - тем ниже фпс, но скорость проигрывания совпадает с реальным временем.
На клавиатуре на "#" нарисуем кнопку проигрывания:
А если проигрывание уже включено - будем рисовать там кнопку паузы (второе нажатие на "#" останавливает плеер):
Проверка на Android 15 на еще одном видео-формате OGV (OGG-video): андроид загружает его в MediaMetadataRetriever без ошибок, но кадры из него не достает, и длительность получить не удается. Дополнительно будем считать загрузку видео неудачной и выдавать сообщение об этом если после запроса длительности он был неудачным (и длительность так и осталась равная нулю) или вернул ноль (хз как на каких моделях телефонов будет).
На подписи к левой софт-клавише "Отмену" заменим на "Выход", какая отмена когда уже снял десяток кадров в файлы, этого уже не отменить.
Сделаем два режима съемки - в паинткад и в файл. Переключение между ними сделаем по Джойстику Влево/Вправо или по нажатию на переключатель. Сам переключатель нарисуем вместо заголовка окна (эдакий переключаемый заголовок, со стрелками по бокам). Т.к. варианта всего два, то что жми на его правую часть, что на левую - переключает по очереди первый и второй режимы съемки.
Когда снимаем в паинткад - то имя файла (номер кадра и JPG/PNG формат) показывать не будем:
А когда снимаем в файл - то будем:
Проверяем оба режима.
1) Съемка кадра в PaintCAD
Поставим макс.размер рисунка 800x800. Откроем видео 1080x1920. Докрутим видео до какой-то позиции и нажмем "Снимок":
Паинткад снимает кадр, видит что он больше максимального размера рисунка и тогда масштабирует этот кадр так, чтобы он влез в максимальный размер. Получается кадр из видео размером 450x800:
2) Съемка кадра в файл
Откроем это же видео 1080x1920. Выбираем кадры и жмем "Снимок". Кадр снимается и сохраняется в файл. Счетчик в правом нижнем углу увеличивается на 1. Чтобы его сбросить - нужно еще раз открыть этот файл ("Обзор" по правому софту и выбрать его). Снимем в файлы, например, 3 кадра. Следующий был бы 4.jpg, но его снимать не будем:
Названия файлов будем в андроид-модуле съемки кадров делать как в модуле съемки кадров для явы: при имени видеофайла vid.mp4 кадры будут vid-1.jpg, vid-2.jpg, vid-3.jpg и т.д. Посмотрим в окошке файлового менеджера - вот они лежат рядом с исходным видеофайлом:
Подсказку по управлению оставим и для андроида (показывается после выбора видеофайла в файловом менеджере перед переходом к окошку Video3GP2), но только пропишем функции кнопок для андроид-окошка:
Внизу формат JPG или PNG все-таки нужно показывать и для режима съемки кадра на рисунок в PaintCAD, т.к. по нему можно определить пережимается ли кадр в JPG или вытаскивается в паинткад через PNG (без потерь качества после вытаскивания из MediaMetadataRetriever-а). Отобразим только формат (JPG или PNG) большими буквами в правом нижнем углу:
Теперь окно, вроде бы, доделано. Проверяем на других андроидах.
Samsung Galaxy Ace на Android 2.3.3 - снимем с его же камеры mp4-видео и попытаемся его открыть. Открывает, узнает длительность видео правильно, показывает кадр:
НО какое бы не выбирать смещение во времени - отдает один и тот же кадр.
В интернете пишут, что MediaMetadataRetriever впервые появился в Android 2.3 и в старых андроидах сильно зависел от конкретной реализации, конкретного телефона. Сначала появился запрос кадра
getFrameAtTime(время в мкс), и нельзя было указать брать ключевые опорные кадры или любой ближайший. Потом в 2.3.3 появились методы какой брать кадр (ближайший любой, ближайший ключевой с любой стороны указанной временной отметки в мкс, из предыдущих кадров относительно отметки, из следующих кадров).
В общем, берет какой-то один кадр и показывает)
Пробуем каждый раз для получения кадра создавать новый MediaMetadataRetriever, открывать видеофайл, просить один единственный кадр по нужному смещению во времени, закрывать видеофайл - не помогает
Пробуем отследить не происходили ли какие-нибудь исключения - нет, не происходили, он работает как будто все ок, только выдает одно и то же изображение для любого смещения во времени.
Пробуем переключить метод забора кадра на ближайший ключевой кадр - опять выдает только один кадр для любого смещения во времени.
Пробуем запросить кадр старым методом из Android 2.3
getFrameAtTime(время в мкс) - снова выдает только один кадр для любого смещения во времени.
Казалось бы "какой глючный MediaMetadataRetriever, не показывает кадры, может быть мы что-то не то делаем, надо все починить". Но с 3GP видеофайлами он ведет себя иначе)
При проигрывании 3GP, снятого на старом сименсе в 2006 году, он то рисует нормальный кадр (но статичный, не меняющийся), то рисует зеленые кадры, и даже зеленые кадры с разноцветным мусором. И вот находим это место, где он перескакивает на зеленый. Бегаем по 40 мс влево-вправо от этого места.
Последняя временная отметка, где кадр статичный, но выглядит нормально:
И на 40 мс позже - зеленый экран:
И если перейти на 40 мс назад - то опять будет красивый кадр. Т.е. декодер видео в андроиде есть, он работает, на каждую временную отметку у него есть в ответ конкретный кадр. И если бы он нормально декодировал, он бы получил все кадры нормально рисующиеся и меняющиеся в зависимости от смещения по времени. И точно также, как выше прыгает с нормального кадра на зеленый, прыгал бы с одного нормального кадра на другой нормальный и все бы было ок.
Значит, действительно, в старых андроидах MediaMetadataRetriever работает так себе. Кадры выдает отлично, опции MediaMetadataRetriever.OPTION_CLOSEST как-то слушается, исключений не выдает, но в возвращаемых кадрах нарисован либо первый неменяющийся кадр из видеофайла, либо зеленый фон/мусор и т.д. И его функционирование может вообще зависеть не только от версии андроида, а еще и от модификации андроида на конкретном телефоне. На одном телефоне с андроидом 2.3.3 покажутся статичные кадры, на другом мусорные, на третьем все будет ок (если там каким-то образом все допилено в MediaMetadataRetriever разработчиками прошивки до работоспособного состояния).
Поэтому чинить ничего не надо, все в порядке. Поэтому на некоторых старых андроидах, вероятно, функция "Снять 3GP/MP4 кадр" будет вытаскивать только один кадр или шумы/мусор.
И, кстати, если с mp4 на новых андроидах все отлично, то с 3gp все не так радужно - даже на новых андроидах редкие (опорные) кадры рисуются нормально, остальные как будто должны накладываться на тот опорный по очереди, но андроид этого не понимает и, затирая опорный кадр следующими кадрами, начинает рисовать только измененные фрагменты на зеленом фоне, сером фоне, в странной искаженной палитре. Видимо, с декодированием 3GP в андроидах беда (это видно и по встроенному в телефоны видеоплееру - они 3GP рисуют также некорректно).
С этим ничего не поделаешь если только не написать свой декодер для 3GP, а для старых андроидов и для mp4, а еще для ogv, avi со всеми кодеками, и еще для десятка других видеоформатов, и этого делать мы конечно же не будем))
Чтоб ничего не писать есть еще сторонние готовые модули типа FFmpegMediaMetadataRetriever, ну мы его тоже использовать не будем, т.к. он для современных андроидов только, и с ним тащить в проект кучу чужого кода, библиотек и т.п. У нас же просто универсальная явовская прога, работающая на андроиде с 2.3 до современных независимо от марки и битности процессора.
Остается только проверить эти глюки MediaMetadataRetriever-а на более широком спектре телефонов и андроидов, и понять (хотя бы) до какой версии андроида проблема сохраняется (и до какой версии кадры могут быть статичные на протяжении всего видео или мусорные).
Проверка окна Video3GP2 (android) на тестовых телефонах
Возьмем четыре небольших видеофайла - два 3GP разных размеров (посмотрим как их криво открывает андроид и открывает ли нормально хоть на одной из версий андроида), один MP4 (снятый на samsung galaxy ace), один AVI с запаковкой кодеком Xvid (для проверки умеет ли хоть какой-нибудь андроид открывать Microsoft AVI-файлы):
vgt1.3gp
Video: S263 128x96 12.5fps 51kbps [V: English [eng] (h263, yuv420p, 128x96, 51 kb/s)]
vgt2.3gp
Video: S263 176x144 (4:3) 14.5fps 111kbps [V: English [eng] (h263, yuv420p, 176x144, 111 kb/s)]
vgt3.mp4
Video: MPEG4 Video 640x480 23.73fps 1405kbps [V: VideoHandle [eng] (mpeg4 simple profile, yuv420p, 640x480, 1405 kb/s)]
vgt4.avi
Video: Xvid 320x240 30fps 278kbps [V: mpeg4 advanced simple profile, yuv420p, 320x240, 278 kb/s]
На андроиде - будем для каждого файла делать тесты:
1. Получаем один из результатов А, Б или В:
А) отлично: показывает много хороших кадров в зависимости от смещения по времени и, следовательно, дает выбрать один из них
Б) средненько: показывает один хороший статичный кадр, дополнительная проверка: есть ли мусор/битые/зеленые кадры при проигрывании или нет
В) всё плохо: не открылся файл с видео (сообщение про "не удалось...")
2. Проверка съемки кадра в PaintCAD (чтоб сразу на нем рисовать или обрабатывать эффектами)
3. Проверка съемки кадра в JPG-файл
4. Проверка съемки кадра в PNG-файл
1 - Android 2.3.3 - Samsung Galaxy Ace
Файл vgt1.3gp
Тест 1 - Результат Б "средненько". Статичный кадр.
Дополнительная проверка: в некоторых местах по времени мусор на зеленом фоне, в некоторых просто зеленый фон
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt2.3gp
Тест 1 - Результат Б "средненько". Тоже статичный кадр.
Дополнительная проверка: мусора нет, все видео - один и тот же кадр.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt3.mp4
Тест 1 - Результат Б "средненько". Опять статичный кадр)
Дополнительная проверка: мусора нет, все видео статичный кадр.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt4.avi
Тест 1 - Результат Б "средненько". AVI с Xvid-кодеком открывается. Но показывает только первый статичный кадр
Дополнительная проверка: мусора нет, все видео статичный кадр.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG

Итог Samsung Galaxy Ace на Android 2.3.3:
- на этом телефоне андроид смог показать на 3GP/MP4-тестовых файлах только один кадр средствами MediaMetadataRetriever
- при открытии 3GP может появляться мусор в кадрах
- AVI-файл, запакованный кодеком Xvid, здесь тоже открывается, но показывает только один кадр
2 - Android 4.2 - RugGear RG310
Файл vgt1.3gp
Тест 1 - Результат Б "средненько". Одиночный кадр, потом мусор
Дополнительная проверка: здесь мусор является движущимися изменяющимися фрагментами, которые надо бы рисовать поверх первого опорного кадра
Неожиданно встречается второй опорный кадр!
Потом опять идет мусор
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt2.3gp
Тест 1 - Результат Б "средненько". Тоже статичный кадр.
Дополнительная проверка: мусора нет, все видео - один и тот же кадр. Это если включать воспроизведение и быстро запрашивать кадры.
А если вручную идти по 1 секунде, то на 10 и на 20 секундах телефон выдает еще пару опорных кадров:
Т.е. когда запрашиваешь кадры быстро - он берет из кеша какого-то и отправляет первый кадр. А если медленно идешь, вручную перебираешь кадры - то выдает опорные, встречающиеся посередине. Но между ними - отдает статичный кадр. С 0 по 10 секунд - первый кадр, с 10 по 20 секунд - второй кадр, с 20 секунд до конца видео - третий кадр. Промежуточные кадры между опорными отдавать не хочет ни при переборе кадров вручную, ни при автоматическом проигрывании.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt3.mp4
Тест 1 - Результат Б "средненько". Статичный кадр
Дополнительная проверка: мусора нет, все видео статичный кадр. Если медленно перебирать кадры, то иногда выдает второй опорный кадр.
При этом непонятно в какой момент времени он стоит. При переборе кадров вперед сначала долго показывает кадры с первым, потом неожиданно включает второй. Мотаешь назад - долго показывает второй кадр, и совсем не в том месте, где переключался с первого на второй при перемотке вперед - включает опять первый. Зато если переходишь на нулевую отметку времени, а до этого отдавал второй кадр - то мгновенно включает первый. Видимо нулевая отметка времени нужна чтоб получить "предпросмотровое" изображение, и на нее кеширование не распространяется.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt4.avi
Тест 1 - Результат Б "средненько". AVI с Xvid-кодеком тут тоже открывается. И опять показывает только первый статичный кадр
Дополнительная проверка: мусора нет, все видео статичный кадр.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG

Итог RugGear RG310 на Android 4.2:
- на этом телефоне андроид смог показать на 3GP/MP4-тестовых файлах несколько опорных кадров средствами MediaMetadataRetriever. Вероятно, он их медленно извлекает, поэтому при множественных частых запросах кадров показывает один и тот же кадр из кеша. Если же вручную медленно идти по кадрам, то он покажет и другие опорные кадры. Промежуточные между опорными кадры показывать не хочет
- при открытии 3GP мусор в виде движущихся изменяющихся частей кадров на черном фоне
- AVI-файл, запакованный кодеком Xvid, открывает, но показывает и дает извлечь только один статичный кадр на всей протяженности видео
3 - Android (Mocor) 4.4.4 - Joy's S15
На этом телефоне с андроидом 4.4.4 результаты очень похожи на предыдущий телефон с андроидом 4.2
Файл vgt1.3gp
Тест 1 - Результат Б "средненько". Одиночный кадр, потом мусор. Потом еще одиночный опорный кадр.
Дополнительная проверка: здесь мусор, как и в андроиде 4.2 прошлого телефона, является движущимися изменяющимися фрагментами, которые надо бы рисовать поверх первого опорного кадра
Неожиданно встречается второй опорный кадр!
Потом опять идет мусор
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt2.3gp
Тест 1 - Результат Б "средненько". Тоже статичный кадр.
Дополнительная проверка: мусора нет, все видео - один и тот же кадр. А если вручную идти по 1 секунде, то на 10 и на 20 секундах, как и на андроиде 4.2, телефон выдает еще пару опорных кадров:
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt3.mp4
Тест 1 - Результат Б "средненько". Статичный кадр
Дополнительная проверка: мусора нет, все видео статичный кадр. Если медленно перебирать кадры, то иногда выдает второй опорный кадр.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt4.avi
Тест 1 - Результат Б "средненько". AVI с Xvid-кодеком тут тоже открывается. И опять показывает только первый статичный кадр
Дополнительная проверка: есть мусор. Похож на тот, что появляется при проигрывании 3GP. Движущиеся меняющиеся объекты рисуются, остальное черное.
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG

Итог Joy's S15 на Android (Mocor) 4.4.4:
- на этом телефоне андроид смог показать на 3GP/MP4-тестовых файлах несколько опорных кадров средствами MediaMetadataRetriever. Как на предыдущем андроиде 4.2
- при открытии 3GP мусор в виде движущихся изменяющихся частей кадров на черном фоне, как на андроиде 4.2
- AVI-файл, запакованный кодеком Xvid, открывает, показывает много кадров, но только опорные полные кадры, остальные - рисует мусором из изменяющихся частей кадров на черном фоне
4 - Android 5.0.1 - Asus ZenFone 2
Для того чтобы понять какие андроиды с какими видеоформатами работают - пройдемся по разным версиям, которых не было в десятке тестовых устройств.
Это Asus ZenFone 2 - лопатка на андроиде 5.0.1 с экраном 720x1280 пикселей:
Посмотрим как на андроиде 5 открываются различные видеоформаты для съемки кадров.
Файл vgt1.3gp
Тест 1 - Результат Б "средненько". Одиночный кадр, потом мусор. Потом еще одиночный опорный кадр.
Дополнительная проверка: здесь мусор, как и в других андроидах, является движущимися изменяющимися фрагментами, которые надо бы рисовать поверх первого опорного кадра
И опять виден второй опорный кадр
Потом опять идет мусор
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt2.3gp
Тест 1 - Результат А "отлично". Этот 3GP отличается от предыдущего только размером по ширине и высоте. Но если в том были проблемы с мусором, то тут андроид проигрывает его на ура и достает кадры с любого смещения во времени.
Дополнительная проверка: мусора нет, все отлично
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt3.mp4
Тест 1 - Результат А "отлично". Все кадры достаются и проигрывание идет по ним гладко, без пустых кадров, без мусора
Дополнительная проверка: мусора нет
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt4.avi
Тест 1 - Результат В "всё плохо", AVI с Xvid-кодеком на этом андроиде 5.0.1 просто не открывается

Итог Asus ZenFone 2 на Android 5.0.1:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров остальные кадры с мусором
- но второй 3GP файл, размером побольше по ширине/высоте, проигрывается отлично и любые кадры можно достать
- третий, MP4 тестовый файл, проигрывается тоже отлично и достаются любые кадры
- AVI-файл, запакованный кодеком Xvid не хочет открывать (видимо, нет поддержки кодека Xvid или вообще поддержки AVI-файлов)
5 - Android 7.0 - Fly FS522 Cirrus 14
Этот Fly FS522 Cirrus 14 - еще один смартфон, на андроиде 7.0 с экраном 1080x1920 пикселей:
Теперь посмотрим как на андроиде 7 открываются все эти видео.
Файл vgt1.3gp
Тест 1 - Результат Б "средненько". Одиночный кадр, потом мусор. Потом еще одиночный опорный кадр.
Дополнительная проверка: здесь мусор, как и в других андроидах, является движущимися изменяющимися фрагментами, которые надо бы рисовать поверх первого опорного кадра
И опять, как и на других телефонах, виден второй опорный кадр
Потом опять мусор
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt2.3gp
Тест 1 - Результат Б "средненько". Одиночный статичный кадр, потом все меняется на следующем опорном кадре через 10 секунд и еще через 10 секунд еще раз на одном опорном кадре
Дополнительная проверка: мусора нет, в этом плане все отлично
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt3.mp4
Тест 1 - Результат Б "средненько". Одиночный статичный кадр, потом все меняется на следующем опорном кадре
Дополнительная проверка: мусора нет
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG
Файл vgt4.avi
Тест 1 - Результат Б "средненько". Одиночный статичный кадр, AVI с Xvid-кодеком здесь открывается, но кадров кроме самого первого не показывает
Тест 2 - Съемка кадра в PaintCAD работает
Тест 3 - Съемка кадра в файл работает и в формате JPG, и в формате PNG

Итог Fly FS522 Cirrus 14 на Android 7.0:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров остальные кадры с мусором
- второй 3GP файл, размером побольше по ширине/высоте, тоже показывает только опорные кадры, между ними статичные предыдущие опорные кадры
- третий, MP4 тестовый файл, показывает тоже только опорные кадры (они где-то раз в секунду в видео лежат, вот каждую секунду изображение и меняется), промежуточные кадры не показывает
- AVI-файл, запакованный кодеком Xvid открывает, но показывает только один статичный кадр на все видео
6 - Android 9 - Soyes XS13
Итог Soyes XS13 на Android 9:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров и по прошествии второго кадра (отметка по времени 12 секунд) остальные кадры - с мусором
- второй 3GP файл, размером побольше по ширине/высоте, отлично проигрывается и любые кадры достаются
- третий, MP4 тестовый файл, тоже отлично проигрывается и любые кадры достаются
- AVI-файл, запакованный кодеком Xvid открывается, проигрывается и любые кадры достаются
7 - Android 11 - Xiaomi Redmi Note 8 Pro
Это телефон на Android 11, разрешение экрана 1080x2340. Результаты очень похожи на предыдущий Android 8.
Итог Xiaomi Redmi Note 8 Pro на Android 11:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров (0 c и 12 с) остальные кадры - с мусором
- второй 3GP файл, размером побольше по ширине/высоте, отлично проигрывается и любые кадры достаются
- третий, MP4 тестовый файл, тоже отлично проигрывается и любые кадры достаются
- AVI-файл, запакованный кодеком Xvid открывается, проигрывается и любые кадры достаются
8 - Android 12 - Xiaomi Duoqin F22 Pro
Итог Xiaomi Duoqin F22 Pro на Android 12:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров (0 c и 12 с) остальные кадры - с мусором
- второй 3GP файл, размером побольше по ширине/высоте, отлично проигрывается и любые кадры достаются
- третий, MP4 тестовый файл, тоже отлично проигрывается и любые кадры достаются
- AVI-файл, запакованный кодеком Xvid - не открывается
9 - Android 15 - Xiaomi Redmi Turbo 3 (Poco F6)
Итог Xiaomi Redmi Turbo 3 (Poco F6) на Android 15:
- на этом телефоне андроид смог показать на мелком 3GP тестовом файле несколько опорных кадров средствами MediaMetadataRetriever, кроме двух опорных кадров (0 c и 12 с) остальные кадры - с мусором зеленого цвета
- второй 3GP файл, размером побольше по ширине/высоте, отлично проигрывается и любые кадры достаются
- третий, MP4 тестовый файл, тоже отлично проигрывается и любые кадры достаются
- AVI-файл, запакованный кодеком Xvid не открывается
В итоге
Все андроиды поддерживают совершенно разные типы файлов и кодеков) Будет неудивительно, что если взять три телефона с одной и той же версией андроида - то они, наверное, будут по разному поддерживать/не поддерживать разные форматы в MediaMetadataRetriever, хоть андроид один и тот же. Все, скорее всего, зависит от того поддержку чего впихнул в андроид производитель телефона.
Ява-версию окошка Video3GP налаживать пока не будем, строчки внизу окна выровняли в рамках масштабирования. Ее и на сименсах не проверить толком (эмуляторы ведут себя не так, как телефоны, видео грузят, снимки не делают, видимо, какой-нибудь памяти не хватает чтоб запаковать и скинуть в JPG кадр), а на нокии N90 она не грузит файл (вообще не пытается, видимо никогда и не грузила, т.к. отладка была только на сименсах, как и тесты на настоящих устройствах). Позже надо будет почитать как же работать с видеоплеером под j2me и разобраться почему она не грузит и как оно должно работать.
А на андроидах все работает хорошо. Хотя бы в пределах поддерживаемых андроидом форматов на каждом устройстве.