1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package androidx.media.filterfw;
16
17import java.util.Vector;
18
19class FrameQueue {
20
21    public static class Builder {
22
23        private FrameType mReadType = null;
24        private FrameType mWriteType = null;
25
26        private Vector<FrameQueue> mAttachedQueues = new Vector<FrameQueue>();
27
28        public Builder() {}
29
30        public void setWriteType(FrameType type) {
31            mWriteType = type;
32        }
33
34        public void setReadType(FrameType type) {
35            mReadType = type;
36        }
37
38        public void attachQueue(FrameQueue queue) {
39            mAttachedQueues.add(queue);
40        }
41
42        public FrameQueue build(String name) {
43            FrameType type = buildType();
44            // TODO: This currently does not work correctly (Try camera -> branch -> target-slot)
45            //validateType(type, name);
46            FrameQueue result = new FrameQueue(type, name);
47            buildQueueImpl(result);
48            return result;
49        }
50
51        private void buildQueueImpl(FrameQueue queue) {
52            QueueImpl queueImpl = queue.new SingleFrameQueueImpl();
53            queue.mQueueImpl = queueImpl;
54        }
55
56        private FrameType buildType() {
57            FrameType result = FrameType.merge(mWriteType, mReadType);
58            for (FrameQueue queue : mAttachedQueues) {
59                result = FrameType.merge(result, queue.mType);
60            }
61            return result;
62        }
63
64        /*
65        private void validateType(FrameType type, String queueName) {
66            if (!type.isSpecified()) {
67                throw new RuntimeException("Cannot build connection queue '" + queueName + "' as "
68                        + "its type (" + type + ") is underspecified!");
69            }
70        }
71         */
72    }
73
74    private interface QueueImpl {
75        public boolean canPull();
76
77        public boolean canPush();
78
79        public Frame pullFrame();
80
81        public Frame fetchAvailableFrame(int[] dimensions);
82
83        public Frame peek();
84
85        public void pushFrame(Frame frame);
86
87        public void clear();
88    }
89
90    private class SingleFrameQueueImpl implements QueueImpl {
91        private Frame mFrame = null;
92
93        @Override
94        public boolean canPull() {
95            return mFrame != null;
96        }
97
98        @Override
99        public boolean canPush() {
100            return mFrame == null;
101        }
102
103        @Override
104        public Frame pullFrame() {
105            Frame result = mFrame;
106            mFrame = null;
107            return result;
108        }
109
110        @Override
111        public Frame peek() {
112            return mFrame;
113        }
114
115        @Override
116        public Frame fetchAvailableFrame(int[] dimensions) {
117            // Note that we cannot use a cached frame here, as we do not know where that cached
118            // instance would end up.
119            FrameManager manager = FrameManager.current();
120            return new Frame(mType, dimensions, manager);
121        }
122
123        @Override
124        public void pushFrame(Frame frame) {
125            mFrame = frame.retain();
126            mFrame.setReadOnly(true);
127        }
128
129        @Override
130        public void clear() {
131            if (mFrame != null) {
132                mFrame.release();
133                mFrame = null;
134            }
135        }
136    }
137
138    private QueueImpl mQueueImpl;
139    private FrameType mType;
140    private String mName;
141
142    public FrameType getType() {
143        return mType;
144    }
145
146    public boolean canPull() {
147        return mQueueImpl.canPull();
148    }
149
150    public boolean canPush() {
151        return mQueueImpl.canPush();
152    }
153
154    public Frame pullFrame() {
155        return mQueueImpl.pullFrame();
156    }
157
158    public Frame fetchAvailableFrame(int[] dimensions) {
159        return mQueueImpl.fetchAvailableFrame(dimensions);
160    }
161
162    public void pushFrame(Frame frame) {
163        mQueueImpl.pushFrame(frame);
164    }
165
166    public Frame peek() {
167        return mQueueImpl.peek();
168    }
169
170    @Override
171    public String toString() {
172        return mName;
173    }
174
175    public void clear() {
176        mQueueImpl.clear();
177    }
178
179    private FrameQueue(FrameType type, String name) {
180        mType = type;
181        mName = name;
182    }
183
184}
185