Index: webrtc/sdk/android/src/java/org/webrtc/I420BufferImpl.java |
diff --git a/webrtc/sdk/android/src/java/org/webrtc/I420BufferImpl.java b/webrtc/sdk/android/src/java/org/webrtc/I420BufferImpl.java |
index 87fc202ecea6e88d34a5e31aac3230e5c6113bd0..09c07822714a1d4a98b986c67b78819d5f33ea68 100644 |
--- a/webrtc/sdk/android/src/java/org/webrtc/I420BufferImpl.java |
+++ b/webrtc/sdk/android/src/java/org/webrtc/I420BufferImpl.java |
@@ -15,21 +15,48 @@ import org.webrtc.VideoFrame.I420Buffer; |
/** Implementation of an I420 VideoFrame buffer. */ |
class I420BufferImpl implements VideoFrame.I420Buffer { |
+ private final ByteBuffer buffer; |
private final int width; |
private final int height; |
- private final int strideUV; |
- private final ByteBuffer y; |
- private final ByteBuffer u; |
- private final ByteBuffer v; |
+ private final int chromaHeight; |
+ private final int yPos; |
+ private final int strideY; |
+ private final int uPos; |
+ private final int strideU; |
+ private final int vPos; |
+ private final int strideV; |
+ private final ReleaseCallback releaseCallback; |
- I420BufferImpl(int width, int height) { |
+ private int refCount; |
+ |
+ /** Allocates an I420Buffer backed by existing data. */ |
+ I420BufferImpl(ByteBuffer buffer, int width, int height, int yPos, int strideY, int uPos, |
+ int strideU, int vPos, int strideV, ReleaseCallback releaseCallback) { |
+ this.buffer = buffer; |
this.width = width; |
this.height = height; |
- this.strideUV = (width + 1) / 2; |
- int halfHeight = (height + 1) / 2; |
- this.y = ByteBuffer.allocateDirect(width * height); |
- this.u = ByteBuffer.allocateDirect(strideUV * halfHeight); |
- this.v = ByteBuffer.allocateDirect(strideUV * halfHeight); |
+ this.chromaHeight = (height + 1) / 2; |
+ this.yPos = yPos; |
+ this.strideY = strideY; |
+ this.uPos = uPos; |
+ this.strideU = strideU; |
+ this.vPos = vPos; |
+ this.strideV = strideV; |
+ this.releaseCallback = releaseCallback; |
+ |
+ this.refCount = 1; |
+ } |
+ |
+ /** Allocates an empty I420Buffer suitable for an image of the given dimensions. */ |
+ static I420BufferImpl allocate(int width, int height) { |
+ int chromaHeight = (height + 1) / 2; |
+ int strideUV = (width + 1) / 2; |
+ int yPos = 0; |
+ int uPos = yPos + width * height; |
+ int vPos = uPos + strideUV * chromaHeight; |
+ ByteBuffer buffer = ByteBuffer.allocateDirect(width * height + 2 * strideUV * chromaHeight); |
+ return new I420BufferImpl( |
+ buffer, width, height, yPos, width, uPos, strideUV, vPos, strideUV, null); |
} |
@Override |
@@ -44,32 +71,41 @@ class I420BufferImpl implements VideoFrame.I420Buffer { |
@Override |
public ByteBuffer getDataY() { |
- return y; |
+ ByteBuffer data = buffer.slice(); |
+ data.position(yPos); |
+ data.limit(yPos + getStrideY() * height); |
+ return data; |
} |
@Override |
public ByteBuffer getDataU() { |
- return u; |
+ ByteBuffer data = buffer.slice(); |
+ data.position(uPos); |
+ data.limit(uPos + strideU * chromaHeight); |
+ return data; |
} |
@Override |
public ByteBuffer getDataV() { |
- return v; |
+ ByteBuffer data = buffer.slice(); |
+ data.position(vPos); |
+ data.limit(vPos + strideV * chromaHeight); |
+ return data; |
} |
@Override |
public int getStrideY() { |
- return width; |
+ return strideY; |
} |
@Override |
public int getStrideU() { |
- return strideUV; |
+ return strideU; |
} |
@Override |
public int getStrideV() { |
- return strideUV; |
+ return strideV; |
} |
@Override |
@@ -78,8 +114,20 @@ class I420BufferImpl implements VideoFrame.I420Buffer { |
} |
@Override |
- public void retain() {} |
+ public void retain() { |
+ ++refCount; |
+ } |
@Override |
- public void release() {} |
+ public void release() { |
+ if (--refCount == 0 && releaseCallback != null) { |
+ releaseCallback.onRelease(); |
+ } |
+ } |
+ |
+ // Callback called when the frame is no longer referenced. |
+ interface ReleaseCallback { |
+ // Called when the frame is no longer referenced. |
+ void onRelease(); |
+ } |
} |