1

我需要有关我正在处理的应用程序的帮助。该应用程序必须有一个自定义的相机接口来录制带音频的视频,并且必须在 TextureView 画布上实时添加一些对象。旧的 Camera API 已弃用,因此我必须使用 Camera2 API 在 TextureView 上呈现实时预览。我的目标是在 TextureView 画布上绘制一些对象,可以是一些文本/jpg/gif,而相机流在后台呈现,并且能够使用我的覆盖画布内容和相机馈送来录制视频。

问题是我可以在透明覆盖视图中绘制自定义内容,但这只是为了用户的查看目的。我已经尝试研究了几天,但我无法找到正确的方法来解决我的目的。

我在调用 openCamera() 方法后尝试了以下代码,但随后我只看到了一个绘制的矩形,但没有看到相机预览:

Canvas canvas = mTextureView.lockCanvas();
Paint myPaint = new Paint();
myPaint.setColor(Color.WHITE);
myPaint.setStrokeWidth(10);
canvas.drawRect(100, 100, 300, 300, myPaint);
mTextureView.unlockCanvasAndPost(canvas);

我还尝试了一个自定义 TextureView 类并覆盖了 vonDrawForeground(Canvas canvas) 方法,但它不起作用。

TextureView 类中的 onDraw() 方法是最终的,因此,除了流式传输相机源之外,我此时无法做任何事情。

/**
 * Subclasses of TextureView cannot do their own rendering
 * with the {@link Canvas} object.
 *
 * @param canvas The Canvas to which the View is rendered.
 */
@Override
protected final void onDraw(Canvas canvas) {
}

简而言之,我希望用户能够通过我的相机应用程序录制视频,并在这里和那里使用一些道具。

4

2 回答 2

0

可能最高效的选择是将相机馈送直接输入 GPU,在 GPU 上绘制,然后从那里直接渲染到显示器和视频编码器。

这就是许多视频聊天应用程序所做的,例如,用于任何效果。

您可以使用 SurfaceTexture 将 camera2 连接到 EGL,然后您可以将预览渲染到四边形上,然后在顶部进行添加。

然后,您可以渲染到屏幕缓冲区(例如 GLSurfaceView),并渲染到来自 MediaRecorder/MediaCodec Surface 的单独 EGLImage。

那里涉及很多代码,并且有很多用于 EGL 设置的脚手架,因此很难指出任何简单的示例。

于 2017-10-05T20:02:45.900 回答
0

实时修改视频是一个高处理器,因此,高电池开销操作 - 我相信你知道这一点,但值得一提的是,如果你可以在服务器端添加你的修改,也许通过发送带有时间戳集的流文本覆盖到服务器,你应该有更多的马力服务器端。

以下代码将在 Android 上的 Camera2 捕获的静止图片或帧中添加文本和图像。我没有将它与视频一起使用,因此无法评论速度以及使用实时视频流执行此操作是否实用 - 它没有为此进行优化,但它应该是您的起点:

        //Copy the image to a BitBuffer
        ByteBuffer buffer = mCameraImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        Log.d(TAG,"ImageSaver bytes.length: " + bytes.length);
        buffer.get(bytes);
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inMutable = true;
        Bitmap cameraBitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length, opt);
        if (cameraBitmap == null) {
            Log.d(TAG,"ImageSaver cameraBitmap is null");
            return;
        } else {
            camImgBitmap = cameraBitmap;
        }

        //Modify captured picture by drawing on canvas
        Canvas camImgCanvas = new Canvas(camImgBitmap);

        //Draw an image in the middle
        Drawable d = ContextCompat.getDrawable(this, R.drawable.image_to_add);
        int bitMapWidthCenter = camImgBitmap.getWidth()/2;
        int bitMapheightCenter = camImgBitmap.getHeight()/2;
        int imageToDrawSize = camImgBitmap.getWidth()/10;
        int rTop = bitMapheightCenter - sightsSize;
        int rLeft = bitMapWidthCenter - sightsSize;
        int rRight = bitMapWidthCenter + sightsSize;
        int rBot = bitMapheightCenter + sightsSize;
        d.setBounds(rLeft, rTop, rRight, rBot);
        d.draw(camImgCanvas);

        //Now Draw in some text
        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        int textSize = camImgBitmap.getHeight()/20;
        int textPadding = 40;
        paint.setTextSize(textSize);
        camImgCanvas.drawText("Name: " + text1, textPadding, (camImgBitmap.getHeight() - (textSize * 2) ) - textPadding, paint);
        camImgCanvas.drawText("Time: " + text2 + " degrees", textPadding, (camImgBitmap.getHeight() - textSize) - textPadding, paint);
于 2017-10-05T09:44:40.660 回答