На самом деле я работаю с OpenGL, и я хотел бы поместить все свои текстуры в MP4 для их сжатия.
Затем мне нужно получить его из MP4 на моем Android
Мне нужно как-то декодировать MP4 и получать кадр за кадром по запросу.
Я нашел это MediaCodec
https://developer.android.com/reference/android/media/MediaCodec
и это MediaMetadataRetriever
https://developer.android.com/reference/android/media/MediaMetadataRetriever
Но я не видел подход, как запросить кадр за кадром ...
Если есть кто-то, кто работал с MP4, пожалуйста, дайте мне способ, куда идти.
PS Я работаю с собственным способом (JNI), поэтому не имеет значения, как это сделать .. Java или нативный, но мне нужно найти способ.
EDIT1
Я делаю какой-то фильм (только одну 3d модель), поэтому я меняю свою геометрию, а также текстуры каждые 32 миллисекунды.Поэтому мне кажется разумным использовать mp4 для tex, потому что каждый новый кадр (32 миллисекунды) очень похож на предыдущий ...
Теперь я использую 400 кадров для одной модели.Для геометрии я использую .mtr, а для tex я использую .pkm (потому что он оптимизирован для Android), поэтому у меня есть около 350 файлов .mtr (потому что некоторые файлы содержат субиндекс) и 400 .pkm файлов ...
Это причина, почему я собираюсь использовать mp4 для tex.Потому что один mp4 намного меньше, чем 400 .pkm
EDIT2
Пожалуйста, посмотрите на Edit1
На самом делевсе, что мне нужно знать, это API Android, который может читать MP4
по кадрам?Может быть, какой-то getNextFrame()
метод?
Примерно так
MP4Player player = new MP4Player(PATH_TO_MY_MP4_FILE);
void readMP4(){
Bitmap b;
while(player.hasNext()){
b = player.getNextFrame();
///.... my code here ...///
}
}
EDIT3
Я сделал такую реализацию на Java
public static void read(@NonNull final Context iC, @NonNull final String iPath)
{
long time;
int fileCount = 0;
//Create a new Media Player
MediaPlayer mp = MediaPlayer.create(iC, Uri.parse(iPath));
time = mp.getDuration() * 1000;
Log.e("TAG", String.format("TIME :: %s", time));
MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
mRetriever.setDataSource(iPath);
long a = System.nanoTime();
//frame rate 10.03/sec, 1/10.03 = in microseconds 99700
for (int i = 99700 ; i <= time ; i = i + 99700)
{
Bitmap b = mRetriever.getFrameAtTime(i, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
if (b == null)
{
Log.e("TAG", String.format("BITMAP STATE :: %s", "null"));
}
else
{
fileCount++;
}
long curTime = System.nanoTime();
Log.e("TAG", String.format("EXECUTION TIME :: %s", curTime - a));
a = curTime;
}
Log.e("TAG", String.format("COUNT :: %s", fileCount));
}
и здесь время выполнения
E/TAG: EXECUTION TIME :: 267982039
E/TAG: EXECUTION TIME :: 222928769
E/TAG: EXECUTION TIME :: 289899461
E/TAG: EXECUTION TIME :: 138265423
E/TAG: EXECUTION TIME :: 127312577
E/TAG: EXECUTION TIME :: 251179654
E/TAG: EXECUTION TIME :: 133996500
E/TAG: EXECUTION TIME :: 289730345
E/TAG: EXECUTION TIME :: 132158270
E/TAG: EXECUTION TIME :: 270951461
E/TAG: EXECUTION TIME :: 116520808
E/TAG: EXECUTION TIME :: 209071269
E/TAG: EXECUTION TIME :: 149697230
E/TAG: EXECUTION TIME :: 138347269
На этот раз в наносекундах == +/- 200 миллисекунд ... Это очень медленно ... Мне нужно около 30 миллисекунд на кадр.
Итак, я думаю, что этот метод выполняется на процессоре, поэтому спросите, есть ли метод, который выполняется на GPU?
EDIT4
Я обнаружил, что существует MediaCodec
класс
https://developer.android.com/reference/android/media/MediaCodec
Также я нашел подобный вопрос здесь MediaCodec получает все кадры из видео
Я понял, что есть способ чтения по байтам, но не по кадрам ...
Итак, еще вопрос - есть ли способ прочитать mp4
видео по кадрам?