Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating stream from canvas using custom capturer(webrtc)

Tags:

android

webrtc

I wrote below code to obtain stream from canvas. But after every 5 minutes. I am getting (out of memory). I looked "Profiler" in android studio to check memory consumption and it got increased rapidly while app was running. I am not sure, its because of costly bitmaps or any other costly affair. Any help or suggestion would be helpful.

@Override
   public void startCapture(int width, int height, int fps) {

    if (captureThread == null || !captureThread.isInterrupted()) {
        captureThread = new Thread(() -> {
            try {
                newCameraHeight = 480;
                newCameraWidth = 640;

                long start = System.nanoTime();
                capturerObs.onCapturerStarted(true);
                int[] textures = new int[1];
                GLES20.glGenTextures(1, textures, 0);

                String name = getInitialWord(userName).toUpperCase();

                YuvConverter yuvConverter = new YuvConverter();

                releaseBitmap(bitmap);
                bitmap = Bitmap.createBitmap(newCameraWidth, newCameraHeight, Bitmap.Config.ARGB_8888);
                Bitmap newBitmap = bitmap.copy(bitmap.getConfig(), true);
                releaseBitmap(bitmap);

                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
                Log.d("InitialsClass", "start capturer width- " + newCameraWidth + " height- " + newCameraHeight);


                while (!Thread.currentThread().isInterrupted()) {
                    Resources resources = appContext.getResources();
                    float scale = resources.getDisplayMetrics().density;

                    Canvas canvas = new Canvas(newBitmap);
                    canvas.drawRGB(0, 0, 0);

                    Paint circlePaint = new Paint();
                    circlePaint.setColor(Color.parseColor("#FAD7A0"));
                    circlePaint.setStyle(Paint.Style.FILL);
                    circlePaint.setAntiAlias(true);
                    circlePaint.setAlpha(128);
                    canvas.drawCircle(newCameraWidth / 2, newCameraHeight / 2, 150, circlePaint);
                    TextPaint textPaint = new TextPaint();
                    textPaint.setColor(Color.WHITE);
                    textPaint.setTextSize((int) (18 * scale));
                    textPaint.setTypeface(Typeface.create(typeFace, Typeface.NORMAL));
                    textPaint.setTextAlign(Paint.Align.CENTER);
                    textPaint.setAntiAlias(true);

                    Rect textBounds = new Rect();
                    textPaint.getTextBounds(name, 0, name.length(), textBounds);
                    textBounds.set(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2 + (textBounds.height() / 2 - 4));

                    canvas.save();
                    canvas.scale(1f, -1f, textBounds.centerX(), textBounds.centerY());
                    canvas.drawText(name, textBounds.centerX(), textBounds.centerY() + textBounds.height() + 3, textPaint);
                    canvas.restore();

                    Matrix matrix = new Matrix();

                    matrix.setScale(1, -1);
                    matrix.postTranslate(0, canvas.getHeight());
                    canvas.setMatrix(matrix);

                    TextPaint userNameTextPaint = new TextPaint();
                    userNameTextPaint.setColor(Color.WHITE);
                    userNameTextPaint.setTypeface(Typeface.create(typeFace, Typeface.BOLD));
                    textPaint.setTextSize((int) (10 * scale));
                    textPaint.setAntiAlias(true);
                    Rect textBound = new Rect();
                    userNameTextPaint.getTextBounds(userName, 0, userName.length(), textBound);
                    int horizontalSpacing = 16;
                    int verticalSpacing = 24;
                    int x = horizontalSpacing;
                    int y = newCameraHeight - verticalSpacing;

                    textPaint.setTextAlign(Paint.Align.LEFT);
                    canvas.drawText(userName, x, y, textPaint);

                    Paint paint = new Paint();
                    if (isLocalCandidate) {
                        paint.setColor(Color.GREEN);
                    } else {
                        paint.setColor(Color.TRANSPARENT);
                    }
                    paint.setStrokeWidth(8);
                    paint.setStyle(Paint.Style.STROKE);
                    canvas.drawRect(0, 8, canvas.getWidth() - 8, canvas.getHeight() - 8, paint);

                    if (surTexture != null && surTexture.getHandler() != null && surTexture.getHandler().getLooper().getThread().isAlive()) {
                        surTexture.getHandler().post(() -> {
                            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
                            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
                            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, newBitmap, 0);
                            TextureBufferImpl buffer = new TextureBufferImpl(newCameraWidth, newCameraHeight, VideoFrame.TextureBuffer.Type.RGB, textures[0], new Matrix(), surTexture.getHandler(), yuvConverter, null);

                            VideoFrame.I420Buffer i420Buf = yuvConverter.convert(buffer);

                            long frameTime = System.nanoTime() - start;
                            VideoFrame videoFrame = new VideoFrame(i420Buf, 0, frameTime);
                            capturerObs.onFrameCaptured(videoFrame);
                        });
                    }
                    Thread.sleep(100);
                }
            } catch (InterruptedException ex) {
                Log.d("InitialsClass file", ex.toString());
                Thread.currentThread().interrupt();
                return;
            }
        });
    }
    captureThread.start();
}
like image 343
cyrus000 Avatar asked Feb 20 '21 03:02

cyrus000


1 Answers

I increased the frame captured time and now creating canvas only once.

  this.executor_.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                Log.d("InitialsClass", "camera start file capturer inside while");
                if(isFirstTime) {
                    isFirstTime = false;
                    if(canvas == null) {
                        canvas = new Canvas(bitmap);
                    }
                    canvas.drawRGB(0, 0, 0);

                    if (circlePaint == null) {
                        circlePaint = new Paint();
                    }
                    circlePaint.setColor(Color.parseColor("#FAD7A0"));
                    circlePaint.setStyle(Paint.Style.FILL);
                    circlePaint.setAntiAlias(true);
                    circlePaint.setAlpha(128);
                    canvas.drawCircle(newCameraWidth / 2, newCameraHeight / 2, 155, circlePaint);

                    if (textPaint == null) {
                        textPaint = new TextPaint();
                    }
                    textPaint.setColor(Color.WHITE);
                    textPaint.setTextSize((int) (18 * scale));
                    textPaint.setTypeface(Typeface.create(textFace, Typeface.NORMAL));
                    textPaint.setTextAlign(Paint.Align.CENTER);
                    textPaint.setAntiAlias(true);

                    if(textBound == null) {
                        textBounds = new Rect();
                    }
                    textPaint.getTextBounds(name, 0, name.length(), textBounds);
                    textBounds.set(0, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight() / 2 + (textBounds.height() / 2 - 4));

                    canvas.save();
                    canvas.scale(1f, -1f, textBounds.centerX(), textBounds.centerY());
                    canvas.drawText(name, textBounds.centerX(), textBounds.centerY() + textBounds.height() + 3, textPaint);
                    canvas.restore();

                    if (matrix == null) {
                        matrix = new Matrix();
                    }
                    matrix.setScale(1, -1);
                    matrix.postTranslate(0, canvas.getHeight());
                    canvas.setMatrix(matrix);

                    if (userNameTextPaint == null) {
                        userNameTextPaint = new TextPaint();
                    }
                    userNameTextPaint.setColor(Color.WHITE);
                    userNameTextPaint.setTypeface(Typeface.create(textFace, Typeface.BOLD));
                    textPaint.setTextSize((int) (11 * scale));
                    textPaint.setAntiAlias(true);

                    if (textBound == null) {
                        textBound = new Rect();
                    }
                    userNameTextPaint.getTextBounds(userName, 0, userName.length(), textBound);
                    int horizontalSpacing = 16;
                    int verticalSpacing = 20;
                    int x = horizontalSpacing;
                    int y = bitmap.getHeight() - verticalSpacing;

                    textPaint.setTextAlign(Paint.Align.LEFT);
                    canvas.drawText(userName, x, y, textPaint);

                    if (paint == null) {
                        paint = new Paint();
                    }
                    if (isLocalCandidate) {
                        paint.setColor(Color.GREEN);
                        paint.setStrokeWidth(8);
                        paint.setStyle(Paint.Style.STROKE);
                        canvas.drawRect(0, 8, canvas.getWidth() - 8, canvas.getHeight() - 8, paint);
                    } else {
                        paint.setColor(Color.DKGRAY);
                        paint.setStrokeWidth(4);
                        paint.setStyle(Paint.Style.STROKE);
                        canvas.drawRect(0, 4, canvas.getWidth() - 4, canvas.getHeight() - 4, paint);
                    }
                }
                if (surTexture != null && surTexture.getHandler() != null && surTexture.getHandler().getLooper().getThread().isAlive()) {
                    surTexture.getHandler().post(() -> {
                        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
                        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
                        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
                        VideoFrame.I420Buffer i420Buf = yuvConverter.convert(buffer);

                        long frameTime = System.nanoTime() - start;
                        VideoFrame videoFrame = new VideoFrame(i420Buf, 0, frameTime);
                        capturerObs.onFrameCaptured(videoFrame);
                    });
                }
            }
        }, 0L, 1, TimeUnit.SECONDS);
}
like image 71
cyrus000 Avatar answered Oct 19 '22 02:10

cyrus000