Android 将大型ByteBuffer的部分存储到文件中
我已经实现了一个循环缓冲区或循环缓冲区,以总帧分辨率1280x720存储250帧原始视频数据。作为缓冲区,我使用ByteBuffer类。缓冲区使用循环器在单独的线程中运行,每个新帧都通过消息传递给线程处理程序对象。当达到限制时,位置设置为0,并且从一开始就覆盖整个缓冲区。这样,缓冲区总是包含最后250个视频帧 由于所需的堆空间大约为320 MB,因此我在清单中使用了标记android:largeHeap=true 现在我们来讨论这个问题。循环运行良好,它消耗的堆空间略小于允许的大小,这对我来说是可以接受的。但在某个时候,我希望将整个缓冲区存储到原始二进制文件中,同时考虑缓冲区的当前位置 让我用一个小图表来解释: 循环缓冲区如下所示: |=======================================================================================尾部============| 0---------buffer.position---------buffer.limit 在保存时,我想首先将尾部存储到文件中,因为它包含视频的开头,然后是头部,直到当前buffer.position。由于ByteBuffer堆空间已满,我无法分配更多的字节数组来从中提取数据,因此,我必须直接将ByteBuffer写入文件 目前ByteBuffer只允许使用完全写入方法写入文件。有人知道解决办法吗?或者对于我的任务有更好的解决方案吗 我将在下面给出我的代码:Android 将大型ByteBuffer的部分存储到文件中,android,memory-management,io,Android,Memory Management,Io,我已经实现了一个循环缓冲区或循环缓冲区,以总帧分辨率1280x720存储250帧原始视频数据。作为缓冲区,我使用ByteBuffer类。缓冲区使用循环器在单独的线程中运行,每个新帧都通过消息传递给线程处理程序对象。当达到限制时,位置设置为0,并且从一开始就覆盖整个缓冲区。这样,缓冲区总是包含最后250个视频帧 由于所需的堆空间大约为320 MB,因此我在清单中使用了标记android:largeHeap=true 现在我们来讨论这个问题。循环运行良好,它消耗的堆空间略小于允许的大小,这对我来说是
public class FrameRecorderThread extends Thread {
public int MAX_NUMBER_FRAMES_QUEUE = 25 * 10; // 25 fps * 10 seconds
public Handler frameHandler;
private ByteBuffer byteBuffer;
byte[] image = new byte[1382400]; // bytes for one image
@Override
public void run() {
Looper.prepare();
byteBuffer = ByteBuffer.allocateDirect(MAX_NUMBER_FRAMES_QUEUE * 1382400); // A lot of memory is allocated
frameHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Store message content (byte[]) to queue
if(msg.what == 0) { // STORE FRAME TO BUFFER
if(byteBuffer.position() < MAX_NUMBER_IMAGES_QUEUE * 1382400) {
byteBuffer.put((byte[])msg.obj);
}
else {
byteBuffer.position(0); // Start overwriting from the beginning
}
}
else if(msg.what == 1) { // SAVE IMAGES
String fileName = "VIDEO_BUF_1.raw";
File directory = new File(Environment.getExternalStorageDirectory()
+ "/FrameRecorder/");
directory.mkdirs();
try {
FileOutputStream outStream = new FileOutputStream(Environment.getExternalStorageDirectory()
+ "/FrameRecorder/" + fileName);
// This is the current position of the split between head and tail
int position = byteBuffer.position();
try {
// This stores the whole buffer in a file but does
// not respect the order (tail before head)
outStream.getChannel().write(byteBuffer);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
Log.e("FMT", "File not found. (" + e.getLocalizedMessage() + ")");
}
}
else if(msg.what == 2) { // STOP LOOPER
Looper looper = Looper.myLooper();
if(looper != null) {
looper.quit();
byteBuffer = null;
System.gc();
}
}
}
};
Looper.loop();
}}
提前非常感谢 只需创建一个小节并将其写入文件
或者调用set Length,然后写入它,然后将其设置回原来的值。好的,与此同时,我进一步研究了一下,找到了一个解决方案
我使用的不是ByteBuffer对象,而是简单的byte[]数组。开始时,我分配帧所需的所有堆空间。在存储时,我可以使用当前位置写入缓冲区的头部和尾部。这是可行的,比预期的要容易 你能给我举个例子吗?生成一个小节正是这里的问题,所以我不知道怎么做。只需创建一个具有所需偏移量和长度的新小节,使用旧小节作为src。我不能这样做,因为我需要为此分配内存。不幸的是,堆空间已满。但我可以试着按字节来做。或者有更好的解决方案吗?调用长度大小,写块,然后调用翻转