Revert of Android VideoCapturer: Send ByteBuffer instead of byte[] (patchset #1 id:1 of https://codereview.webrtc.org/1372813002/ )
Reason for revert: The top row in the video stream from the camera is messed up. The byte[] pointer is not the same as GetDirectBufferAddress() apparently. Original issue's description: > Android VideoCapturer: Send ByteBuffer instead of byte[] > > The purpose with this CL is to replace GetByteArrayElements() and ReleaseByteArrayElements() with GetDirectBufferAddress(). > > R=hbos@webrtc.org > > Committed: https://crrev.com/cb3649b40b3fd6d5bbb0a92003b717e46ce90924 > Cr-Commit-Position: refs/heads/master@{#10091} TBR=hbos@webrtc.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review URL: https://codereview.webrtc.org/1377783002 Cr-Commit-Position: refs/heads/master@{#10103}
This commit is contained in:
@ -35,7 +35,6 @@ import android.util.Size;
|
|||||||
import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
|
import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
|
||||||
import org.webrtc.VideoRenderer.I420Frame;
|
import org.webrtc.VideoRenderer.I420Frame;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -105,11 +104,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnFrameCaptured(ByteBuffer frame, int width, int height,
|
public void OnFrameCaptured(byte[] frame, int length, int width, int height,
|
||||||
int rotation, long timeStamp) {
|
int rotation, long timeStamp) {
|
||||||
synchronized (frameLock) {
|
synchronized (frameLock) {
|
||||||
++framesCaptured;
|
++framesCaptured;
|
||||||
frameSize = frame.capacity();
|
frameSize = length;
|
||||||
timestamps.add(timeStamp);
|
timestamps.add(timeStamp);
|
||||||
frameLock.notify();
|
frameLock.notify();
|
||||||
}
|
}
|
||||||
|
@ -569,11 +569,12 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
}
|
}
|
||||||
rotation = (info.orientation + rotation) % 360;
|
rotation = (info.orientation + rotation) % 360;
|
||||||
// Mark the frame owning |data| as used.
|
// Mark the frame owning |data| as used.
|
||||||
final ByteBuffer buffer = videoBuffers.reserveByteBuffer(data, captureTimeNs);
|
// Note that since data is directBuffer,
|
||||||
if (buffer != null) {
|
// data.length >= videoBuffers.frameSize.
|
||||||
|
if (videoBuffers.reserveByteBuffer(data, captureTimeNs)) {
|
||||||
cameraFramesCount++;
|
cameraFramesCount++;
|
||||||
frameObserver.OnFrameCaptured(buffer, captureFormat.width, captureFormat.height,
|
frameObserver.OnFrameCaptured(data, videoBuffers.frameSize, captureFormat.width,
|
||||||
rotation, captureTimeNs);
|
captureFormat.height, rotation, captureTimeNs);
|
||||||
} else {
|
} else {
|
||||||
Logging.w(TAG, "reserveByteBuffer failed - dropping frame.");
|
Logging.w(TAG, "reserveByteBuffer failed - dropping frame.");
|
||||||
}
|
}
|
||||||
@ -655,8 +656,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
: " Pending buffers: " + pendingFramesTimeStamps() + "."));
|
: " Pending buffers: " + pendingFramesTimeStamps() + "."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the reserved byte buffer, or null on failure.
|
public boolean reserveByteBuffer(byte[] data, long timeStamp) {
|
||||||
public ByteBuffer reserveByteBuffer(byte[] data, long timeStamp) {
|
|
||||||
checkIsOnValidThread();
|
checkIsOnValidThread();
|
||||||
final ByteBuffer buffer = queuedBuffers.remove(data);
|
final ByteBuffer buffer = queuedBuffers.remove(data);
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
@ -664,21 +664,21 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
// capture format in |startPreviewOnCameraThread|. Drop these old frames.
|
// capture format in |startPreviewOnCameraThread|. Drop these old frames.
|
||||||
Logging.w(TAG, "Received callback buffer from previous configuration with length: "
|
Logging.w(TAG, "Received callback buffer from previous configuration with length: "
|
||||||
+ (data == null ? "null" : data.length));
|
+ (data == null ? "null" : data.length));
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
if (buffer.capacity() != frameSize) {
|
if (buffer.capacity() != frameSize) {
|
||||||
throw new IllegalStateException("Callback buffer has unexpected frame size");
|
throw new IllegalStateException("Callback buffer has unexpected frame size");
|
||||||
}
|
}
|
||||||
if (pendingBuffers.containsKey(timeStamp)) {
|
if (pendingBuffers.containsKey(timeStamp)) {
|
||||||
Logging.e(TAG, "Timestamp already present in pending buffers - they need to be unique");
|
Logging.e(TAG, "Timestamp already present in pending buffers - they need to be unique");
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
pendingBuffers.put(timeStamp, buffer);
|
pendingBuffers.put(timeStamp, buffer);
|
||||||
if (queuedBuffers.isEmpty()) {
|
if (queuedBuffers.isEmpty()) {
|
||||||
Logging.v(TAG, "Camera is running out of capture buffers."
|
Logging.v(TAG, "Camera is running out of capture buffers."
|
||||||
+ " Pending buffers: " + pendingFramesTimeStamps());
|
+ " Pending buffers: " + pendingFramesTimeStamps());
|
||||||
}
|
}
|
||||||
return buffer;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void returnBuffer(long timeStamp) {
|
public void returnBuffer(long timeStamp) {
|
||||||
@ -722,8 +722,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 width, int height, int rotation,
|
abstract void OnFrameCaptured(byte[] data, int length, int width, int height,
|
||||||
long timeStamp);
|
int rotation, long timeStamp);
|
||||||
|
|
||||||
// Requests an output format from the video capturer. Captured frames
|
// Requests an output format from the video capturer. Captured frames
|
||||||
// by the camera will be scaled/or dropped by the video capturer.
|
// by the camera will be scaled/or dropped by the video capturer.
|
||||||
@ -746,9 +746,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void OnFrameCaptured(ByteBuffer buffer, int width, int height, int rotation,
|
public void OnFrameCaptured(byte[] data, int length, int width, int height,
|
||||||
long timeStamp) {
|
int rotation, long timeStamp) {
|
||||||
nativeOnFrameCaptured(nativeCapturer, buffer, width, height, rotation, timeStamp);
|
nativeOnFrameCaptured(nativeCapturer, data, length, width, height, rotation, timeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -759,7 +759,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
|
|||||||
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 buffer, int width, int height, int rotation, long timeStamp);
|
byte[] data, int length, int width, int height, int rotation, long timeStamp);
|
||||||
private native void nativeOnOutputFormatRequest(long nativeCapturer,
|
private native void nativeOnOutputFormatRequest(long nativeCapturer,
|
||||||
int width, int height, int fps);
|
int width, int height, int fps);
|
||||||
}
|
}
|
||||||
|
@ -176,13 +176,13 @@ void AndroidVideoCapturerJni::OnCapturerStarted(bool success) {
|
|||||||
success);
|
success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidVideoCapturerJni::OnIncomingFrame(const uint8_t* video_frame,
|
void AndroidVideoCapturerJni::OnIncomingFrame(void* video_frame,
|
||||||
int length,
|
int length,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int rotation,
|
int rotation,
|
||||||
int64 time_stamp) {
|
int64 time_stamp) {
|
||||||
const uint8_t* y_plane = video_frame;
|
const uint8_t* y_plane = static_cast<uint8_t*>(video_frame);
|
||||||
// Android guarantees that the stride is a multiple of 16.
|
// Android guarantees that the stride is a multiple of 16.
|
||||||
// http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29
|
// http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29
|
||||||
int y_stride;
|
int y_stride;
|
||||||
@ -215,14 +215,20 @@ void AndroidVideoCapturerJni::OnOutputFormatRequest(int width,
|
|||||||
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_byte_buffer,
|
(JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame, jint length,
|
||||||
jint width, jint height, jint rotation, jlong ts) {
|
jint width, jint height, jint rotation, jlong ts) {
|
||||||
const uint8_t* bytes =
|
jboolean is_copy = true;
|
||||||
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_byte_buffer));
|
jbyte* bytes = jni->GetByteArrayElements(j_frame, &is_copy);
|
||||||
const int length = jni->GetDirectBufferCapacity(j_byte_buffer);
|
// If this is a copy of the original frame, it means that the memory
|
||||||
RTC_CHECK(bytes != nullptr && length != -1) << "ByteBuffer is not direct";
|
// is not direct memory and thus VideoCapturerAndroid does not guarantee
|
||||||
|
// that the memory is valid when we have released |j_frame|.
|
||||||
|
// TODO(magjed): Move ReleaseByteArrayElements() into ReturnBuffer() and
|
||||||
|
// remove this check.
|
||||||
|
RTC_CHECK(!is_copy)
|
||||||
|
<< "NativeObserver_nativeOnFrameCaptured: frame is a copy";
|
||||||
reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer)
|
reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer)
|
||||||
->OnIncomingFrame(bytes, length, width, height, rotation, ts);
|
->OnIncomingFrame(bytes, length, width, height, rotation, ts);
|
||||||
|
jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeCapturerStarted)
|
JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeCapturerStarted)
|
||||||
|
@ -61,7 +61,7 @@ class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate {
|
|||||||
|
|
||||||
// Called from VideoCapturerAndroid::NativeObserver on a Java thread.
|
// Called from VideoCapturerAndroid::NativeObserver on a Java thread.
|
||||||
void OnCapturerStarted(bool success);
|
void OnCapturerStarted(bool success);
|
||||||
void OnIncomingFrame(const uint8_t* video_frame,
|
void OnIncomingFrame(void* video_frame,
|
||||||
int length,
|
int length,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
Reference in New Issue
Block a user