1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.captureintent.resource;
18
19import com.android.camera.async.MainThread;
20import com.android.camera.async.RefCountBase;
21import com.android.camera.captureintent.PreviewTransformCalculator;
22import com.android.camera.debug.Log;
23import com.android.camera.util.Size;
24
25import android.graphics.Matrix;
26import android.graphics.SurfaceTexture;
27import android.view.Surface;
28
29import javax.annotation.ParametersAreNonnullByDefault;
30
31@ParametersAreNonnullByDefault
32public class ResourceSurfaceTextureImpl implements ResourceSurfaceTexture {
33    private static final Log.Tag TAG = new Log.Tag("ResSurfaceTexture");
34
35    private final RefCountBase<ResourceConstructed> mResourceConstructed;
36
37    /** The surface texture. */
38    private final SurfaceTexture mSurfaceTexture;
39
40    /** The preview stream size. */
41    private Size mPreviewSize;
42
43    /** The preview layout size. */
44    private Size mPreviewLayoutSize;
45
46    /** The default buffer size in SurfaceTexture. */
47    private Size mSurfaceTextureDefaultBufferSize;
48
49    private final PreviewTransformCalculator mPreviewTransformCalculator;
50
51    /**
52     * Creates a reference counted {@link ResourceSurfaceTextureImpl} object.
53     */
54    public static RefCountBase<ResourceSurfaceTexture> create(
55            RefCountBase<ResourceConstructed> resourceConstructed,
56            SurfaceTexture surfaceTexture) {
57        ResourceSurfaceTexture resourceSurfaceTexture = new ResourceSurfaceTextureImpl(
58                resourceConstructed,
59                surfaceTexture,
60                new PreviewTransformCalculator(resourceConstructed.get().getOrientationManager()));
61        return new RefCountBase<>(resourceSurfaceTexture);
62    }
63
64    protected ResourceSurfaceTextureImpl(
65            RefCountBase<ResourceConstructed> resourceConstructed,
66            SurfaceTexture surfaceTexture,
67            PreviewTransformCalculator previewTransformCalculator) {
68        mResourceConstructed = resourceConstructed;
69        mResourceConstructed.addRef();
70        mSurfaceTexture = surfaceTexture;
71        mPreviewTransformCalculator = previewTransformCalculator;
72        mPreviewSize = new Size(0, 0);
73        mPreviewLayoutSize = new Size(0, 0);
74        mSurfaceTextureDefaultBufferSize = new Size(0, 0);
75    }
76
77    public RefCountBase<ResourceConstructed> getResourceConstructed() {
78        return mResourceConstructed;
79    }
80
81    @Override
82    public Surface createPreviewSurface() {
83        return new Surface(mSurfaceTexture);
84    }
85
86    @Override
87    public Size getPreviewSize() {
88        return mPreviewSize;
89    }
90
91    @Override
92    public Size getPreviewLayoutSize() {
93        return mPreviewLayoutSize;
94    }
95
96    @Override
97    public void setPreviewSize(Size previewSize) {
98        // Update preview transform when preview stream size is changed.
99        if (!mPreviewSize.equals(previewSize)) {
100            mPreviewSize = previewSize;
101
102            /**
103             * Update transform here since preview size might change when
104             * switching between back and front camera.
105             */
106            mResourceConstructed.get().getMainThread().execute(new Runnable() {
107                @Override
108                public void run() {
109                    updatePreviewTransform();
110                }
111            });
112        }
113
114        // Update surface texture's default buffer size. See b/17286155.
115        mSurfaceTexture.setDefaultBufferSize(mPreviewSize.width(), mPreviewSize.height());
116    }
117
118    @Override
119    public void setPreviewLayoutSize(Size previewLayoutSize) {
120        MainThread.checkMainThread();
121
122        // Update preview transform when preview layout size is changed.
123        if (!mPreviewLayoutSize.equals(previewLayoutSize)) {
124            mPreviewLayoutSize = previewLayoutSize;
125            updatePreviewTransform();
126        }
127    }
128
129    /**
130     * Updates the default buffer size in SurfaceTexture with the configured
131     * preview stream size.
132     */
133    protected void updateSurfaceTextureDefaultBufferSize(Size defaultBufferSize) {
134        mSurfaceTexture.setDefaultBufferSize(defaultBufferSize.width(), defaultBufferSize.height());
135    }
136
137    @Override
138    public void updatePreviewTransform() {
139        MainThread.checkMainThread();
140        if (mPreviewSize.getWidth() == 0 || mPreviewSize.getHeight() == 0) {
141            Log.w(TAG, "Do nothing since mPreviewSize is 0");
142            return;
143        }
144        if (mPreviewLayoutSize.getWidth() == 0 || mPreviewLayoutSize.getHeight() == 0) {
145            Log.w(TAG, "Do nothing since mPreviewLayoutSize is 0");
146            return;
147        }
148
149        Matrix transformMatrix = mPreviewTransformCalculator.toTransformMatrix(
150                mPreviewLayoutSize, mPreviewSize);
151        mResourceConstructed.get().getModuleUI().updatePreviewTransform(transformMatrix);
152    }
153
154    @Override
155    public void close() {
156        mResourceConstructed.close();
157    }
158}
159