Skip to content

Commit 8ea2450

Browse files
author
xianing
committed
Merge remote-tracking branch 'origin/4.0.0-preview' into 4.0.0-preview
2 parents beb61aa + 9cb74c5 commit 8ea2450

2 files changed

Lines changed: 115 additions & 16 deletions

File tree

Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ProcessRawData.java

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.agora.api.example.annotation.Example;
2828
import io.agora.api.example.common.BaseFragment;
2929
import io.agora.api.example.utils.CommonUtil;
30+
import io.agora.api.example.utils.YUVUtils;
3031
import io.agora.base.VideoFrame;
3132
import io.agora.rtc2.*;
3233
import io.agora.rtc2.video.*;
@@ -260,21 +261,47 @@ public boolean onCaptureVideoFrame(VideoFrame videoFrame) {
260261
isSnapshot = false;
261262

262263
// get image bitmap
263-
VideoFrame.I420Buffer buffer = videoFrame.getBuffer().toI420();
264-
ByteBuffer ib = ByteBuffer.allocate(videoFrame.getBuffer().getHeight() * videoFrame.getBuffer().getWidth() * 2);
265-
ib.put(buffer.getDataY());
266-
ib.put(buffer.getDataU());
267-
ib.put(buffer.getDataV());
268-
YuvImage yuvImage = new YuvImage(ib.array(),
269-
ImageFormat.NV21, videoFrame.getBuffer().getWidth(), videoFrame.getBuffer().getHeight(), null);
270-
ByteArrayOutputStream out = new ByteArrayOutputStream();
271-
yuvImage.compressToJpeg(new Rect(0, 0,
272-
videoFrame.getBuffer().getWidth(), videoFrame.getBuffer().getHeight()), 50, out);
273-
byte[] imageBytes = out.toByteArray();
274-
Bitmap bm = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
275-
264+
// VideoFrame.I420Buffer buffer = videoFrame.getBuffer().toI420();
265+
// ByteBuffer ib = ByteBuffer.allocate(videoFrame.getBuffer().getHeight() * videoFrame.getBuffer().getWidth() * 2);
266+
// ib.put(buffer.getDataY());
267+
// ib.put(buffer.getDataU());
268+
// ib.put(buffer.getDataV());
269+
// YuvImage yuvImage = new YuvImage(ib.array(),
270+
// ImageFormat.NV21, videoFrame.getBuffer().getWidth(), videoFrame.getBuffer().getHeight(), null);
271+
// ByteArrayOutputStream out = new ByteArrayOutputStream();
272+
// yuvImage.compressToJpeg(new Rect(0, 0,
273+
// videoFrame.getBuffer().getWidth(), videoFrame.getBuffer().getHeight()), 50, out);
274+
// byte[] imageBytes = out.toByteArray();
275+
// Bitmap bm = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
276+
277+
VideoFrame.Buffer buffer = videoFrame.getBuffer();
278+
279+
VideoFrame.I420Buffer i420Buffer = buffer.toI420();
280+
int width = i420Buffer.getWidth();
281+
int height = i420Buffer.getHeight();
282+
283+
ByteBuffer bufferY = i420Buffer.getDataY();
284+
ByteBuffer bufferU = i420Buffer.getDataU();
285+
ByteBuffer bufferV = i420Buffer.getDataV();
286+
287+
byte[] i420 = YUVUtils.toWrappedI420(bufferY, bufferU, bufferV, width, height);
288+
289+
Bitmap bitmap = YUVUtils.NV21ToBitmap(getContext(),
290+
YUVUtils.I420ToNV21(i420, width, height),
291+
width,
292+
height);
293+
294+
Matrix matrix = new Matrix();
295+
matrix.setRotate(270);
296+
// 围绕原地进行旋转
297+
Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
276298
// save to file
277-
saveBitmap2Gallery(bm);
299+
saveBitmap2Gallery(newBitmap);
300+
301+
bitmap.recycle();
302+
//别忘了释放
303+
i420Buffer.release();
304+
278305
}
279306
return false;
280307
}

Android/APIExample/app/src/main/java/io/agora/api/example/utils/YUVUtils.java

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package io.agora.api.example.utils;
22

3+
import static android.renderscript.Element.RGBA_8888;
4+
import static android.renderscript.Element.U8;
5+
import static android.renderscript.Element.U8_4;
6+
37
import android.content.Context;
48
import android.graphics.Bitmap;
59
import android.graphics.BitmapFactory;
@@ -8,12 +12,14 @@
812
import android.graphics.Rect;
913
import android.graphics.YuvImage;
1014
import android.renderscript.Allocation;
11-
import android.renderscript.Element;
15+
import android.renderscript.Type.Builder;
1216
import android.renderscript.RenderScript;
1317
import android.renderscript.ScriptIntrinsicBlur;
18+
import android.renderscript.ScriptIntrinsicYuvToRGB;
1419

1520
import java.io.ByteArrayOutputStream;
1621
import java.io.IOException;
22+
import java.nio.ByteBuffer;
1723

1824
public class YUVUtils {
1925

@@ -124,7 +130,7 @@ public static Bitmap blur(Context context, Bitmap image, float radius) {
124130
Bitmap outputBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
125131
Allocation in = Allocation.createFromBitmap(rs, image);
126132
Allocation out = Allocation.createFromBitmap(rs, outputBitmap);
127-
ScriptIntrinsicBlur intrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
133+
ScriptIntrinsicBlur intrinsicBlur = ScriptIntrinsicBlur.create(rs, U8_4(rs));
128134
intrinsicBlur.setRadius(radius);
129135
intrinsicBlur.setInput(in);
130136
intrinsicBlur.forEach(out);
@@ -145,4 +151,70 @@ public static byte[] bitmapToI420(int inputWidth, int inputHeight, Bitmap scaled
145151
return yuv;
146152
}
147153

154+
public static byte[] toWrappedI420(ByteBuffer bufferY,
155+
ByteBuffer bufferU,
156+
ByteBuffer bufferV,
157+
int width,
158+
int height) {
159+
int chromaWidth = (width + 1) / 2;
160+
int chromaHeight = (height + 1) / 2;
161+
int lengthY = width * height;
162+
int lengthU = chromaWidth * chromaHeight;
163+
int lengthV = lengthU;
164+
165+
166+
int size = lengthY + lengthU + lengthV;
167+
168+
byte[] out = new byte[size];
169+
for (int i = 0; i < size; i++) {
170+
if (i < lengthY) {
171+
out[i] = bufferY.get(i);
172+
} else if (i < lengthY + lengthU) {
173+
int j = (i - lengthY) / chromaWidth;
174+
int k = (i - lengthY) % chromaWidth;
175+
out[i] = bufferU.get(j * width + k);
176+
} else {
177+
int j = (i - lengthY - lengthU) / chromaWidth;
178+
int k = (i - lengthY - lengthU) % chromaWidth;
179+
out[i] = bufferV.get(j * width + k);
180+
}
181+
}
182+
183+
return out;
184+
}
185+
/**
186+
* I420转nv21
187+
*/
188+
public static byte[] I420ToNV21(byte[] data, int width, int height) {
189+
byte[] ret = new byte[data.length];
190+
int total = width * height;
191+
192+
ByteBuffer bufferY = ByteBuffer.wrap(ret, 0, total);
193+
ByteBuffer bufferVU = ByteBuffer.wrap(ret, total, total / 2);
194+
195+
bufferY.put(data, 0, total);
196+
for (int i = 0; i < total / 4; i += 1) {
197+
bufferVU.put(data[i + total + total / 4]);
198+
bufferVU.put(data[total + i]);
199+
}
200+
201+
return ret;
202+
}
203+
204+
public static Bitmap NV21ToBitmap(Context context, byte[] nv21, int width, int height) {
205+
RenderScript rs = RenderScript.create(context);
206+
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, U8_4(rs));
207+
Builder yuvType = null;
208+
yuvType = (new Builder(rs, U8(rs))).setX(nv21.length);
209+
Allocation in = Allocation.createTyped(rs, yuvType.create(), 1);
210+
Builder rgbaType = (new Builder(rs, RGBA_8888(rs))).setX(width).setY(height);
211+
Allocation out = Allocation.createTyped(rs, rgbaType.create(), 1);
212+
in.copyFrom(nv21);
213+
yuvToRgbIntrinsic.setInput(in);
214+
yuvToRgbIntrinsic.forEach(out);
215+
Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
216+
out.copyTo(bmpout);
217+
return bmpout;
218+
}
219+
148220
}

0 commit comments

Comments
 (0)