示例#1
0
 @Override
 public long getSize() {
   parseDetails();
   long size = 0;
   for (Box box : boxes) {
     size += box.getSize();
   }
   return size;
 }
示例#2
0
  public void getBox(WritableByteChannel os) throws IOException {
    parseDetails();
    for (Box box : boxes) {

      if (os instanceof FileChannel) {
        long startPos = ((FileChannel) os).position();
        box.getBox(os);
        long size = ((FileChannel) os).position() - startPos;
        assert size == box.getSize();
      } else {
        box.getBox(os);
      }
    }
  }
示例#3
0
 public long getDataOffset() {
   Object b = this;
   long offset = 16;
   while (b instanceof Box) {
     for (Box box : ((Box) b).getParent().getBoxes()) {
       if (b == box) {
         break;
       }
       offset += box.getSize();
     }
     b = ((Box) b).getParent();
   }
   return offset;
 }
 public long getDataOffset() {
   Box b = this;
   long offset = 16;
   while (b.getParent() != null) {
     for (Box box : b.getParent().getBoxes()) {
       if (b == box) {
         break;
       }
       offset += box.getSize();
     }
     b = b.getParent();
   }
   return offset;
 }
示例#5
0
  /** {@inheritDoc} */
  public Container build(Movie movie) {
    if (fragmenter == null) {
      fragmenter = new TimeBasedFragmenter(2);
    }
    LOG.fine("Creating movie " + movie);
    for (Track track : movie.getTracks()) {
      // getting the samples may be a time consuming activity
      List<Sample> samples = track.getSamples();
      putSamples(track, samples);
      long[] sizes = new long[samples.size()];
      for (int i = 0; i < sizes.length; i++) {
        Sample b = samples.get(i);
        sizes[i] = b.getSize();
      }
      track2SampleSizes.put(track, sizes);
    }

    BasicContainer isoFile = new BasicContainer();

    isoFile.addBox(createFileTypeBox(movie));

    Map<Track, int[]> chunks = new HashMap<Track, int[]>();
    for (Track track : movie.getTracks()) {
      chunks.put(track, getChunkSizes(track));
    }
    Box moov = createMovieBox(movie, chunks);
    isoFile.addBox(moov);
    List<SampleSizeBox> stszs = Path.getPaths(moov, "trak/mdia/minf/stbl/stsz");

    long contentSize = 0;
    for (SampleSizeBox stsz : stszs) {
      contentSize += sum(stsz.getSampleSizes());
    }

    InterleaveChunkMdat mdat = new InterleaveChunkMdat(movie, chunks, contentSize);
    isoFile.addBox(mdat);

    /*
    dataOffset is where the first sample starts. In this special mdat the samples always start
    at offset 16 so that we can use the same offset for large boxes and small boxes
     */
    long dataOffset = mdat.getDataOffset();
    for (StaticChunkOffsetBox chunkOffsetBox : chunkOffsetBoxes.values()) {
      long[] offsets = chunkOffsetBox.getChunkOffsets();
      for (int i = 0; i < offsets.length; i++) {
        offsets[i] += dataOffset;
      }
    }
    for (SampleAuxiliaryInformationOffsetsBox saio : sampleAuxiliaryInformationOffsetsBoxes) {
      long offset =
          saio.getSize(); // the calculation is systematically wrong by 4, I don't want to debug
      // why. Just a quick correction --san 14.May.13
      offset += 4 + 4 + 4 + 4 + 4 + 24;
      // size of all header we were missing otherwise (moov, trak, mdia, minf, stbl)
      Object b = saio;
      do {
        Object current = b;
        b = ((Box) b).getParent();

        for (Box box : ((Container) b).getBoxes()) {
          if (box == current) {
            break;
          }
          offset += box.getSize();
        }

      } while (b instanceof Box);

      long[] saioOffsets = saio.getOffsets();
      for (int i = 0; i < saioOffsets.length; i++) {
        saioOffsets[i] = saioOffsets[i] + offset;
      }
      saio.setOffsets(saioOffsets);
    }

    return isoFile;
  }
示例#6
0
  public SampleList(TrackBox trackBox) {
    this.isoFile = trackBox.getIsoFile(); // where are we?
    offsets2Sizes = new HashMap<Long, Long>();

    // find all mdats first to be able to use them later with explicitly looking them up
    long currentOffset = 0;
    for (Box b : isoFile.getBoxes()) {
      long currentSize = b.getSize();
      if ("mdat".equals(b.getType())) {
        if (b instanceof MediaDataBox) {
          long contentOffset = currentOffset + ((MediaDataBox) b).getHeader().limit();
          mdatStartCache.put((MediaDataBox) b, contentOffset);
          mdatEndCache.put((MediaDataBox) b, contentOffset + currentSize);
          mdats.add((MediaDataBox) b);
        } else {
          throw new RuntimeException(
              "Sample need to be in mdats and mdats need to be instanceof MediaDataBox");
        }
      }
      currentOffset += currentSize;
    }

    // first we get all sample from the 'normal' MP4 part.
    // if there are none - no problem.

    SampleSizeBox sampleSizeBox = trackBox.getSampleTableBox().getSampleSizeBox();
    ChunkOffsetBox chunkOffsetBox = trackBox.getSampleTableBox().getChunkOffsetBox();
    SampleToChunkBox sampleToChunkBox = trackBox.getSampleTableBox().getSampleToChunkBox();

    if (sampleToChunkBox != null
        && sampleToChunkBox.getEntries().size() > 0
        && chunkOffsetBox != null
        && chunkOffsetBox.getChunkOffsets().length > 0
        && sampleSizeBox != null
        && sampleSizeBox.getSampleCount() > 0) {
      long[] numberOfSamplesInChunk =
          sampleToChunkBox.blowup(chunkOffsetBox.getChunkOffsets().length);
      if (sampleSizeBox.getSampleSize() > 0) {
        // Every sample has the same size!
        // no need to store each size separately
        // this happens when people use raw audio formats in MP4 (are you stupid guys???)
        offsets2Sizes = new DummyMap<Long, Long>(sampleSizeBox.getSampleSize());
        long sampleSize = sampleSizeBox.getSampleSize();
        for (int i = 0; i < numberOfSamplesInChunk.length; i++) {
          long thisChunksNumberOfSamples = numberOfSamplesInChunk[i];
          long sampleOffset = chunkOffsetBox.getChunkOffsets()[i];
          for (int j = 0; j < thisChunksNumberOfSamples; j++) {
            offsets2Sizes.put(sampleOffset, sampleSize);
            sampleOffset += sampleSize;
          }
        }
      } else {
        // the normal case where all samples have different sizes
        int sampleIndex = 0;
        long sampleSizes[] = sampleSizeBox.getSampleSizes();
        for (int i = 0; i < numberOfSamplesInChunk.length; i++) {
          long thisChunksNumberOfSamples = numberOfSamplesInChunk[i];
          long sampleOffset = chunkOffsetBox.getChunkOffsets()[i];
          for (int j = 0; j < thisChunksNumberOfSamples; j++) {
            long sampleSize = sampleSizes[sampleIndex];
            offsets2Sizes.put(sampleOffset, sampleSize);
            sampleOffset += sampleSize;
            sampleIndex++;
          }
        }
      }
    }

    // Next we add all samples from the fragments
    // in most cases - I've never seen it different it's either normal or fragmented.

    List<MovieExtendsBox> movieExtendsBoxes = trackBox.getParent().getBoxes(MovieExtendsBox.class);

    if (movieExtendsBoxes.size() > 0) {
      List<TrackExtendsBox> trackExtendsBoxes =
          movieExtendsBoxes.get(0).getBoxes(TrackExtendsBox.class);
      for (TrackExtendsBox trackExtendsBox : trackExtendsBoxes) {
        if (trackExtendsBox.getTrackId() == trackBox.getTrackHeaderBox().getTrackId()) {
          for (MovieFragmentBox movieFragmentBox :
              trackBox.getIsoFile().getBoxes(MovieFragmentBox.class)) {
            offsets2Sizes.putAll(
                getOffsets(movieFragmentBox, trackBox.getTrackHeaderBox().getTrackId()));
          }
        }
      }
    }

    // We have now a map from all sample offsets to their sizes
  }