package com.googlecode.mp4parser.authoring.tracks; import com.coremedia.iso.IsoBufferWrapper; import com.coremedia.iso.IsoBufferWrapperImpl; import com.coremedia.iso.IsoFile; import com.coremedia.iso.boxes.CompositionTimeToSample; import com.coremedia.iso.boxes.SampleDependencyTypeBox; import com.coremedia.iso.boxes.SampleDescriptionBox; import com.coremedia.iso.boxes.TimeToSampleBox; import com.coremedia.iso.boxes.sampleentry.TextSampleEntry; import com.googlecode.mp4parser.authoring.AbstractTrack; import com.googlecode.mp4parser.authoring.TrackMetaData; import com.googlecode.mp4parser.boxes.threegpp26245.FontTableBox; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Collections; import java.util.Date; import java.util.LinkedList; import java.util.List; /** * */ public class TextTrackImpl extends AbstractTrack { TrackMetaData trackMetaData = new TrackMetaData(); SampleDescriptionBox sampleDescriptionBox; List<Line> subs = new LinkedList<Line>(); public List<Line> getSubs() { return subs; } public TextTrackImpl() { sampleDescriptionBox = new SampleDescriptionBox(); TextSampleEntry tx3g = new TextSampleEntry(IsoFile.fourCCtoBytes("tx3g")); tx3g.setStyleRecord(new TextSampleEntry.StyleRecord()); tx3g.setBoxRecord(new TextSampleEntry.BoxRecord()); sampleDescriptionBox.addBox(tx3g); FontTableBox ftab = new FontTableBox(); ftab.setEntries(Collections.singletonList(new FontTableBox.FontRecord(1, "Serif"))); tx3g.addBox(ftab); trackMetaData.setCreationTime(new Date()); trackMetaData.setModificationTime(new Date()); trackMetaData.setTimescale(1000); // Text tracks use millieseconds } public List<IsoBufferWrapper> getSamples() { List<IsoBufferWrapper> samples = new LinkedList<IsoBufferWrapper>(); long lastEnd = 0; for (Line sub : subs) { long silentTime = sub.from - lastEnd; if (silentTime > 0) { samples.add(new IsoBufferWrapperImpl(new byte[]{0, 0})); } else if (silentTime < 0) { throw new Error("Subtitle display times may not intersect"); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); try { dos.writeShort(sub.text.getBytes("UTF-8").length); dos.write(sub.text.getBytes("UTF-8")); dos.close(); } catch (IOException e) { throw new Error("VM is broken. Does not support UTF-8"); } samples.add(new IsoBufferWrapperImpl(baos.toByteArray())); lastEnd = sub.to; } return samples; } public SampleDescriptionBox getSampleDescriptionBox() { return sampleDescriptionBox; } public List<TimeToSampleBox.Entry> getDecodingTimeEntries() { List<TimeToSampleBox.Entry> stts = new LinkedList<TimeToSampleBox.Entry>(); long lastEnd = 0; for (Line sub : subs) { long silentTime = sub.from - lastEnd; if (silentTime > 0) { stts.add(new TimeToSampleBox.Entry(1, silentTime)); } else if (silentTime < 0) { throw new Error("Subtitle display times may not intersect"); } stts.add(new TimeToSampleBox.Entry(1, sub.to - sub.from)); lastEnd = sub.to; } return stts; } public List<CompositionTimeToSample.Entry> getCompositionTimeEntries() { return null; } public long[] getSyncSamples() { return null; } public List<SampleDependencyTypeBox.Entry> getSampleDependencies() { return null; } public TrackMetaData getTrackMetaData() { return trackMetaData; } public Type getType() { return Type.TEXT; } public static class Line { long from; long to; String text; public Line(long from, long to, String text) { this.from = from; this.to = to; this.text = text; } } }