package com.carusto.ReactNativePjSip; import android.content.Context; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup; import org.pjsip.pjsua2.MediaSize; import org.pjsip.pjsua2.VideoWindow; public abstract class PjSipVideo extends ViewGroup implements SurfaceHolder.Callback { private static String TAG = "PjSipVideo"; private String objectFit = "cover"; private SurfaceHolder surfaceHolder; private SurfaceView surfaceView; private PjSipVideoWindowHandler videoWindowHandler; private VideoWindow videoWindow; private int layoutLeft = 0; private int layoutTop = 0; private int layoutRight = 0; private int layoutBottom = 0; public PjSipVideo(Context context) { super(context); surfaceView = new SurfaceView(context); surfaceView.getHolder().addCallback(this); surfaceView.setZOrderOnTop(false); addView(surfaceView); } protected void setCallback(PjSipVideoWindowHandler callback) { videoWindowHandler = callback; if (surfaceHolder != null) { try { videoWindow = this.videoWindowHandler.start(surfaceHolder); doLayout(); } catch (Exception e) { Log.e(TAG, "An error occurs during getting video window by surface", e); } } } public void setObjectFit(String type) { if (objectFit.equals(type.toLowerCase())) { return; } objectFit = type.toLowerCase(); try { doLayout(); } catch (Exception e) { Log.e(TAG, "An error occurs during setting object fit with active video window.", e); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { layoutTop = t; layoutLeft = l; layoutBottom = b; layoutRight = r; if (surfaceHolder == null) { surfaceView.layout(0, 0, r - l, b - t); } else { try { doLayout(); } catch (Exception e) { Log.e(TAG, "An error occurs during layout", e); } } } protected void doLayout() throws Exception { int layoutWidth = layoutRight - layoutLeft; int layoutHeight = layoutBottom - layoutTop; if (surfaceView == null || videoWindow == null) { return; } MediaSize size = videoWindow.getInfo().getSize(); int height; int width; switch (objectFit) { case "cover": { if (size.getH() == size.getW()) { int max = Math.max(layoutWidth, layoutHeight); width = max; height = max; } else if (size.getW() / layoutWidth > size.getH() / layoutHeight) { height = layoutHeight; width = Math.round(((float) layoutHeight / size.getH()) * size.getW()); } else { width = layoutWidth; height = Math.round(((float) layoutWidth / size.getW()) * size.getH()); } break; } case "contain": default: { if (size.getH() == size.getW()) { int min = Math.min(layoutWidth, layoutHeight); width = min; height = min; } else if (size.getW() > size.getH()) { width = layoutWidth; height = Math.round(((float) layoutWidth / size.getW()) * size.getH()); } else { height = layoutHeight; width = Math.round(((float) layoutHeight / size.getH()) * size.getW()); } } } int offsetLeft = (layoutWidth - width) / 2; int offsetTop = (layoutHeight - height) / 2; Log.d(TAG, "resize to video width-" + size.getW()); Log.d(TAG, "resize to video height-" + size.getH()); Log.d(TAG, "resize to width-" + width); Log.d(TAG, "resize to height-" + height); Log.d(TAG, "resize to layoutWidth-" + layoutWidth); Log.d(TAG, "resize to layoutHeight-" + layoutHeight); Log.d(TAG, "resize to offsetLeft-" + offsetLeft); Log.d(TAG, "resize to offsetTop-" + offsetTop); surfaceView.layout( offsetLeft, offsetTop, offsetLeft + width, offsetTop + height ); } @Override public void surfaceCreated(final SurfaceHolder holder) { this.surfaceHolder = holder; if (this.videoWindowHandler != null) { try { videoWindow = this.videoWindowHandler.start(holder); doLayout(); } catch (Exception e) { Log.e(TAG, "An error occurs during getting video window by surface", e); } } } @Override public void surfaceChanged(final SurfaceHolder surfaceHolder, int i, int i1, int i2) { // Nothing } @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { // Nothing } }