/*
* Copyright 2015 Constant Innovations Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.constantinnovationsinc.livemultimedia.utilities;
import android.os.MemoryFile;
import android.util.Log;
import java.io.IOException;
public class SharedVideoMemory {
public int sharedVideoFramesBuffer = 0;
public MemoryFile mSharedMemFile = null;
/**
* MemoryFile is a wrapper for the Linux ashmem driver.
* MemoryFiles are backed by shared memory, which can be optionally
* set to be purgeable.
* Purgeable files may have their contents reclaimed by the kernel
* in low memory conditions (only if allowPurging is set to true).
* After a file is purged, attempts to read or write the file will
* cause an IOException to be thrown.
*/
private static String TAG = "MemoryFile";
private int mFrameCount = 0;
private int mProcessedFrames = 0;
private int mFrameSize = -1;
/**
* Allocates a new ashmem region. The region is initially not purgable.
*
* @param name optional name for the file (can be null).
* @param frameSize how many frame to store
* @param length of the memory file in bytes.
* @throws IOException if the memory file could not be created.
*/
public SharedVideoMemory(String name, int frameSize, int length) throws IOException {
mSharedMemFile = new MemoryFile(name, length);
mFrameSize = frameSize;
}
/**
* Closes the memory file. If there are no other open references to the memory
* file, it will be deleted.
*/
public void close() {
mSharedMemFile.close();
}
public boolean isEmpty() {
return (mSharedMemFile.length() == 0);
}
public int getFrameCount() {
return mFrameCount;
}
public int getProcessFramesCount() {
return mProcessedFrames;
}
public int getFrameSize() {
return mFrameSize;
}
public synchronized void lockMemory() {
try {
if (mSharedMemFile != null) {
mSharedMemFile.allowPurging(false);
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
public synchronized void clearMemory() {
try {
if (mSharedMemFile != null) {
mSharedMemFile.allowPurging(true);
}
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
@SuppressWarnings("unused")
public boolean getNextFrame(int frameNum, byte[] buffer) {
Boolean mFlag = false;
if (buffer == null) {
Log.e(TAG, "Cannot return video frame into a null buffer that was passed to getNextFrame()");
return false;
}
if (frameNum == mFrameCount) {
Log.e(TAG, "You have now read to the end of sharedMemory file");
return false;
}
try {
Log.d(TAG, "About to read from shared file for frame:framesize is: " + frameNum + "," + mFrameSize);
int readBytes = mSharedMemFile.readBytes(buffer, frameNum * mFrameSize, 0, mFrameSize);
if (readBytes == mFrameSize) {
mFlag = true;
mProcessedFrames++;
} else {
Log.e(TAG, "bytes read are mot the same as frame size!");
}
} catch (IndexOutOfBoundsException | IOException e) {
Log.e(TAG, e.getMessage());
mFlag = false;
}
return mFlag;
}
/**
* Write bytes to the memory file.
* Will throw an IOException if the file has been purged.
*
* @param buffer byte array to write bytes from.
* @param srcOffset offset into the byte array buffer to write from.
* @param destOffset offset into the memory file to write to.
* @param count number of bytes to write.
* @throws IOException if the memory file has been purged or deactivated.
*/
public void writeBytes(byte[] buffer, int srcOffset, int destOffset, int count) {
try {
mSharedMemFile.writeBytes(buffer, srcOffset, destOffset, count);
mFrameCount++;
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
public Boolean isLastFrame() {
return (mFrameCount == mProcessedFrames);
}
}