1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.googlecode.mp4parser.boxes.piff;
2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoFile;
4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeReader;
5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.coremedia.iso.IsoTypeWriter;
6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.googlecode.mp4parser.util.Path;
7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.FileInputStream;
9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.FileNotFoundException;
10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.IOException;
11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.UnsupportedEncodingException;
12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.nio.ByteBuffer;
13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayList;
14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Collections;
15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.List;
16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/**
18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.7. ASF GUIDs
19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * ASF_Protection_System_Identifier_Object
22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 9A04F079-9840-4286-AB92E65BE0885F95
23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * ASF_Content_Protection_System_Microsoft_PlayReady
25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * F4637010-03C3-42CD-B932B48ADF3A6A54
26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * ASF_StreamType_PlayReady_Encrypted_Command_Media
28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * 8683973A-6639-463A-ABD764F1CE3EEAE0
29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Specifications > Microsoft PlayReady Format Specification > 2. PlayReady Media Format > 2.5. Data Objects > 2.5.1. Payload Extension for AES in Counter Mode
32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
33dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The sample Id is used as the IV in CTR mode. Block offset, starting at 0 and incremented by 1 after every 16 bytes, from the beginning of the sample is used as the Counter.
34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The sample ID for each sample (media object) is stored as an ASF payload extension system with the ID of ASF_Payload_Extension_Encryption_SampleID = {6698B84E-0AFA-4330-AEB2-1C0A98D7A44D}. The payload extension can be stored as a fixed size extension of 8 bytes.
36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * The sample ID is always stored in big-endian byte order.
38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */
39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupublic class PlayReadyHeader extends ProtectionSpecificHeader {
40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private long length;
41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private List<PlayReadyRecord> records;
42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public PlayReadyHeader() {
44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    @Override
48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void parse(ByteBuffer byteBuffer) {
49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        /*
50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu   Length DWORD 32
51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu   PlayReady Record Count WORD 16
53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu   PlayReady Records See Text Varies
55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        */
57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        length = IsoTypeReader.readUInt32BE(byteBuffer);
59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        int recordCount = IsoTypeReader.readUInt16BE(byteBuffer);
60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        records = PlayReadyRecord.createFor(byteBuffer, recordCount);
62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    @Override
65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public ByteBuffer getData() {
66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        int size = 4 + 2;
68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        for (PlayReadyRecord record : records) {
69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            size += 2 + 2;
70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            size += record.getValue().rewind().limit();
71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        ByteBuffer byteBuffer = ByteBuffer.allocate(size);
73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        IsoTypeWriter.writeUInt32BE(byteBuffer, size);
75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        IsoTypeWriter.writeUInt16BE(byteBuffer, records.size());
76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        for (PlayReadyRecord record : records) {
77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            IsoTypeWriter.writeUInt16BE(byteBuffer, record.type);
78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            IsoTypeWriter.writeUInt16BE(byteBuffer, record.getValue().limit());
79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            ByteBuffer tmp4debug = record.getValue();
80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            byteBuffer.put(tmp4debug);
81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
83dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return byteBuffer;
84dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
85dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
86dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public void setRecords(List<PlayReadyRecord> records) {
87dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        this.records = records;
88dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
89dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
90dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public List<PlayReadyRecord> getRecords() {
91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return Collections.unmodifiableList(records);
92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    @Override
95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public String toString() {
96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        final StringBuilder sb = new StringBuilder();
97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append("PlayReadyHeader");
98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append("{length=").append(length);
99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", recordCount=").append(records.size());
100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append(", records=").append(records);
101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        sb.append('}');
102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        return sb.toString();
103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    public static abstract class PlayReadyRecord {
106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        int type;
107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public PlayReadyRecord(int type) {
110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            this.type = type;
111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public static List<PlayReadyRecord> createFor(ByteBuffer byteBuffer, int recordCount) {
114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            List<PlayReadyRecord> records = new ArrayList<PlayReadyRecord>(recordCount);
115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            for (int i = 0; i < recordCount; i++) {
117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                PlayReadyRecord record;
118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                int type = IsoTypeReader.readUInt16BE(byteBuffer);
119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                int length = IsoTypeReader.readUInt16BE(byteBuffer);
120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                switch (type) {
121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    case 0x1:
122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        record = new RMHeader();
123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        break;
124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    case 0x2:
125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        record = new DefaulPlayReadyRecord(0x02);
126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        break;
127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    case 0x3:
128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        record = new EmeddedLicenseStore();
129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        break;
130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    default:
131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                        record = new DefaulPlayReadyRecord(type);
132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                }
133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                record.parse((ByteBuffer) byteBuffer.slice().limit(length));
134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                byteBuffer.position(byteBuffer.position() + length);
135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                records.add(record);
136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return records;
139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
140dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
141dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public abstract void parse(ByteBuffer bytes);
142dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
143dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        @Override
144dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public String toString() {
145dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            final StringBuilder sb = new StringBuilder();
146dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            sb.append("PlayReadyRecord");
147dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            sb.append("{type=").append(type);
148dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            sb.append(", length=").append(getValue().limit());
149dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu//            sb.append(", value=").append(Hex.encodeHex(getValue())).append('\'');
150dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            sb.append('}');
151dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            return sb.toString();
152dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
153dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
154dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public abstract ByteBuffer getValue();
155dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
156dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public static class RMHeader extends PlayReadyRecord {
157dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            String header;
158dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
159dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public RMHeader() {
160dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                super(0x01);
161dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
162dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
163dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
164dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public void parse(ByteBuffer bytes) {
165dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                try {
166dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    byte[] str = new byte[bytes.slice().limit()];
167dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    bytes.get(str);
168dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    header = new String(str, "UTF-16LE");
169dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                } catch (UnsupportedEncodingException e) {
170dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    throw new RuntimeException(e);
171dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                }
172dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
173dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
174dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
175dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public ByteBuffer getValue() {
176dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                byte[] headerBytes;
177dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                try {
178dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    headerBytes = header.getBytes("UTF-16LE");
179dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                } catch (UnsupportedEncodingException e) {
180dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                    throw new RuntimeException(e);
181dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                }
182dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return ByteBuffer.wrap(headerBytes);
183dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
184dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
185dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public void setHeader(String header) {
186dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                this.header = header;
187dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
188dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
189dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public String getHeader() {
190dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return header;
191dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
192dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
193dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
194dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public String toString() {
195dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                final StringBuilder sb = new StringBuilder();
196dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append("RMHeader");
197dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append("{length=").append(getValue().limit());
198dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append(", header='").append(header).append('\'');
199dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append('}');
200dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return sb.toString();
201dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
202dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
203dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
204dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public static class EmeddedLicenseStore extends PlayReadyRecord {
205dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            ByteBuffer value;
206dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
207dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public EmeddedLicenseStore() {
208dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                super(0x03);
209dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
210dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
211dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
212dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public void parse(ByteBuffer bytes) {
213dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                this.value = bytes.duplicate();
214dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
215dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
216dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
217dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public ByteBuffer getValue() {
218dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return value;
219dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
220dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
221dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
222dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public String toString() {
223dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                final StringBuilder sb = new StringBuilder();
224dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append("EmeddedLicenseStore");
225dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append("{length=").append(getValue().limit());
226dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                //sb.append(", value='").append(Hex.encodeHex(getValue())).append('\'');
227dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                sb.append('}');
228dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return sb.toString();
229dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
230dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
231dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
232dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        public static class DefaulPlayReadyRecord extends PlayReadyRecord {
233dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            ByteBuffer value;
234dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
235dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public DefaulPlayReadyRecord(int type) {
236dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                super(type);
237dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
238dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
239dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
240dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public void parse(ByteBuffer bytes) {
241dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                this.value = bytes.duplicate();
242dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
243dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
244dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            @Override
245dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            public ByteBuffer getValue() {
246dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu                return value;
247dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            }
248dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
249dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu        }
250dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
251dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    }
252dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
253dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu}
254