1/*
2 * Copyright 2012 Sebastian Annies, Hamburg
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 */
16package com.googlecode.mp4parser.authoring.tracks;
17
18import com.coremedia.iso.boxes.*;
19import com.coremedia.iso.boxes.sampleentry.TextSampleEntry;
20import com.googlecode.mp4parser.authoring.AbstractTrack;
21import com.googlecode.mp4parser.authoring.TrackMetaData;
22import com.googlecode.mp4parser.boxes.threegpp26245.FontTableBox;
23
24import java.io.ByteArrayOutputStream;
25import java.io.DataOutputStream;
26import java.io.IOException;
27import java.nio.ByteBuffer;
28import java.util.Collections;
29import java.util.Date;
30import java.util.LinkedList;
31import java.util.List;
32
33/**
34 *
35 */
36public class TextTrackImpl extends AbstractTrack {
37    TrackMetaData trackMetaData = new TrackMetaData();
38    SampleDescriptionBox sampleDescriptionBox;
39    List<Line> subs = new LinkedList<Line>();
40
41    public List<Line> getSubs() {
42        return subs;
43    }
44
45    public TextTrackImpl() {
46        sampleDescriptionBox = new SampleDescriptionBox();
47        TextSampleEntry tx3g = new TextSampleEntry("tx3g");
48        tx3g.setDataReferenceIndex(1);
49        tx3g.setStyleRecord(new TextSampleEntry.StyleRecord());
50        tx3g.setBoxRecord(new TextSampleEntry.BoxRecord());
51        sampleDescriptionBox.addBox(tx3g);
52
53        FontTableBox ftab = new FontTableBox();
54        ftab.setEntries(Collections.singletonList(new FontTableBox.FontRecord(1, "Serif")));
55
56        tx3g.addBox(ftab);
57
58
59        trackMetaData.setCreationTime(new Date());
60        trackMetaData.setModificationTime(new Date());
61        trackMetaData.setTimescale(1000); // Text tracks use millieseconds
62
63
64    }
65
66
67    public List<ByteBuffer> getSamples() {
68        List<ByteBuffer> samples = new LinkedList<ByteBuffer>();
69        long lastEnd = 0;
70        for (Line sub : subs) {
71            long silentTime = sub.from - lastEnd;
72            if (silentTime > 0) {
73                samples.add(ByteBuffer.wrap(new byte[]{0, 0}));
74            } else if (silentTime < 0) {
75                throw new Error("Subtitle display times may not intersect");
76            }
77            ByteArrayOutputStream baos = new ByteArrayOutputStream();
78            DataOutputStream dos = new DataOutputStream(baos);
79            try {
80                dos.writeShort(sub.text.getBytes("UTF-8").length);
81                dos.write(sub.text.getBytes("UTF-8"));
82                dos.close();
83            } catch (IOException e) {
84                throw new Error("VM is broken. Does not support UTF-8");
85            }
86            samples.add(ByteBuffer.wrap(baos.toByteArray()));
87            lastEnd = sub.to;
88        }
89        return samples;
90    }
91
92    public SampleDescriptionBox getSampleDescriptionBox() {
93        return sampleDescriptionBox;
94    }
95
96    public List<TimeToSampleBox.Entry> getDecodingTimeEntries() {
97        List<TimeToSampleBox.Entry> stts = new LinkedList<TimeToSampleBox.Entry>();
98        long lastEnd = 0;
99        for (Line sub : subs) {
100            long silentTime = sub.from - lastEnd;
101            if (silentTime > 0) {
102                stts.add(new TimeToSampleBox.Entry(1, silentTime));
103            } else if (silentTime < 0) {
104                throw new Error("Subtitle display times may not intersect");
105            }
106            stts.add(new TimeToSampleBox.Entry(1, sub.to - sub.from));
107            lastEnd = sub.to;
108        }
109        return stts;
110    }
111
112    public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() {
113        return null;
114    }
115
116    public long[] getSyncSamples() {
117        return null;
118    }
119
120    public List<SampleDependencyTypeBox.Entry> getSampleDependencies() {
121        return null;
122    }
123
124    public TrackMetaData getTrackMetaData() {
125        return trackMetaData;
126    }
127
128    public String getHandler() {
129        return "sbtl";
130    }
131
132
133    public static class Line {
134        long from;
135        long to;
136        String text;
137
138
139        public Line(long from, long to, String text) {
140            this.from = from;
141            this.to = to;
142            this.text = text;
143        }
144
145        public long getFrom() {
146            return from;
147        }
148
149        public String getText() {
150            return text;
151        }
152
153        public long getTo() {
154            return to;
155        }
156    }
157
158    public AbstractMediaHeaderBox getMediaHeaderBox() {
159        return new NullMediaHeaderBox();
160    }
161
162    public SubSampleInformationBox getSubsampleInformationBox() {
163        return null;
164    }
165}
166