package org.deviceconnect.android.deviceplugin.webrtc.core; import android.content.Context; import android.graphics.Bitmap; import android.util.AttributeSet; import org.deviceconnect.android.deviceplugin.webrtc.BuildConfig; import org.deviceconnect.android.deviceplugin.webrtc.util.ImageUtils; import org.deviceconnect.android.deviceplugin.webrtc.util.MixedReplaceMediaServer; import org.deviceconnect.android.deviceplugin.webrtc.util.YuvConverter; import org.webrtc.EglBase; import org.webrtc.SurfaceViewRenderer; import org.webrtc.VideoRenderer; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; public class MySurfaceViewRenderer extends SurfaceViewRenderer { private static final boolean DEBUG = BuildConfig.DEBUG; private static final String TAG = "WebRTC"; public static final String TYPE_LOCAL = "local"; public static final String TYPE_REMOTE = "remote"; private String mType = null; private YuvConverter mYuvConverter; private ByteBuffer mByteBuffer; private MixedReplaceMediaServer mServer = null; private int mFrameHeight = 0; private int mFrameWidth = 0; private boolean mReleased; private Bitmap mBitmap; private ByteArrayOutputStream mOutputStream = new ByteArrayOutputStream(); public MySurfaceViewRenderer(Context context) { super(context); } public MySurfaceViewRenderer(Context context, AttributeSet attrs) { super(context, attrs); } public void release() { if (mReleased) { return; } mReleased = true; mByteBuffer = null; if (mBitmap != null) { mBitmap.recycle(); mBitmap = null; } if (mYuvConverter != null) { mYuvConverter.release(); mYuvConverter = null; } } public void createYuvConverter(EglBase.Context context) { mYuvConverter = new YuvConverter(context); } public String getUrl() { if (mServer == null) { return null; } return mServer.getUrl(mType); } public int getFrameHeight() { return mFrameHeight; } public int getFrameWidth() { return mFrameWidth; } public String getMimeType() { if (mServer == null) { return null; } return mServer.getMimeType(); } public void setType(final String type) { mType = type; } public void setWebServer(final MixedReplaceMediaServer server) { mServer = server; } @Override public void renderFrame(VideoRenderer.I420Frame frame) { if (mReleased) { return; } if (mServer != null && mYuvConverter != null) { if (!frame.yuvFrame) { convertTextureToYUV(frame); } else { convertYuvToRGB(frame); } } super.renderFrame(frame); } private void convertYuvToRGB(VideoRenderer.I420Frame frame) { if (frame.yuvPlanes == null || frame.yuvPlanes[0] == null) { return; } if (mBitmap == null || mBitmap.getWidth() != frame.width || mBitmap.getHeight() != frame.height) { mBitmap = Bitmap.createBitmap(frame.width, frame.height, Bitmap.Config.ARGB_8888); } ImageUtils.decodeYUV420SP3(mBitmap, frame.yuvPlanes, frame.width, frame.height, frame.yuvStrides); mOutputStream.reset(); mBitmap.compress(Bitmap.CompressFormat.JPEG, 20, mOutputStream); mFrameHeight = frame.height; mFrameWidth = frame.width; mServer.offerMedia(mType, mOutputStream.toByteArray()); } private void convertTextureToYUV(VideoRenderer.I420Frame frame) { if (mByteBuffer == null) { int uv_height = (frame.height + 1) / 2; int total_height = frame.height + uv_height; int size = frame.width * total_height; mByteBuffer = ByteBuffer.allocateDirect(size); mByteBuffer.order(ByteOrder.nativeOrder()); } if (mBitmap == null || mBitmap.getWidth() != frame.width || mBitmap.getHeight() != frame.height) { mBitmap = Bitmap.createBitmap(frame.width, frame.height, Bitmap.Config.ARGB_8888); } mYuvConverter.convert(mByteBuffer, frame.width, frame.height, frame.width, frame.textureId, frame.samplingMatrix); ImageUtils.decodeYUV420SP2(mBitmap, mByteBuffer, frame.width, frame.height); mOutputStream.reset(); mBitmap.compress(Bitmap.CompressFormat.JPEG, 20, mOutputStream); mFrameHeight = frame.height; mFrameWidth = frame.width; mServer.offerMedia(mType, mOutputStream.toByteArray()); } }