Home | History | Annotate | Download | only in tracks
      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  */
     16 package com.googlecode.mp4parser.authoring.tracks;
     17 
     18 import com.coremedia.iso.boxes.*;
     19 import com.coremedia.iso.boxes.sampleentry.TextSampleEntry;
     20 import com.googlecode.mp4parser.authoring.AbstractTrack;
     21 import com.googlecode.mp4parser.authoring.TrackMetaData;
     22 import com.googlecode.mp4parser.boxes.apple.BaseMediaInfoAtom;
     23 import com.googlecode.mp4parser.boxes.apple.GenericMediaHeaderAtom;
     24 import com.googlecode.mp4parser.boxes.apple.GenericMediaHeaderTextAtom;
     25 import com.googlecode.mp4parser.boxes.apple.QuicktimeTextSampleEntry;
     26 import com.googlecode.mp4parser.boxes.threegpp26245.FontTableBox;
     27 
     28 import java.io.ByteArrayOutputStream;
     29 import java.io.DataOutputStream;
     30 import java.io.IOException;
     31 import java.nio.ByteBuffer;
     32 import java.util.Collections;
     33 import java.util.Date;
     34 import java.util.LinkedList;
     35 import java.util.List;
     36 
     37 /**
     38  * A Text track as Quicktime Pro would create.
     39  */
     40 public 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