Skip to content

Most visited

Recently visited

navigation
HdrViewfinder / src / com.example.android.hdrviewfinder /

ViewfinderProcessor.java

1
/*
2
 * Copyright (C) 2014 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
 
17
package com.example.android.hdrviewfinder;
18
 
19
import android.graphics.ImageFormat;
20
import android.os.Handler;
21
import android.os.HandlerThread;
22
import android.renderscript.Allocation;
23
import android.renderscript.Element;
24
import android.renderscript.RenderScript;
25
import android.renderscript.Type;
26
import android.util.Size;
27
import android.view.Surface;
28
 
29
/**
30
 * Renderscript-based merger for an HDR viewfinder
31
 */
32
public class ViewfinderProcessor {
33
 
34
    private Allocation mInputHdrAllocation;
35
    private Allocation mInputNormalAllocation;
36
    private Allocation mPrevAllocation;
37
    private Allocation mOutputAllocation;
38
 
39
    private Surface mOutputSurface;
40
    private HandlerThread mProcessingThread;
41
    private Handler mProcessingHandler;
42
    private ScriptC_hdr_merge mHdrMergeScript;
43
 
44
    public ProcessingTask mHdrTask;
45
    public ProcessingTask mNormalTask;
46
 
47
    private Size mSize;
48
 
49
    private int mMode;
50
 
51
    public final static int MODE_NORMAL = 0;
52
    public final static int MODE_SIDE_BY_SIDE = 1;
53
    public final static int MODE_HDR = 2;
54
 
55
    public ViewfinderProcessor(RenderScript rs, Size dimensions) {
56
        mSize = dimensions;
57
 
58
        Type.Builder yuvTypeBuilder = new Type.Builder(rs, Element.YUV(rs));
59
        yuvTypeBuilder.setX(dimensions.getWidth());
60
        yuvTypeBuilder.setY(dimensions.getHeight());
61
        yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
62
        mInputHdrAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
63
                Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
64
        mInputNormalAllocation = Allocation.createTyped(rs, yuvTypeBuilder.create(),
65
                Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
66
 
67
        Type.Builder rgbTypeBuilder = new Type.Builder(rs, Element.RGBA_8888(rs));
68
        rgbTypeBuilder.setX(dimensions.getWidth());
69
        rgbTypeBuilder.setY(dimensions.getHeight());
70
        mPrevAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
71
                Allocation.USAGE_SCRIPT);
72
        mOutputAllocation = Allocation.createTyped(rs, rgbTypeBuilder.create(),
73
                Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
74
 
75
        mProcessingThread = new HandlerThread("ViewfinderProcessor");
76
        mProcessingThread.start();
77
        mProcessingHandler = new Handler(mProcessingThread.getLooper());
78
 
79
        mHdrMergeScript = new ScriptC_hdr_merge(rs);
80
 
81
        mHdrMergeScript.set_gPrevFrame(mPrevAllocation);
82
 
83
        mHdrTask = new ProcessingTask(mInputHdrAllocation, dimensions.getWidth()/2, true);
84
        mNormalTask = new ProcessingTask(mInputNormalAllocation, 0, false);
85
 
86
        setRenderMode(MODE_NORMAL);
87
    }
88
 
89
    public Surface getInputHdrSurface() {
90
        return mInputHdrAllocation.getSurface();
91
    }
92
 
93
    public Surface getInputNormalSurface() {
94
        return mInputNormalAllocation.getSurface();
95
    }
96
 
97
    public void setOutputSurface(Surface output) {
98
        mOutputAllocation.setSurface(output);
99
    }
100
 
101
    public void setRenderMode(int mode) {
102
        mMode = mode;
103
    }
104
 
105
    /**
106
     * Simple class to keep track of incoming frame count,
107
     * and to process the newest one in the processing thread
108
     */
109
    class ProcessingTask implements Runnable, Allocation.OnBufferAvailableListener {
110
        private int mPendingFrames = 0;
111
        private int mFrameCounter = 0;
112
        private int mCutPointX;
113
        private boolean mCheckMerge;
114
 
115
        private Allocation mInputAllocation;
116
 
117
        public ProcessingTask(Allocation input, int cutPointX, boolean checkMerge) {
118
            mInputAllocation = input;
119
            mInputAllocation.setOnBufferAvailableListener(this);
120
            mCutPointX = cutPointX;
121
            mCheckMerge = checkMerge;
122
        }
123
 
124
        @Override
125
        public void onBufferAvailable(Allocation a) {
126
            synchronized(this) {
127
                mPendingFrames++;
128
                mProcessingHandler.post(this);
129
            }
130
        }
131
 
132
        @Override
133
        public void run() {
134
 
135
            // Find out how many frames have arrived
136
            int pendingFrames;
137
            synchronized(this) {
138
                pendingFrames = mPendingFrames;
139
                mPendingFrames = 0;
140
 
141
                // Discard extra messages in case processing is slower than frame rate
142
                mProcessingHandler.removeCallbacks(this);
143
            }
144
 
145
            // Get to newest input
146
            for (int i = 0; i < pendingFrames; i++) {
147
                mInputAllocation.ioReceive();
148
            }
149
 
150
            mHdrMergeScript.set_gFrameCounter(mFrameCounter++);
151
            mHdrMergeScript.set_gCurrentFrame(mInputAllocation);
152
            mHdrMergeScript.set_gCutPointX(mCutPointX);
153
            if (mCheckMerge && mMode == MODE_HDR) {
154
                mHdrMergeScript.set_gDoMerge(1);
155
            } else {
156
                mHdrMergeScript.set_gDoMerge(0);
157
            }
158
 
159
            // Run processing pass
160
            mHdrMergeScript.forEach_mergeHdrFrames(mPrevAllocation, mOutputAllocation);
161
            mOutputAllocation.ioSend();
162
        }
163
    }
164
 
165
}
This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.