OSDN Git Service

Add timestamp support into core mobile filter framework.
[android-x86/system-media.git] / mca / filterfw / java / android / filterfw / core / CachedFrameManager.java
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
17
18 package android.filterfw.core;
19
20 import android.filterfw.core.Frame;
21 import android.filterfw.core.FrameFormat;
22 import android.filterfw.core.SimpleFrameManager;
23
24 import java.util.Map;
25 import java.util.SortedMap;
26 import java.util.TreeMap;
27
28 import android.util.Log;
29
30 /**
31  * @hide
32  */
33 public class CachedFrameManager extends SimpleFrameManager {
34
35     private SortedMap<Integer, Frame> mAvailableFrames;
36     private int mStorageCapacity = 24 * 1024 * 1024; // Cap default storage to 24MB
37     private int mStorageSize = 0;
38     private int mTimeStamp = 0;
39
40     public CachedFrameManager() {
41         super();
42         mAvailableFrames = new TreeMap<Integer, Frame>();
43     }
44
45     @Override
46     public Frame newFrame(FrameFormat format) {
47         Frame result = findAvailableFrame(format, Frame.NO_BINDING, 0);
48         if (result == null) {
49             result = super.newFrame(format);
50         }
51         result.setTimestamp(Frame.TIMESTAMP_NOT_SET);
52         return result;
53     }
54
55     @Override
56     public Frame newBoundFrame(FrameFormat format, int bindingType, long bindingId) {
57         Frame result = findAvailableFrame(format, bindingType, bindingId);
58         if (result == null) {
59             result = super.newBoundFrame(format, bindingType, bindingId);
60         }
61         result.setTimestamp(Frame.TIMESTAMP_NOT_SET);
62         return result;
63     }
64
65     @Override
66     public Frame retainFrame(Frame frame) {
67         return super.retainFrame(frame);
68     }
69
70     @Override
71     public Frame releaseFrame(Frame frame) {
72         if (frame.isReusable()) {
73             int refCount = frame.decRefCount();
74             if (refCount == 0) {
75                 if (!storeFrame(frame)) {
76                     frame.dealloc();
77                 }
78                 return null;
79             } else if (refCount < 0) {
80                 throw new RuntimeException("Frame reference count dropped below 0!");
81             }
82         } else {
83             super.releaseFrame(frame);
84         }
85         return frame;
86     }
87
88     private boolean storeFrame(Frame frame) {
89         synchronized(mAvailableFrames) {
90             // Make sure this frame alone does not exceed capacity
91             int frameSize = frame.getFormat().getSize();
92             if (frameSize > mStorageCapacity) {
93                 return false;
94             }
95
96             // Drop frames if adding this frame would exceed capacity
97             int newStorageSize = mStorageSize + frameSize;
98             while (newStorageSize > mStorageCapacity) {
99                 dropOldestFrame();
100                 newStorageSize = mStorageSize + frameSize;
101             }
102
103             // Store new frame
104             mStorageSize = newStorageSize;
105             mAvailableFrames.put(mTimeStamp, frame);
106             ++mTimeStamp;
107             return true;
108         }
109     }
110
111     private void dropOldestFrame() {
112         int oldest = mAvailableFrames.firstKey();
113         Frame frame = mAvailableFrames.get(oldest);
114         mStorageSize -= frame.getFormat().getSize();
115         frame.dealloc();
116         mAvailableFrames.remove(oldest);
117     }
118
119     private Frame findAvailableFrame(FrameFormat format, int bindingType, long bindingId) {
120         // Look for a frame that is compatible with the requested format
121         synchronized(mAvailableFrames) {
122             for (Map.Entry<Integer, Frame> entry : mAvailableFrames.entrySet()) {
123                 Frame frame = entry.getValue();
124                 // Check that format is compatible
125                 if (frame.getFormat().isReplaceableBy(format)) {
126                     // Check that binding is compatible (if frame is bound)
127                     if (bindingType == Frame.NO_BINDING
128                         || (bindingId == frame.getBindingId()
129                             && bindingType == frame.getBindingType())) {
130                         // We found one! Take it out of the set of available frames and attach the
131                         // requested format to it.
132                         super.retainFrame(frame);
133                         mAvailableFrames.remove(entry.getKey());
134                         frame.reset(format);
135                         mStorageSize -= format.getSize();
136                         return frame;
137                     }
138                 }
139             }
140         }
141         return null;
142     }
143 }