Ale*_*nko 4 mp4 android opengl-es android-mediacodec
实际上我正在使用 OpenGL,我想将我所有的纹理都放在 MP4 中以压缩它们。
然后我需要从我的 Android 上的 MP4 中获取它
我需要以某种方式解码 MP4 并根据请求逐帧获取。
我找到了这个 MediaCodec
https://developer.android.com/reference/android/media/MediaCodec
和这个 MediaMetadataRetriever
https://developer.android.com/reference/android/media/MediaMetadataRetriever
但是我没有看到如何逐帧请求的方法......
如果有人用过MP4,请给我一个去哪里的方法。
PS我正在使用本机方式(JNI),所以怎么做都无所谓..Java或本机,但我需要找到方法。
编辑1
我制作了某种电影(只有一个 3d 模型),所以我每 32 毫秒更改一次几何和纹理。因此,在我看来,将 mp4 用于 tex 似乎是合理的,因为每个新帧(32 毫秒)都与原始帧非常相似......
现在我为一个模型使用 400 帧。对于几何,我使用 .mtr,对于 tex,我使用 .pkm(因为它针对 android 进行了优化),所以我有大约 350 个 .mtr 文件(因为有些文件包含子索引)和 400 个 .pkm 文件......
这就是为什么我要为 tex 使用 mp4 的原因。因为一个 mp4 比 400 .pkm 小得多
编辑2
请看一下 Edit1
实际上,我需要知道的只是可以MP4按帧读取的Android API ?也许某种getNextFrame()方法?
像这样的东西
MP4Player player = new MP4Player(PATH_TO_MY_MP4_FILE);
void readMP4(){
Bitmap b;
while(player.hasNext()){
b = player.getNextFrame();
///.... my code here ...///
}
}
Run Code Online (Sandbox Code Playgroud)
编辑3
我在 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));
}
Run Code Online (Sandbox Code Playgroud)
和这里执行时间
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
Run Code Online (Sandbox Code Playgroud)
这次以纳秒为单位 == +/- 200 毫秒......它非常缓慢......我需要大约 30 毫秒的帧。
所以,我认为这个方法是在CPU上执行的,所以请问是否有在GPU上执行的方法?
编辑4
我发现有MediaCodec课
https://developer.android.com/reference/android/media/MediaCodec
我也在这里发现了类似的问题MediaCodec 从视频中获取所有帧
我知道有一种方法可以按字节读取,但不能按帧读取...
所以,仍然有问题 - 是否有办法mp4按帧读取视频?
fad*_*den 12
The solution would look something like the ExtractMpegFramesTest, in which MediaCodec is used to generate "external" textures from video frames. In the test code, the frames are rendered to an off-screen pbuffer and then saved as PNG. You would just render them directly.
There are a few problems with this:
getFrameAtTime() method has less-than-desirable performance for the reasons noted above. You're unlikely to get better results by writing it yourself, although you can save a bit of time by skipping the step where it creates a Bitmap object. Also, you passed OPTION_CLOSEST_SYNC in, but that will only produce the results you want if all your frames are sync frames (again, clumsy database of JPEG images). You need to use OPTION_CLOSEST.如果您只是想在纹理上播放电影(或者您的问题可以减少到那个程度),Grafika有一些示例。一个可能相关的是 TextureFromCamera,它在可以缩放和旋转的 GLES 矩形上呈现相机视频流。您可以使用其他演示之一中的 MP4 播放代码替换相机输入。如果您只是向前玩,这会很好用,但如果您想跳过或向后走,就会遇到麻烦。
您所描述的问题听起来与 2D 游戏开发人员处理的问题非常相似。做他们所做的可能是最好的方法。
| 归档时间: |
|
| 查看次数: |
6293 次 |
| 最近记录: |