1/*
2 * Copyright 2011 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
17package com.googlecode.mp4parser.boxes.mp4.objectdescriptors;
18
19import com.coremedia.iso.Hex;
20import com.coremedia.iso.IsoTypeReader;
21import com.coremedia.iso.IsoTypeWriter;
22
23import java.io.IOException;
24import java.nio.ByteBuffer;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.List;
28import java.util.logging.Logger;
29
30/**
31 * class DecoderConfigDescriptor extends BaseDescriptor : bit(8)
32 * tag=DecoderConfigDescrTag {
33 * bit(8) objectTypeIndication;
34 * bit(6) streamType;
35 * bit(1) upStream;
36 * const bit(1) reserved=1;
37 * bit(24) bufferSizeDB;
38 * bit(32) maxBitrate;
39 * bit(32) avgBitrate;
40 * DecoderSpecificInfo decSpecificInfo[0 .. 1];
41 * profileLevelIndicationIndexDescriptor profileLevelIndicationIndexDescr
42 * [0..255];
43 * }
44 */
45@Descriptor(tags = {0x04})
46public class DecoderConfigDescriptor extends BaseDescriptor {
47    private static Logger log = Logger.getLogger(DecoderConfigDescriptor.class.getName());
48
49
50    int objectTypeIndication;
51    int streamType;
52    int upStream;
53    int bufferSizeDB;
54    long maxBitRate;
55    long avgBitRate;
56
57    DecoderSpecificInfo decoderSpecificInfo;
58    AudioSpecificConfig audioSpecificInfo;
59    List<ProfileLevelIndicationDescriptor> profileLevelIndicationDescriptors = new ArrayList<ProfileLevelIndicationDescriptor>();
60    byte[] configDescriptorDeadBytes;
61
62    @Override
63    public void parseDetail(ByteBuffer bb) throws IOException {
64        objectTypeIndication = IsoTypeReader.readUInt8(bb);
65
66        int data = IsoTypeReader.readUInt8(bb);
67        streamType = data >>> 2;
68        upStream = (data >> 1) & 0x1;
69
70        bufferSizeDB = IsoTypeReader.readUInt24(bb);
71        maxBitRate = IsoTypeReader.readUInt32(bb);
72        avgBitRate = IsoTypeReader.readUInt32(bb);
73
74
75
76        BaseDescriptor descriptor;
77        if (bb.remaining() > 2) { //1byte tag + at least 1byte size
78            final int begin = bb.position();
79            descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
80            final int read = bb.position() - begin;
81            log.finer(descriptor + " - DecoderConfigDescr1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
82            if (descriptor != null) {
83                final int size = descriptor.getSize();
84                if (read < size) {
85                    //skip
86                    configDescriptorDeadBytes = new byte[size - read];
87                    bb.get(configDescriptorDeadBytes);
88                }
89            }
90            if (descriptor instanceof DecoderSpecificInfo) {
91                decoderSpecificInfo = (DecoderSpecificInfo) descriptor;
92            }
93            if (descriptor instanceof AudioSpecificConfig) {
94                audioSpecificInfo = (AudioSpecificConfig) descriptor;
95            }
96        }
97
98        while (bb.remaining() > 2) {
99            final long begin = bb.position();
100            descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb);
101            final long read = bb.position() - begin;
102            log.finer(descriptor + " - DecoderConfigDescr2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null));
103            if (descriptor instanceof ProfileLevelIndicationDescriptor) {
104                profileLevelIndicationDescriptors.add((ProfileLevelIndicationDescriptor) descriptor);
105            }
106        }
107    }
108    public int serializedSize() {
109        return 15 + audioSpecificInfo.serializedSize();
110    }
111
112    public ByteBuffer serialize() {
113        ByteBuffer out = ByteBuffer.allocate(serializedSize());
114        IsoTypeWriter.writeUInt8(out, 4);
115        IsoTypeWriter.writeUInt8(out, serializedSize() - 2);
116        IsoTypeWriter.writeUInt8(out, objectTypeIndication);
117        int flags = (streamType << 2) | (upStream << 1) | 1;
118        IsoTypeWriter.writeUInt8(out, flags);
119        IsoTypeWriter.writeUInt24(out, bufferSizeDB);
120        IsoTypeWriter.writeUInt32(out, maxBitRate);
121        IsoTypeWriter.writeUInt32(out, avgBitRate);
122        out.put(audioSpecificInfo.serialize().array());
123        return out;
124    }
125
126    public DecoderSpecificInfo getDecoderSpecificInfo() {
127        return decoderSpecificInfo;
128    }
129
130    public AudioSpecificConfig getAudioSpecificInfo() {
131        return audioSpecificInfo;
132    }
133
134    public void setAudioSpecificInfo(AudioSpecificConfig audioSpecificInfo) {
135        this.audioSpecificInfo = audioSpecificInfo;
136    }
137
138    public List<ProfileLevelIndicationDescriptor> getProfileLevelIndicationDescriptors() {
139        return profileLevelIndicationDescriptors;
140    }
141
142    public int getObjectTypeIndication() {
143        return objectTypeIndication;
144    }
145
146    public void setObjectTypeIndication(int objectTypeIndication) {
147        this.objectTypeIndication = objectTypeIndication;
148    }
149
150    public int getStreamType() {
151        return streamType;
152    }
153
154    public void setStreamType(int streamType) {
155        this.streamType = streamType;
156    }
157
158    public int getUpStream() {
159        return upStream;
160    }
161
162    public void setUpStream(int upStream) {
163        this.upStream = upStream;
164    }
165
166    public int getBufferSizeDB() {
167        return bufferSizeDB;
168    }
169
170    public void setBufferSizeDB(int bufferSizeDB) {
171        this.bufferSizeDB = bufferSizeDB;
172    }
173
174    public long getMaxBitRate() {
175        return maxBitRate;
176    }
177
178    public void setMaxBitRate(long maxBitRate) {
179        this.maxBitRate = maxBitRate;
180    }
181
182    public long getAvgBitRate() {
183        return avgBitRate;
184    }
185
186    public void setAvgBitRate(long avgBitRate) {
187        this.avgBitRate = avgBitRate;
188    }
189
190    @Override
191    public String toString() {
192        final StringBuilder sb = new StringBuilder();
193        sb.append("DecoderConfigDescriptor");
194        sb.append("{objectTypeIndication=").append(objectTypeIndication);
195        sb.append(", streamType=").append(streamType);
196        sb.append(", upStream=").append(upStream);
197        sb.append(", bufferSizeDB=").append(bufferSizeDB);
198        sb.append(", maxBitRate=").append(maxBitRate);
199        sb.append(", avgBitRate=").append(avgBitRate);
200        sb.append(", decoderSpecificInfo=").append(decoderSpecificInfo);
201        sb.append(", audioSpecificInfo=").append(audioSpecificInfo);
202        sb.append(", configDescriptorDeadBytes=").append(Hex.encodeHex(configDescriptorDeadBytes != null ? configDescriptorDeadBytes : new byte[]{}));
203        sb.append(", profileLevelIndicationDescriptors=").append(profileLevelIndicationDescriptors == null ? "null" : Arrays.asList(profileLevelIndicationDescriptors).toString());
204        sb.append('}');
205        return sb.toString();
206    }
207    /*objectTypeIndication values
208      0x00 Forbidden
209    0x01 Systems ISO/IEC 14496-1 a
210    0x02 Systems ISO/IEC 14496-1 b
211    0x03 Interaction Stream
212    0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c
213    0x05 Systems ISO/IEC 14496-1 AFX d
214    0x06 Font Data Stream
215    0x07 Synthesized Texture Stream
216    0x08 Streaming Text Stream
217    0x09-0x1F reserved for ISO use
218    0x20 Visual ISO/IEC 14496-2 e
219    0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
220    0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f
221    0x23-0x3F reserved for ISO use
222    0x40 Audio ISO/IEC 14496-3 g
223    0x41-0x5F reserved for ISO use
224    0x60 Visual ISO/IEC 13818-2 Simple Profile
225    0x61 Visual ISO/IEC 13818-2 Main Profile
226    0x62 Visual ISO/IEC 13818-2 SNR Profile
227    0x63 Visual ISO/IEC 13818-2 Spatial Profile
228    0x64 Visual ISO/IEC 13818-2 High Profile
229    0x65 Visual ISO/IEC 13818-2 422 Profile
230    0x66 Audio ISO/IEC 13818-7 Main Profile
231    0x67 Audio ISO/IEC 13818-7 LowComplexity Profile
232    0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
233    0x69 Audio ISO/IEC 13818-3
234    0x6A Visual ISO/IEC 11172-2
235    0x6B Audio ISO/IEC 11172-3
236    0x6C Visual ISO/IEC 10918-1
237    0x6D reserved for registration authority i
238    0x6E Visual ISO/IEC 15444-1
239    0x6F - 0x9F reserved for ISO use
240    0xA0 - 0xBF reserved for registration authority i
241    0xC0 - 0xE0 user private
242    0xE1 reserved for registration authority i
243    0xE2 - 0xFE user private
244    0xFF no object type specified h
245    */
246    /* streamType values
247      0x00 Forbidden
248    0x01 ObjectDescriptorStream (see 7.2.5)
249    0x02 ClockReferenceStream (see 7.3.2.5)
250    0x03 SceneDescriptionStream (see ISO/IEC 14496-11)
251    0x04 VisualStream
252    0x05 AudioStream
253    0x06 MPEG7Stream
254    0x07 IPMPStream (see 7.2.3.2)
255    0x08 ObjectContentInfoStream (see 7.2.4.2)
256    0x09 MPEGJStream
257    0x0A Interaction Stream
258    0x0B IPMPToolStream (see [ISO/IEC 14496-13])
259    0x0C - 0x1F reserved for ISO use
260    0x20 - 0x3F user private
261    */
262}
263