How to generate a black frame at the access terminal of the GB28181 device on the Andorid platform and push it to the national standard platform

When we were working on the Android platform GB28181 device access module, we encountered such a demand. When doing mobile intercom, video data is not needed, but on the national standard platform side, if there is no video, most platforms cannot broadcast pure audio packages. data (most of the web pages are implemented based on http-flv or webrtc), based on this, we did a simple process to generate a 32*32 black frame through Bitmap, and then ensured that the upstream audio and video data are available, but due to Video is black frame data, which hardly takes up bandwidth.

Without further ado, let's go to the code:

    class LayerPostThread extends Thread
    {
        private volatile boolean is_exit_ = false;
        private long handle_ = 0;
        ByteBuffer image_buffer_ = null;
        private int width_ = 32;
        private int height_ = 32;

        @Override
        public void run() {
            image_buffer_ = null;

            if (0 == handle_)
                return;

            generateImageBuffer(width_, height_);

            while(!is_exit_) {
                postImageLayer(0, 0, 0, width_, height_);
                waitSleep(40);
            }

            image_buffer_ = null;
        }

        private void generateImageBuffer(int width, int height)
        {
            Bitmap bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888);
            bitmap.eraseColor(android.graphics.Color.argb(255, 0, 0, 0));

            if (null == bitmap)
                return;

            if ( image_buffer_ != null) {
                image_buffer_.rewind();

                if ( image_buffer_.remaining() < bitmap.getByteCount())
                    image_buffer_ = null;
            }

            if (null == image_buffer_)
                image_buffer_ = ByteBuffer.allocateDirect(bitmap.getByteCount());

            bitmap.copyPixelsToBuffer(image_buffer_);
        }

        private int postImageLayer(int index, int left, int top, int video_w, int video_h) {
            if (video_w < 1 || video_h < 1)
                return  0;

            int scale_w = 0, scale_h = 0, scale_filter_mode = 0;

            libPublisher.PostLayerImageRGBA8888ByteBuffer(handle_, index, left, top, image_buffer_, 0,
                    4*video_w, video_w, video_h,
                    0, 0, scale_w, scale_h, scale_filter_mode,0);

            return 0;
        }

        public void startPost(long handle, int w, int h, boolean is_text, boolean is_pitcure) {
            this.is_exit_ = false;
            this.handle_ = handle;

            try {
                this.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public void stopPost() {
            this.is_exit_ = true;

            try {
                this.join(1000);
            }
            catch (Exception e) {
                e.printStackTrace();
            }

            handle_ = 0;
        }
    }

The external call logic is as follows:

    private LayerPostThread layer_post_thread_ = null;

    private void startLayerPostThread() {
        if (null == layer_post_thread_) {
            layer_post_thread_ = new LayerPostThread();
            layer_post_thread_.startPost(publisherHandle, video_width_, video_height_, isHasTextWatermark(), isHasPictureWatermark());
        }
    }

    private void stopLayerPostThread() {
        if (layer_post_thread_ != null) {
            layer_post_thread_.stopPost();
            layer_post_thread_ = null;
        }
    }

To put it simply, the read Bitmap data is converted to bytebuffer, and then delivered to the bottom layer by calling the PostLayerImageRGBA8888ByteBuffer() interface. The interface design of PostLayerImageRGBA8888ByteBuffer() is as follows:

    /*
     * SmartPublisherJniV2.java
     * Author: daniusdk.com
     */
	/**
	 * 投递层RGBA8888图像,如果不需要Aplpha通道的话, 请使用RGBX8888接口, 效率高
	 *
	 * @param index: 层索引, 必须大于等于0, 注意:如果index是0的话,将忽略Alpha通道
	 *
	 * @param left: 层叠加的左上角坐标, 对于第0层的话传0
	 *
	 * @param top: 层叠加的左上角坐标, 对于第0层的话传0
	 *
	 * @param rgba_plane: rgba 图像数据
	 *
	 * @param offset: 图像偏移, 这个主要目的是用来做clip的, 一般传0
	 *
	 * @param row_stride: stride information
	 *
	 * @param width: width, 必须大于1, 如果是奇数, 将减1
	 *
	 * @param height: height, 必须大于1, 如果是奇数, 将减1
	 *
	 * @param  is_vertical_flip: 是否垂直翻转, 0不翻转, 1翻转
	 *
	 * @param  is_horizontal_flip:是否水平翻转, 0不翻转, 1翻转
	 *
	 * @param  scale_width: 缩放宽,必须是偶数, 0或负数不缩放
	 *
	 * @param  scale_height: 缩放高, 必须是偶数, 0或负数不缩放
	 *
	 * @param  scale_filter_mode: 缩放质量, 传0使用默认速度,可选等级范围是:[1,3],值越大缩放质量越好, 但速度越慢
	 *
	 * @param  rotation_degree: 顺时针旋转, 必须是0, 90, 180, 270, 注意:旋转是在缩放, 垂直/水品反转之后再做, 请留意顺序
	 *
	 * @return {0} if successful
	 */
	public native int PostLayerImageRGBA8888ByteBuffer(long handle, int index, int left, int top,
											 ByteBuffer rgba_plane, int offset, int row_stride, int width, int height,
											 int is_vertical_flip,  int is_horizontal_flip,
											 int scale_width,  int scale_height, int scale_filter_mode,
											 int rotation_degree);

This interface is very powerful, and can perform various operations such as cropping and inversion on the passed data. Interested developers can try it out.

Guess you like

Origin blog.csdn.net/renhui1112/article/details/130293451