yasea icon indicating copy to clipboard operation
yasea copied to clipboard

How to add an overlay image to the Live Stream ??

Open Doss12 opened this issue 7 years ago • 18 comments

Doss12 avatar Mar 01 '17 14:03 Doss12

You can create a bitmap object using Bitmap class library. Search how can make watermark effect in Android.

begeekmyfriend avatar Mar 01 '17 15:03 begeekmyfriend

大神,我要加个时间水印的话怎么做,没思路啊,能写个例子吗?拜托了

xulingchung2016 avatar Mar 13 '17 01:03 xulingchung2016

Hello, do you have an example or instructions where you add a watermark to the stream? I can get it to display on top of the video by overriding the onDraw function and creating a thread that draws the canvas, but it shows a black screen and it doesn't show on the sent rtmp stream. Thank you!

javlae avatar Mar 21 '17 18:03 javlae

@javlae Finally, i found a solution to this issue, just add this code to SrcCameraView into onPreviewFrame method :D

Bitmap bitmap,b,ov;
Drawable myDrawable = getResources().getDrawable(R.drawable.logo);
   @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        if (mIsEncoding) {
           YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, mPreviewWidth, mPreviewHeight, null);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            yuvImage.compressToJpeg(new Rect(0,0,yuvImage.getWidth(),yuvImage.getHeight()), 100,os);
            byte[] jpegByteArray = os.toByteArray();
            bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
            b = drawableToBitmap(myDrawable);
            ov=overlay(bitmap,b);
            mYuvPreviewFrame=getNV21(mPreviewWidth,mPreviewHeight,ov);
            mPrevCb.onGetYuvFrame(mYuvPreviewFrame);
            camera.addCallbackBuffer(mYuvPreviewFrame);
        }
    }

//getNV21 from a bitmap

  byte [] getNV21(int inputWidth, int inputHeight, Bitmap scaled) {
        int [] argb = new int[inputWidth * inputHeight];

        scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);

        byte [] yuv = new byte[inputWidth*inputHeight*3/2];
        encodeYUV420SP(yuv, argb, inputWidth, inputHeight);

        scaled.recycle();

        return yuv;
    }

    void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
        final int frameSize = width * height;

        int yIndex = 0;
        int uvIndex = frameSize;

        int a, R, G, B, Y, U, V;
        int index = 0;
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {

                a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
                R = (argb[index] & 0xff0000) >> 16;
                G = (argb[index] & 0xff00) >> 8;
                B = (argb[index] & 0xff) >> 0;

                // well known RGB to YUV algorithm
                Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
                U = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
                V = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;

                // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
                //    meaning for every 4 Y pixels there are 1 V and 1 U.  Note the sampling is every other
                //    pixel AND every other scanline.
                yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
                if (j % 2 == 0 && index % 2 == 0) {
                    yuv420sp[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
                    yuv420sp[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
                }

                index ++;
            }
        }
    }


//convert drawable to Bitmap
    public static Bitmap drawableToBitmap (Drawable drawable) {
        Bitmap bitmap = null;
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            if(bitmapDrawable.getBitmap() != null) {
                return bitmapDrawable.getBitmap();
            }
        }
        if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444); // Single color bitmap will be created of 1x1 pixel
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        }
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }
//overlay two bitmap
    private Bitmap overlay(Bitmap bmp1, Bitmap bmp2) {
        Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
        Canvas canvas = new Canvas(bmOverlay);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
        canvas.drawBitmap(bmp1, new Matrix(), paint);
        canvas.drawBitmap(bmp2, new Matrix(), paint);
        return bmOverlay;
    }

Doss12 avatar Mar 24 '17 10:03 Doss12

@Doss12 ONE THOUSAND COOKIES TO YOU MY FRIEND!! The only issue I have is that the image is rotated and flipped, but that should be an easy fix :)

Thank you!

javlae avatar Mar 24 '17 15:03 javlae

@javlae Let me know when you fix that ;)

Doss12 avatar Mar 24 '17 16:03 Doss12

@Doss12 I have fixed it by playing with the image dimensions and the rotation. Now it is perfectly positioned on the video stream, but the problem now is that the stream got really bad FPS due to all the processing (event down to 2 frames per second). I am trying to work on optimization, but so far no luck :(

javlae avatar Mar 27 '17 21:03 javlae

yess i agree with you on the fact that the processing is too long but temporaly it's the only solution that i have found :3

Doss12 avatar Mar 28 '17 10:03 Doss12

Yeah, me too. I wonder how these guys did it: https://play.google.com/store/apps/details?id=com.vaultmicro.camerafi.live&hl=en

javlae avatar Mar 28 '17 11:03 javlae

@Doss12 I think the code is changed. how should the new code be approached. Requirements are the same, I need a logo like say 'hbo' at the top left corner of the preview as well as the live video. I am not at all experienced in dealing with this. please help asap

ninadthakare avatar Jul 12 '17 14:07 ninadthakare

Doss12 : please could you tell me more how did you get the view into the stream? i tried your code but i didn't figure out how to use it? could you give me a sample or a demo? thx

Zouzoufa avatar Sep 06 '17 00:09 Zouzoufa

@Doss12 Hey I can not find onPreviewFrame method in SrcCameraView class. Can you help me here?

chiragdigi avatar Feb 06 '19 05:02 chiragdigi

can you please share SrcCameraView class for same?

truptigoqii avatar Oct 03 '19 11:10 truptigoqii

libpng is all you need.

begeekmyfriend avatar Oct 03 '19 13:10 begeekmyfriend

hi,why I can't find SrcCameraView calss,only find SrsCameraView class,and I can't find mPrevCb.onGetYuvFrame,have the code changed?

RookieTao-Lee avatar Nov 19 '20 07:11 RookieTao-Lee

Why not try libpng

begeekmyfriend avatar Nov 19 '20 11:11 begeekmyfriend

sorry,Could you please tell me more about it? I don't know what is the relationship between srcCameraView and libpng。thank 'you

RookieTao-Lee avatar Nov 23 '20 01:11 RookieTao-Lee

You might use libpng in libenc.cc for image preprocessing.

begeekmyfriend avatar Nov 23 '20 07:11 begeekmyfriend