RateShareEntry.java revision dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf
1/*
2 * Copyright 2012 castLabs, Berlin
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
18package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
19
20import com.coremedia.iso.IsoTypeReader;
21import com.coremedia.iso.IsoTypeWriter;
22
23import java.nio.ByteBuffer;
24import java.util.LinkedList;
25import java.util.List;
26
27import static com.googlecode.mp4parser.util.CastUtils.l2i;
28
29/**
30 * Each sample of a track may be associated to (zero or) one of a number of sample group descriptions, each of
31 * which defines a record of rate-share information. Typically the same rate-share information applies to many
32 * consecutive samples and it may therefore be enough to define two or three sample group descriptions that
33 * can be used at different time intervals.
34 * <p/>
35 * The grouping type 'rash' (short for rate share) is defined as the grouping criterion for rate share information.
36 * Zero or one sample-to-group box ('sbgp') for the grouping type 'rash' can be contained in the sample
37 * table box ('stbl') of a track. It shall reside in a hint track, if a hint track is used, otherwise in a media track.
38 * <p/>
39 * Target rate share may be specified for several operation points that are defined in terms of the total available
40 * bitrate, i.e., the bitrate that should be shared. If only one operation point is defined, the target rate share
41 * applies to all available bitrates. If several operation points are defined, then each operation point specifies a
42 * target rate share. Target rate share values specified for the first and the last operation points also specify the
43 * target rate share values at lower and higher available bitrates, respectively. The target rate share between two
44 * operation points is specified to be in the range between the target rate shares of those operation points. One
45 * possibility is to estimate with linear interpolation.
46 */
47public class RateShareEntry extends GroupEntry {
48    public static final String TYPE = "rash";
49
50    private short operationPointCut;
51    private short targetRateShare;
52    private List<Entry> entries = new LinkedList<Entry>();
53    private int maximumBitrate;
54    private int minimumBitrate;
55    private short discardPriority;
56
57
58    @Override
59    public void parse(ByteBuffer byteBuffer) {
60        operationPointCut = byteBuffer.getShort();
61        if (operationPointCut == 1) {
62            targetRateShare = byteBuffer.getShort();
63        } else {
64            int entriesLeft = operationPointCut;
65            while (entriesLeft-- > 0) {
66                entries.add(new Entry(l2i(IsoTypeReader.readUInt32(byteBuffer)), byteBuffer.getShort()));
67            }
68        }
69        maximumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
70        minimumBitrate = l2i(IsoTypeReader.readUInt32(byteBuffer));
71        discardPriority = (short) IsoTypeReader.readUInt8(byteBuffer);
72    }
73
74    @Override
75    public ByteBuffer get() {
76        ByteBuffer buf = ByteBuffer.allocate(operationPointCut == 1?13:(operationPointCut * 6 + 11 ));
77        buf.putShort(operationPointCut);
78        if (operationPointCut == 1) {
79            buf.putShort(targetRateShare );
80        } else {
81            for (Entry entry : entries) {
82                buf.putInt(entry.getAvailableBitrate());
83                buf.putShort(entry.getTargetRateShare());
84            }
85        }
86        buf.putInt(maximumBitrate);
87        buf.putInt(minimumBitrate);
88        IsoTypeWriter.writeUInt8(buf, discardPriority);
89        buf.rewind();
90        return buf;
91    }
92
93    public static class Entry {
94        public Entry(int availableBitrate, short targetRateShare) {
95            this.availableBitrate = availableBitrate;
96            this.targetRateShare = targetRateShare;
97        }
98
99        int availableBitrate;
100        short targetRateShare;
101
102        @Override
103        public String toString() {
104            return "{" +
105                    "availableBitrate=" + availableBitrate +
106                    ", targetRateShare=" + targetRateShare +
107                    '}';
108        }
109
110        public int getAvailableBitrate() {
111            return availableBitrate;
112        }
113
114        public void setAvailableBitrate(int availableBitrate) {
115            this.availableBitrate = availableBitrate;
116        }
117
118        public short getTargetRateShare() {
119            return targetRateShare;
120        }
121
122        public void setTargetRateShare(short targetRateShare) {
123            this.targetRateShare = targetRateShare;
124        }
125
126        @Override
127        public boolean equals(Object o) {
128            if (this == o) {
129                return true;
130            }
131            if (o == null || getClass() != o.getClass()) {
132                return false;
133            }
134
135            Entry entry = (Entry) o;
136
137            if (availableBitrate != entry.availableBitrate) {
138                return false;
139            }
140            if (targetRateShare != entry.targetRateShare) {
141                return false;
142            }
143
144            return true;
145        }
146
147        @Override
148        public int hashCode() {
149            int result = availableBitrate;
150            result = 31 * result + (int) targetRateShare;
151            return result;
152        }
153    }
154
155    @Override
156    public boolean equals(Object o) {
157        if (this == o) {
158            return true;
159        }
160        if (o == null || getClass() != o.getClass()) {
161            return false;
162        }
163
164        RateShareEntry that = (RateShareEntry) o;
165
166        if (discardPriority != that.discardPriority) {
167            return false;
168        }
169        if (maximumBitrate != that.maximumBitrate) {
170            return false;
171        }
172        if (minimumBitrate != that.minimumBitrate) {
173            return false;
174        }
175        if (operationPointCut != that.operationPointCut) {
176            return false;
177        }
178        if (targetRateShare != that.targetRateShare) {
179            return false;
180        }
181        if (entries != null ? !entries.equals(that.entries) : that.entries != null) {
182            return false;
183        }
184
185        return true;
186    }
187
188    @Override
189    public int hashCode() {
190        int result = (int) operationPointCut;
191        result = 31 * result + (int) targetRateShare;
192        result = 31 * result + (entries != null ? entries.hashCode() : 0);
193        result = 31 * result + maximumBitrate;
194        result = 31 * result + minimumBitrate;
195        result = 31 * result + (int) discardPriority;
196        return result;
197    }
198
199    public short getOperationPointCut() {
200        return operationPointCut;
201    }
202
203    public void setOperationPointCut(short operationPointCut) {
204        this.operationPointCut = operationPointCut;
205    }
206
207    public short getTargetRateShare() {
208        return targetRateShare;
209    }
210
211    public void setTargetRateShare(short targetRateShare) {
212        this.targetRateShare = targetRateShare;
213    }
214
215    public List<Entry> getEntries() {
216        return entries;
217    }
218
219    public void setEntries(List<Entry> entries) {
220        this.entries = entries;
221    }
222
223    public int getMaximumBitrate() {
224        return maximumBitrate;
225    }
226
227    public void setMaximumBitrate(int maximumBitrate) {
228        this.maximumBitrate = maximumBitrate;
229    }
230
231    public int getMinimumBitrate() {
232        return minimumBitrate;
233    }
234
235    public void setMinimumBitrate(int minimumBitrate) {
236        this.minimumBitrate = minimumBitrate;
237    }
238
239    public short getDiscardPriority() {
240        return discardPriority;
241    }
242
243    public void setDiscardPriority(short discardPriority) {
244        this.discardPriority = discardPriority;
245    }
246}
247