1/*
2 * Copyright (C) 2011 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 androidx.media.filterfw;
18
19import java.lang.reflect.Array;
20
21public class FrameValues extends FrameValue {
22
23    /**
24     * Returns the number of values in the Frame.
25     *
26     * This returns 1, if the Frame value is null, or if the value is not an array.
27     *
28     * @return The number of values in the Frame.
29     */
30    public int getCount() {
31        Object value = super.getValue();
32        if (value == null || !value.getClass().isArray()) {
33            return 1;
34        } else {
35            return Array.getLength(super.getValue());
36        }
37    }
38
39    /**
40     * Returns the values in the Frame as an array.
41     *
42     * Note, that this may be called on Frames that have a non-array object assigned to them. In
43     * that case, this method will wrap the object in an array and return that. This way, filters
44     * can treat any object based frame as arrays.
45     *
46     * @return The array of values in this frame.
47     */
48    public Object getValues() {
49        Object value = super.getValue();
50        if (value == null || value.getClass().isArray()) {
51            return super.getValue();
52        } else {
53            // Allow reading a single as an array.
54            Object[] array = (Object[])Array.newInstance(value.getClass(), 1);
55            array[0] = value;
56            return array;
57        }
58    }
59
60    /**
61     * Returns the value at the specified index.
62     *
63     * In case the value is null or not an array, the index must be 0, and the value itself is
64     * returned.
65     *
66     * @param index The index to access.
67     * @return The value at that index.
68     */
69    public Object getValueAtIndex(int index) {
70        Object value = super.getValue();
71        if (value == null || !value.getClass().isArray()) {
72            if (index != 0) {
73                throw new ArrayIndexOutOfBoundsException(index);
74            } else {
75                return value;
76            }
77        } else {
78            return Array.get(value, index);
79        }
80    }
81
82    /**
83     * Returns the value as a FrameValue at the specified index.
84     *
85     * Use this if you want to access elements as FrameValues. You must release the result when
86     * you are done using it.
87     *
88     * @param index The index to access.
89     * @return The value as a FrameValue at that index (must release).
90     */
91    public FrameValue getFrameValueAtIndex(int index) {
92        Object value = getValueAtIndex(index);
93        FrameValue result = Frame.create(getType().asSingle(), new int[0]).asFrameValue();
94        result.setValue(value);
95        return result;
96    }
97
98    /**
99     * Assign the array of values to the frame.
100     *
101     * You may assign null or a non-array object, which are interpreted as a 1-length array.
102     *
103     * @param values The values to assign to the frame.
104     */
105    public void setValues(Object values) {
106        super.setValue(values);
107    }
108
109    /**
110     * Assign a value at the specified index.
111     *
112     * In case the held value is not an array, the index must be 0, and the object will be replaced
113     * by the new object.
114     *
115     * @param value The value to assign.
116     * @param index The index to assign to.
117     */
118    public void setValueAtIndex(Object value, int index) {
119        super.assertAccessible(MODE_WRITE);
120        Object curValue = super.getValue();
121        if (curValue == null || !curValue.getClass().isArray()) {
122            if (index != 0) {
123                throw new ArrayIndexOutOfBoundsException(index);
124            } else {
125                curValue = value;
126            }
127        } else {
128            Array.set(curValue, index, value);
129        }
130    }
131
132    /**
133     * Assign a FrameValue's value at the specified index.
134     *
135     * This method unpacks the FrameValue and assigns the unpacked value to the specified index.
136     * This does not affect the retain-count of the passed Frame.
137     *
138     * @param frame The frame value to assign.
139     * @param index The index to assign to.
140     */
141    public void setFrameValueAtIndex(FrameValue frame, int index) {
142        Object value = frame.getValue();
143        setValueAtIndex(value, index);
144    }
145
146    static FrameValues create(BackingStore backingStore) {
147        assertObjectBased(backingStore.getFrameType());
148        return new FrameValues(backingStore);
149    }
150
151    FrameValues(BackingStore backingStore) {
152        super(backingStore);
153    }
154}
155
156