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