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