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:
parent
07dcf60ee0
commit
41d8fda12d
@ -33,7 +33,6 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
import org.webrtc.VideoCapturerAndroid.CaptureFormat;
|
import org.webrtc.VideoCapturerAndroid.CaptureFormat;
|
||||||
import org.webrtc.VideoRenderer.I420Frame;
|
import org.webrtc.VideoRenderer.I420Frame;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@ -79,12 +78,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnFrameCaptured(ByteBuffer frame, int rotation,
|
public void OnFrameCaptured(byte[] frame, int length, int rotation,
|
||||||
long timeStamp) {
|
long timeStamp) {
|
||||||
assertTrue(frame.isDirect());
|
|
||||||
synchronized (frameLock) {
|
synchronized (frameLock) {
|
||||||
++framesCaptured;
|
++framesCaptured;
|
||||||
frameSize = frame.capacity();
|
frameSize = length;
|
||||||
frameLock.notify();
|
frameLock.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,13 +178,20 @@ void AndroidVideoCapturerJni::OnIncomingFrame_w(void* video_frame,
|
|||||||
JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); }
|
JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); }
|
||||||
|
|
||||||
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnFrameCaptured)
|
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) {
|
jint rotation, jlong ts) {
|
||||||
void* bytes = jni->GetDirectBufferAddress(j_frame);
|
jboolean is_copy = true;
|
||||||
DCHECK(bytes != NULL);
|
jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy);
|
||||||
jlong length = jni->GetDirectBufferCapacity(j_frame);
|
if (!is_copy) {
|
||||||
reinterpret_cast<AndroidVideoCapturerJni*>(
|
reinterpret_cast<AndroidVideoCapturerJni*>(
|
||||||
j_capturer)->OnIncomingFrame(bytes, length, rotation, ts);
|
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)
|
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeCapturerStarted)
|
||||||
|
@ -536,10 +536,11 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
rotation = 360 - rotation;
|
rotation = 360 - rotation;
|
||||||
}
|
}
|
||||||
rotation = (info.orientation + rotation) % 360;
|
rotation = (info.orientation + rotation) % 360;
|
||||||
|
// Mark the frame owning |data| as used.
|
||||||
frameObserver.OnFrameCaptured(
|
// Note that since data is directBuffer,
|
||||||
videoBuffers.reserveByteBuffer(data, captureTimeMs),
|
// data.length >= videoBuffers.frameSize.
|
||||||
rotation,
|
videoBuffers.reserveByteBuffer(data, captureTimeMs);
|
||||||
|
frameObserver.OnFrameCaptured(data, videoBuffers.frameSize, rotation,
|
||||||
captureTimeMs);
|
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).
|
// potentially stalling the capturer if it runs out of buffers to write to).
|
||||||
private static int numCaptureBuffers = 3;
|
private static int numCaptureBuffers = 3;
|
||||||
private final Frame cameraFrames[];
|
private final Frame cameraFrames[];
|
||||||
|
public final int frameSize;
|
||||||
|
|
||||||
private static class Frame {
|
private static class Frame {
|
||||||
public final ByteBuffer buffer;
|
private final ByteBuffer buffer;
|
||||||
public long timeStamp = -1;
|
public long timeStamp = -1;
|
||||||
|
|
||||||
Frame(int width, int height, int format) {
|
Frame(int frameSize) {
|
||||||
int bufSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
|
buffer = ByteBuffer.allocateDirect(frameSize);
|
||||||
buffer = ByteBuffer.allocateDirect(bufSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] data() {
|
byte[] data() {
|
||||||
@ -595,8 +596,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
|
|
||||||
FramePool(int width, int height, int format) {
|
FramePool(int width, int height, int format) {
|
||||||
cameraFrames = new Frame[numCaptureBuffers];
|
cameraFrames = new Frame[numCaptureBuffers];
|
||||||
|
frameSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
|
||||||
for (int i = 0; i < numCaptureBuffers; i++) {
|
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) {
|
for (Frame frame : cameraFrames) {
|
||||||
if (data == frame.data()) {
|
if (data == frame.data()) {
|
||||||
frame.timeStamp = timeStamp;
|
frame.timeStamp = timeStamp;
|
||||||
return frame.buffer;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new RuntimeException("unknown data buffer?!?");
|
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
|
// Delivers a captured frame. Called on a Java thread owned by
|
||||||
// VideoCapturerAndroid.
|
// 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
|
// An implementation of CapturerObserver that forwards all calls from
|
||||||
@ -657,14 +660,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnFrameCaptured(ByteBuffer byteBuffer, int rotation,
|
public void OnFrameCaptured(byte[] data, int length, int rotation,
|
||||||
long timeStamp) {
|
long timeStamp) {
|
||||||
nativeOnFrameCaptured(nativeCapturer, byteBuffer, rotation, timeStamp);
|
nativeOnFrameCaptured(nativeCapturer, data, length, rotation, timeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void nativeCapturerStarted(long nativeCapturer,
|
private native void nativeCapturerStarted(long nativeCapturer,
|
||||||
boolean success);
|
boolean success);
|
||||||
private native void nativeOnFrameCaptured(long nativeCapturer,
|
private native void nativeOnFrameCaptured(long nativeCapturer,
|
||||||
ByteBuffer byteBuffer, int rotation, long timeStamp);
|
byte[] data, int length, int rotation, long timeStamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user