Андроидовское окошко Video3GP2 создано, работает, успешно оттестировано на многих андроидах (см. предыдущий пост). А вот в яве мы только подвинули две нижние строчки (размер кадра в пикселях и имя файла будущего снимка) чтобы они не улезали за панель софт-клавиш.
Попробуем его починим как-нибудь. Или улучшим. Или посмотрим почему оно так плохо себя ведет в эмуляторе.
Отладка на эмуляторе Siemens SL75
Сдвигаем видеовывод
Будем показывать в заголовке окна ошибки пока что.
Получаем размер видео как обычно:
Код: Выделить всё
sw=vc.getSourceWidth();
sh=vc.getSourceHeight();Код: Выделить всё
vc.setDisplayLocation(3 виртуальных пикселя,3 виртуальных пикселя + высота заголовка + 1 виртуальный пиксель);Код: Выделить всё
if (sw!=0) vc.setDisplaySize(ширина экрана - 6 виртуальных пикселей,(ширина экрана - 6 виртуальных пикселей)*sh/sw);
Ну это уже лучше, хотя бы заголовок окошка видно будет.
Почему не фоткает снимки
Сначала попробуем брать снимок без указания параметров:
Код: Выделить всё
byte[] b = vc.getSnapshot(null);
Слишком длинный текст, ничего не понятно) Выведем его в текстовое поле:

Пишет "Такая кодировка не поддерживается"
Пишут, что можно запросить все поддерживаемые кодировки через System.getProperty("video.snapshot.encodings") - но на сименс-эмуляторе оттуда возвращается пустая строка...
Попробуем снимем кадр с другой кодировкой наугад:
Код: Выделить всё
byte[] b = vc.getSnapshot("encoding=jpeg");Код: Выделить всё
byte[] b = vc.getSnapshot("encoding=png");Есть еще вариант bmp! Попробуем его:
Код: Выделить всё
byte[] b = vc.getSnapshot("encoding=bmp");Но вообще в коде было зашито что запрашиваем всегда vc.getSnapshot("encoding=jpeg"), но сименс, видимо, плевал на этот параметр и сохранялись всегда png файлы, поэтому у файлов выставлялось png расширение, а остальным телефонам назначалось jpg расширение для снимков (они-то, видимо, слушались параметра "encoding=jpeg").
Вообще надо сделать как в андроид-окошке на выбор PNG и JPG - и запрашивать, в зависимости от выбранного формата, "encoding=jpeg" или "encoding=png", и ловить ошибку если такой формат телефоном не поддерживается, выводя куда-нибудь что снять кадр не удалось.
Отладка на Nokia 7900
Проверим снимок с видео на реальной нокии Nokia 7900. Поставим сразу "encoding=jpeg" и попробуем снять снимок. Видим другую ошибку:


Пишет, что только съемка через capture://image поддерживает снимки. НО capture://image - это же работа с камерой. А для файлов нужно file://путь/файл.mp4. Получается на нокии 7900 кадры из видео снять и сохранить в файлы не получится.
Зато можно увидеть на первом из этих нокиевских скринов что нокия полноценно слушается кода установки размера видеовывода:
Код: Выделить всё
if (sw!=0) vc.setDisplaySize(ширина экрана - 6 виртуальных пикселей,(ширина экрана - 6 виртуальных пикселей)*sh/sw);Отладка на Nokia N90
На ней 3GP файл вообще не открывается. И попытка снимка выдает ошибку "0". Ну раз видео не открылось, то и снимать нечего.

Отладка на эмуляторе Siemens EL71
Открываем видео:

Иногда эмулятор говорит что не может ничего снять... и извиняется =)


Вероятно тут видео кончилось или сбой какой-то.
А иногда, как обычно, пишет что не поддерживает кодировку:

В общем, на нем тоже ничего не снять)
Переделываем интерфейс в подобный андроидовскому окошку Video3GP2
В любом случае, на реальных сименсах снимались снимки в файлы, да и на других моделях съемка кадров может и работать на каком-нибудь формате файла (jpg, png, bmp). Поэтому переделаем окно под более удобный вид для этих телефонов.
Нужно:
- сделать по кнопке "0" выбор формата (encoding) из известных "jpeg", "png", "bmp" и формат по умолчанию "???" (когда вместо формата передаем в getSnapshot параметр null и телефон должен сам выбрать формат и выдать снимок в этом формате, расширение файла в этом случае назначим ".pic", но даже если внутри будет записан PNG или JPG - по "Открыть ???" он должен загрузиться в паинткад). С выбором формата менять и расширение файла
- контролировать сбой загрузки видео и выводить сообщение что его не удалось загрузить
- контролировать сбой съемки кадра и выводить сообщение что кадр не удалось снять (тогда пользователь попробует сменить формат по "0" и снять кадр в другом формате)
- выводить слева внизу размер видео по ширине/высоте
- выводить справа внизу номер кадра + расширение без приписки имени видео
- сделать отчет номера кадра с 1, а не с 0
- сделать более хитрый подбор ширины/высоты видеопотока для vc.setDisplaySize (как в андроидовском окошке), учитывающий и ширину, и высоту экрана и доступное на экране место, чтоб видео не залезало на нижнюю строку с информацией и панель с подписями софт-клавиш
Сделаем окно Video3GP для j2me такое же по интерфейсу как окно Video3GP2 для андроида.
У j2me плеера есть функции получения текущей временной позиции просмотра в микросекундах p.getMediaTime(), длительности видео в микросекундах p.getDuration(). Также есть функции отрисовки видеопотока в нужном месте экрана и с нужным размером (чтоб сделать масштабирование по кнопке "*" на весь экран).
Есть одна проблема - эти функции на некоторых телефонах поддерживаются, а на некоторых нет.
Если телефон не знает текущую позицию просмотра, то он возвращает TIME_UNKNOWN равное -1 в ответ на вызов getMediaTime(). Если он не знает текущую длительность видео, то он тоже возвращает TIME_UNKNOWN равное -1 в ответ на getDuration().
А уж рисует видео после указания сдвига на экране и размера растра видео - вообще где захочет) Ну будем на хорошие телефоны надеяться, которые все поддерживают и правильно рисуют.
Обработаем неизвестную длительность как невозможность по клику на слайдере на экране, и отображение на нем длительности как "??? с". А если неизвестна и текущая временная позиция плеера, вообще будем писать на слайдере "??? с" без всякой черты, разделяющей текущую позицию и длительность.
И перемотка должна вроде бы работать по p.setMediaTime(timemks), но может не поддерживаться телефоном и тогда ничего не перемотаешь.
Вот что получилось
Nokia N90
Nokia N90 не хочет открывать ни один из видео файлов (3gp мелкий или побольше, mp4 большой):

Nokia 7900
Окошко с подсказками по кнопкам теперь такое же как в андроиде. По кнопке 0 переключается JPG, PNG, а дальше еще BMP и ??? (формат по умолчанию, выбираемый самим телефоном, сохраняет кадры в PIC-файлы, а внутри на самом деле или PNG, или JPG, смотря что конкретный телефон считает форматом по умолчанию). В подсказке не будем расписывать все 4 формата, т.к. BMP это вообще редкость (огромные по объему кадры в памяти, но пишут что такое бывает на каких-то телефонах), а ??? это только если JPG и PNG снимать не хочет, то можно попробовать попросить снять формат "по умолчанию", переключившись по "0" на него.

Эта нокия идеально выполняет сдвиг и масштабирование растра видеопотока на экране, но не может сообщить сколько длительность видео, поэтому на слайдере отображается "текущая позиция / ??? с", а слайдер всегда заполнен полностью (т.к. не может нарисовать сколько из длительности уже проиграно и в каком месте видео по времени мы находимся относительно всего видео).
Без масштабирования по звездочке - растр видеопотока посередине свободной области окна:

После включения масштабирования - нокия натягивает видеопоток со сглаживанием на требуемый паинткадом размер, показывает видео с хорошим FPS, не падающим от масштабирования:

Но т.к. она, как показывалось выше, снимает только кадры с потока с камеры capture://image (и говорит об этом в исключении, которое возникает при попытке снять кадр), то паинткад видит что произошла ошибка и пишет об этом бледно-красным текстом "Ошибка съемки" на 3 секунды на переключателе режима сверху окна и при первой ближайшей перерисовке окна сообщение исчезнет само (например, если идет проигрывание видео по #, и окно часто перерисовывается, отображая слайдер с текущим положением проигрывания во времени). Если попереключать переключатель режима по ДжойВправо-ДжойВлево, то текст ошибки пропадет сразу при переключении, не дожидаясь трех секунд. А если произведение выключено - ошибка будет висеть до любой первой перерисовки:

Если переключить переключатель во второй режим - то включится съемка в файл (прямо как в аналогичном окошке андроида Video3GP2):

Но снимать кадры в файлы от переключения режима Нокия, конечно, не станет. Она снимает только кадры с видеопотока камеры, а из файла с видео - снимать не хочет.
Эмулятор Siemens SL75
Окно с подсказками по клавишам теперь новое как и на нокии. Короткие строчки сверху, а длинные снизу, чтоб не залезли на значок на узких экрана с большими буквами шрифта.

Само окно при запуске проигрывания теперь пытается перерисовываться (каждые 300 мс), и на сименсе почему-то закрашивает плеер =) На нокии он всегда рисовался поверх того, что рисовалось на экране мидлетом в яве.

С другой стороны - это даже хорошо. Не будем закрашивать фоном окна весь экран. А четырьмя прямоугольниками нарисуем фон сверху над видеопотоком, фон снизу под видеопотоком, фон слева от видеопотока и фон справа от видеопотока. А саму область видео закрашивать не будем. Пусть там будет нечто, что по идее должно полностью закраситься видеопотоком. На нокии проблем не будет. На сименсе - это позволит видеопотоку там отрисовываться когда он захочет и никто не будет его закрашивать фоном окна. И если он будет кривого размера (не такого, какого попросил паинткад) и в кривой позиции (не в той, в которой попросил паинткад), но закраска фоном обрежет куски видеопотока, торчащие за рассчитанную область видеопотока.
С первого проигрывания в эмуляторе видеопоток не хочет рисоваться - остается желтое (цвет системного фона окошек) поле:

На настоящем телефоне проигрывалось сразу, с первого запуска (помнится проблем с этим не было). На эмуляторе же - надо дождаться полного проигрывания, и в конце видео появляется сплющенное видео, внизу мусор, а временная позиция встает на месте и даже зашкаливает за длину видео (эх, эмулятор, глючный какой-то):

Повторное проигрывание - появляется видео, проигрываемое с нуля, уже без мусора:

Ни один формат (JPG, PNG, BMP, ???), выбранный по кнопке "0", не дает ничего снять, прямо как на нокии 7900 =) Ну это все эмуль виноват, вообще физический настоящий сименс снимать кадры-то умеет:

Кстати, что-то этот эмулятор сименса плохо реагирует на включение проигрывания/паузы, много раз понажимаешь - плеер высыпает какое-нибудь исключение в лог и окно виснет, а то и паинткад, а то и весь эмуль. Да и без виртуальной клавиатуры (на которой подсказки-значки на кнопках) мало какой человек вспомнит с того окошка с подсказкой по кнопкам, которое показывается перед этим окном съемки кадров, что включить проигрывание можно по нажатию "#".
Поэтому сделаем в явовской версии Video3GP небольшое отличие от андроидовского Video3GP2 - при открытии видео и попадании в окошко съемки кадров сразу будет запускаться проигрывание как раньше. Остается, по идее, только нажать джойстик (а на это подсказка внизу окна показывается со словом "Снимок") и снять кадр, затащив его в паинткад.
А уже тем, кто запомнил управление, будет можно переключиться на съемку в файл, остановить/продолжить показ видео и т.д.
Эмулятор Benq-Siemens EL71
Окошко с подсказками по клавишам выглядит нормально:

А вот с видео этот эмулятор уже ничего не слушается, в отличие от SL75. Показывает видео со сдвигом, по горизонтали равным запрошенному, а по вертикали - ниже примерно на 1 строку текста. И вообще не хочет обрезать видео, показывает целиком, поверх окошка. Оно вылезает из бледно-фиолетового прямоугольника, в пределах которого должно рисоваться:

Все 4 формата снимать не хочет (JPG, PNG, BMP, ???):

MP4 размером 640x480 открывает и даже пытается ужать под требуемую область, но у него не выходит) Видимо, сжимает в какое-то стандартное количество раз, например, в 2 раза:

Ну ладно, как-то работает на эмуляторе Benq-Siemens EL71. Кадры не снимает во всех форматах из MP4 тоже =) На реальном бы устройстве посмотреть вместо эмулятора. Но для этого надо сначала сократить требования паинткада по памяти каким-то образом.
Теперь модуль Video3GP работает и на андроиде, и на яве с новыми возможностями. Андроидовская версия проверена. Явовская - проверена временем, код сохранения кадров не изменялся. Если найти такой java-телефон, который снимает кадры - то этот модуль будет снимать кадры из видео и класть в PNG/JPG/BMP/PIC-файлы в папку где лежит видео
Масштабируем следующее окно
Дальше идет модуль VideoBMP и еще один похожий модуль VideoGIF:

Ревизия окон VideoBMP и VideoGIF
Рассмотрим VideoBMP, а править будем сразу оба, т.к. они похожи.
Это окно VideoBMP используется при массовой конвертации BMP-файлов в GIF-файлы (чтобы потом собрать из них GIF-анимацию, например). Работает эта функция так:
1) в главном меню выбрать "0"-"Обработка"-"BMPs->GIFs". Появится указание что делать дальше - указать папку с готовыми 1.bmp, 2.bmp, 3.bmp и так далее:

2) после выбора в файловом менеджере одного из нумерованных файлов 1.bmp, 2.bmp... появляется окно VideoBMP. Из-за особенностей построения экономного кода оно пошагово отрисовывается, но андроид ляпает пару перерисовок при старте окна - и окно отрисовывается, стирается, а потом поверх окна (которое уже стерто) рисуется только список найденных BMP-файлов. Вообще это было сделано чтоб по движению по списку рисовать только список, а окно больше не рисовать. Но в андроиде это выглядит после двойной перерисовки и пропадания окна вот так:

Убеждаемся что их ровно столько, сколько надо. И жмем правый софт чтобы продолжить. Ну или левый чтобы отменить все это.
3) дальше вызывается открытие каждого BMP и сохранение в соответствующий GIF. В заголовке окна с прогрессом сохранения пишется какой из скольких файлов обрабатывается. Интересно что с полосой прогресса - 100%, но полоска в отрицательную сторону нарисована:

4) ну и в конце радостное окно об успешном завершении конвертации:

И если BMP-файлы не с именами 1.bmp, 2.bmp - то этот модуль их еще и переименовывает в 1.bmp, 2.bmp)
Починим процедуру отрисовки окна VideoBMP чтобы оно отрисовывалось полностью. И посмотрим что там с полосой прогресса при такой пачечной обработке BMP-файлов.
Вставили процедуру перерисовки окошка всегда для андроид-устройств. И еще в процедурах отрисовки полос прогресса теперь контролируем чтоб не было текущее значение меньше нуля (тогда рисуем как при нуле) или больше максимума (тогда рисуем как максимум).
Модуль VideoGIF - для сборки анимированных GIF-файлов. Оно похож по строению на VideoBMP, сразу и в нем тоже исправим перерисовку.
Еще в обоих модулях поправим расчет высоты списка так, чтобы снизу до полосы с подписями софт-клавиш гарантированно был выпуклый край окна (2 виртуальных пикселя) + зазор до списка размером 1 виртуальный пиксель.
А еще в окне Explorer тоже подправим зазор списка, чтобы внизу до края экрана был гарантированно был выпуклый край окна (2 виртуальных пикселя) + зазор до списка размером 1 виртуальный пиксель
Получилось в VideoBMP:

Получилось в VideoGIF:



























































































































































































































































