blob: 96d7d4380e77f27d13471c0bc5dbd3de0feda184 [file] [log] [blame]
sakal836f60c2017-07-28 07:12:23 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11package org.webrtc;
12
13import android.graphics.Matrix;
Sami Kalliomäki61db3fd2018-04-09 17:51:19 +020014import javax.annotation.Nullable;
Magnus Jedvert1d270f82018-04-16 16:28:29 +020015import android.os.Handler;
sakal836f60c2017-07-28 07:12:23 -070016
17/**
Magnus Jedvert1d270f82018-04-16 16:28:29 +020018 * Android texture buffer that glues together the necessary information together with a generic
19 * release callback. ToI420() is implemented by providing a Handler and a YuvConverter.
sakal836f60c2017-07-28 07:12:23 -070020 */
Magnus Jedvert1d270f82018-04-16 16:28:29 +020021public class TextureBufferImpl implements VideoFrame.TextureBuffer {
sakal836f60c2017-07-28 07:12:23 -070022 private final int width;
23 private final int height;
24 private final Type type;
25 private final int id;
26 private final Matrix transformMatrix;
Magnus Jedvert1d270f82018-04-16 16:28:29 +020027 private final Handler toI420Handler;
28 private final YuvConverter yuvConverter;
Sami Kalliomäki61db3fd2018-04-09 17:51:19 +020029 private final RefCountDelegate refCountDelegate;
sakal836f60c2017-07-28 07:12:23 -070030
31 public TextureBufferImpl(int width, int height, Type type, int id, Matrix transformMatrix,
Magnus Jedvert1d270f82018-04-16 16:28:29 +020032 Handler toI420Handler, YuvConverter yuvConverter, @Nullable Runnable releaseCallback) {
sakal836f60c2017-07-28 07:12:23 -070033 this.width = width;
34 this.height = height;
35 this.type = type;
36 this.id = id;
37 this.transformMatrix = transformMatrix;
Magnus Jedvert1d270f82018-04-16 16:28:29 +020038 this.toI420Handler = toI420Handler;
39 this.yuvConverter = yuvConverter;
Sami Kalliomäki61db3fd2018-04-09 17:51:19 +020040 this.refCountDelegate = new RefCountDelegate(releaseCallback);
sakal836f60c2017-07-28 07:12:23 -070041 }
42
43 @Override
44 public VideoFrame.TextureBuffer.Type getType() {
45 return type;
46 }
47
48 @Override
49 public int getTextureId() {
50 return id;
51 }
52
53 @Override
54 public Matrix getTransformMatrix() {
55 return transformMatrix;
56 }
57
58 @Override
59 public int getWidth() {
60 return width;
61 }
62
63 @Override
64 public int getHeight() {
65 return height;
66 }
67
68 @Override
69 public VideoFrame.I420Buffer toI420() {
Magnus Jedvert1d270f82018-04-16 16:28:29 +020070 return ThreadUtils.invokeAtFrontUninterruptibly(
71 toI420Handler, () -> yuvConverter.convert(this));
sakal836f60c2017-07-28 07:12:23 -070072 }
73
74 @Override
75 public void retain() {
Sami Kalliomäki61db3fd2018-04-09 17:51:19 +020076 refCountDelegate.retain();
sakal836f60c2017-07-28 07:12:23 -070077 }
78
79 @Override
80 public void release() {
Sami Kalliomäki61db3fd2018-04-09 17:51:19 +020081 refCountDelegate.release();
sakal836f60c2017-07-28 07:12:23 -070082 }
83
84 @Override
85 public VideoFrame.Buffer cropAndScale(
86 int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth, int scaleHeight) {
Magnus Jedvert783c6e32018-07-05 13:34:17 +020087 final Matrix cropAndScaleMatrix = new Matrix();
Magnus Jedvert65070542018-06-14 12:23:01 +020088 // In WebRTC, Y=0 is the top row, while in OpenGL Y=0 is the bottom row. This means that the Y
89 // direction is effectively reversed.
90 final int cropYFromBottom = height - (cropY + cropHeight);
Magnus Jedvert783c6e32018-07-05 13:34:17 +020091 cropAndScaleMatrix.preTranslate(cropX / (float) width, cropYFromBottom / (float) height);
92 cropAndScaleMatrix.preScale(cropWidth / (float) width, cropHeight / (float) height);
Sami Kalliomäki64051d42018-04-16 13:37:07 +000093
Magnus Jedvert783c6e32018-07-05 13:34:17 +020094 return applyTransformMatrix(cropAndScaleMatrix, scaleWidth, scaleHeight);
95 }
96
97 /**
98 * Create a new TextureBufferImpl with an applied transform matrix and a new size. The
99 * existing buffer is unchanged. The given transform matrix is applied first when texture
100 * coordinates are still in the unmodified [0, 1] range.
101 */
102 public TextureBufferImpl applyTransformMatrix(
103 Matrix transformMatrix, int newWidth, int newHeight) {
104 final Matrix newMatrix = new Matrix(this.transformMatrix);
105 newMatrix.preConcat(transformMatrix);
Magnus Jedvert1d270f82018-04-16 16:28:29 +0200106 retain();
sakal836f60c2017-07-28 07:12:23 -0700107 return new TextureBufferImpl(
Magnus Jedvert783c6e32018-07-05 13:34:17 +0200108 newWidth, newHeight, type, id, newMatrix, toI420Handler, yuvConverter, this ::release);
sakal836f60c2017-07-28 07:12:23 -0700109 }
110}