VideoCapturerAndroid allocates direct buffers so that the frame buffers can be used in C++ without a copy. However byte[] array = ByteBuffer.array() seems to point to the beginning of the underlaying buffer and that is what the camera fills. But it turns out that ByteBuffer.arrayOffset() returns an offset and it seems like the pointer returned by jni->GetDirectBufferAddress(j_frame). This cl reverts back to pass the byte[] to c++ and use jni->GetByteArrayElements to get the address of the buffer.

R=glaznev@webrtc.org, magjed@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/35349004

Cr-Commit-Position: refs/heads/master@{#8535}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8535 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
perkj@webrtc.org 2015-02-27 18:50:53 +00:00
parent 07dcf60ee0
commit 41d8fda12d
3 changed files with 33 additions and 25 deletions

View File

@ -33,7 +33,6 @@ import android.test.suitebuilder.annotation.SmallTest;
import org.webrtc.VideoCapturerAndroid.CaptureFormat;
import org.webrtc.VideoRenderer.I420Frame;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@SuppressWarnings("deprecation")
@ -79,12 +78,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
}
@Override
public void OnFrameCaptured(ByteBuffer frame, int rotation,
public void OnFrameCaptured(byte[] frame, int length, int rotation,
long timeStamp) {
assertTrue(frame.isDirect());
synchronized (frameLock) {
++framesCaptured;
frameSize = frame.capacity();
frameSize = length;
frameLock.notify();
}
}

View File

@ -178,13 +178,20 @@ void AndroidVideoCapturerJni::OnIncomingFrame_w(void* video_frame,
JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); }
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnFrameCaptured)
(JNIEnv* jni, jclass, jlong j_capturer, jobject j_frame,
(JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame, jint length,
jint rotation, jlong ts) {
void* bytes = jni->GetDirectBufferAddress(j_frame);
DCHECK(bytes != NULL);
jlong length = jni->GetDirectBufferCapacity(j_frame);
reinterpret_cast<AndroidVideoCapturerJni*>(
j_capturer)->OnIncomingFrame(bytes, length, rotation, ts);
jboolean is_copy = true;
jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy);
if (!is_copy) {
reinterpret_cast<AndroidVideoCapturerJni*>(
j_capturer)->OnIncomingFrame(bytes, length, rotation, ts);
} else {
// If this is a copy of the original frame, it means that the memory
// is not direct memory and thus VideoCapturerAndroid does not guarantee
// that the memory is valid when we have released |j_frame|.
DCHECK(false) << "j_frame is a copy.";
}
jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT);
}
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeCapturerStarted)

View File

@ -536,10 +536,11 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
rotation = 360 - rotation;
}
rotation = (info.orientation + rotation) % 360;
frameObserver.OnFrameCaptured(
videoBuffers.reserveByteBuffer(data, captureTimeMs),
rotation,
// Mark the frame owning |data| as used.
// Note that since data is directBuffer,
// data.length >= videoBuffers.frameSize.
videoBuffers.reserveByteBuffer(data, captureTimeMs);
frameObserver.OnFrameCaptured(data, videoBuffers.frameSize, rotation,
captureTimeMs);
}
@ -578,14 +579,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
// potentially stalling the capturer if it runs out of buffers to write to).
private static int numCaptureBuffers = 3;
private final Frame cameraFrames[];
public final int frameSize;
private static class Frame {
public final ByteBuffer buffer;
private final ByteBuffer buffer;
public long timeStamp = -1;
Frame(int width, int height, int format) {
int bufSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
buffer = ByteBuffer.allocateDirect(bufSize);
Frame(int frameSize) {
buffer = ByteBuffer.allocateDirect(frameSize);
}
byte[] data() {
@ -595,8 +596,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
FramePool(int width, int height, int format) {
cameraFrames = new Frame[numCaptureBuffers];
frameSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
for (int i = 0; i < numCaptureBuffers; i++) {
cameraFrames[i] = new Frame(width, height, format);
cameraFrames[i] = new Frame(frameSize);
}
}
@ -608,11 +610,11 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
}
ByteBuffer reserveByteBuffer(byte[] data, long timeStamp) {
void reserveByteBuffer(byte[] data, long timeStamp) {
for (Frame frame : cameraFrames) {
if (data == frame.data()) {
frame.timeStamp = timeStamp;
return frame.buffer;
return;
}
}
throw new RuntimeException("unknown data buffer?!?");
@ -639,7 +641,8 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
// Delivers a captured frame. Called on a Java thread owned by
// VideoCapturerAndroid.
abstract void OnFrameCaptured(ByteBuffer buffer, int rotation, long timeStamp);
abstract void OnFrameCaptured(byte[] data, int length, int rotation,
long timeStamp);
}
// An implementation of CapturerObserver that forwards all calls from
@ -657,14 +660,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
@Override
public void OnFrameCaptured(ByteBuffer byteBuffer, int rotation,
public void OnFrameCaptured(byte[] data, int length, int rotation,
long timeStamp) {
nativeOnFrameCaptured(nativeCapturer, byteBuffer, rotation, timeStamp);
nativeOnFrameCaptured(nativeCapturer, data, length, rotation, timeStamp);
}
private native void nativeCapturerStarted(long nativeCapturer,
boolean success);
private native void nativeOnFrameCaptured(long nativeCapturer,
ByteBuffer byteBuffer, int rotation, long timeStamp);
byte[] data, int length, int rotation, long timeStamp);
}
}