aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/pixart/messenger/utils/video/MP4Builder.java')
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/MP4Builder.java445
1 files changed, 0 insertions, 445 deletions
diff --git a/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java b/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java
deleted file mode 100644
index ee8b83e27..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * This is the source code of Telegram for Android v. 1.7.x.
- * It is licensed under GNU GPL v. 2 or later.
- * You should have received a copy of the license in this archive (see LICENSE).
- *
- * Copyright Nikolai Kudashov, 2013-2014.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-
-import com.coremedia.iso.BoxParser;
-import com.coremedia.iso.IsoFile;
-import com.coremedia.iso.IsoTypeWriter;
-import com.coremedia.iso.boxes.Box;
-import com.coremedia.iso.boxes.Container;
-import com.coremedia.iso.boxes.DataEntryUrlBox;
-import com.coremedia.iso.boxes.DataInformationBox;
-import com.coremedia.iso.boxes.DataReferenceBox;
-import com.coremedia.iso.boxes.FileTypeBox;
-import com.coremedia.iso.boxes.HandlerBox;
-import com.coremedia.iso.boxes.MediaBox;
-import com.coremedia.iso.boxes.MediaHeaderBox;
-import com.coremedia.iso.boxes.MediaInformationBox;
-import com.coremedia.iso.boxes.MovieBox;
-import com.coremedia.iso.boxes.MovieHeaderBox;
-import com.coremedia.iso.boxes.SampleSizeBox;
-import com.coremedia.iso.boxes.SampleTableBox;
-import com.coremedia.iso.boxes.SampleToChunkBox;
-import com.coremedia.iso.boxes.StaticChunkOffsetBox;
-import com.coremedia.iso.boxes.SyncSampleBox;
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.coremedia.iso.boxes.TrackBox;
-import com.coremedia.iso.boxes.TrackHeaderBox;
-import com.googlecode.mp4parser.DataSource;
-import com.googlecode.mp4parser.util.Matrix;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-
-@TargetApi(16)
-public class MP4Builder {
-
- private InterleaveChunkMdat mdat = null;
- private Mp4Movie currentMp4Movie = null;
- private FileOutputStream fos = null;
- private FileChannel fc = null;
- private long dataOffset = 0;
- private long writedSinceLastMdat = 0;
- private boolean writeNewMdat = true;
- private HashMap<Track, long[]> track2SampleSizes = new HashMap<>();
- private ByteBuffer sizeBuffer = null;
-
- public MP4Builder createMovie(Mp4Movie mp4Movie) throws Exception {
- currentMp4Movie = mp4Movie;
-
- fos = new FileOutputStream(mp4Movie.getCacheFile());
- fc = fos.getChannel();
-
- FileTypeBox fileTypeBox = createFileTypeBox();
- fileTypeBox.getBox(fc);
- dataOffset += fileTypeBox.getSize();
- writedSinceLastMdat += dataOffset;
-
- mdat = new InterleaveChunkMdat();
-
- sizeBuffer = ByteBuffer.allocateDirect(4);
-
- return this;
- }
-
- private void flushCurrentMdat() throws Exception {
- long oldPosition = fc.position();
- fc.position(mdat.getOffset());
- mdat.getBox(fc);
- fc.position(oldPosition);
- mdat.setDataOffset(0);
- mdat.setContentSize(0);
- fos.flush();
- }
-
- public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo, boolean isAudio) throws Exception {
- if (writeNewMdat) {
- mdat.setContentSize(0);
- mdat.getBox(fc);
- mdat.setDataOffset(dataOffset);
- dataOffset += 16;
- writedSinceLastMdat += 16;
- writeNewMdat = false;
- }
-
- mdat.setContentSize(mdat.getContentSize() + bufferInfo.size);
- writedSinceLastMdat += bufferInfo.size;
-
- boolean flush = false;
- if (writedSinceLastMdat >= 32 * 1024) {
- flushCurrentMdat();
- writeNewMdat = true;
- flush = true;
- writedSinceLastMdat -= 32 * 1024;
- }
-
- currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo);
- byteBuf.position(bufferInfo.offset + (isAudio ? 0 : 4));
- byteBuf.limit(bufferInfo.offset + bufferInfo.size);
-
- if (!isAudio) {
- sizeBuffer.position(0);
- sizeBuffer.putInt(bufferInfo.size - 4);
- sizeBuffer.position(0);
- fc.write(sizeBuffer);
- }
-
- fc.write(byteBuf);
- dataOffset += bufferInfo.size;
-
- if (flush) {
- fos.flush();
- }
- return flush;
- }
-
- public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception {
- return currentMp4Movie.addTrack(mediaFormat, isAudio);
- }
-
- public void finishMovie(boolean error) throws Exception {
- if (mdat.getContentSize() != 0) {
- flushCurrentMdat();
- }
-
- for (Track track : currentMp4Movie.getTracks()) {
- List<Sample> samples = track.getSamples();
- long[] sizes = new long[samples.size()];
- for (int i = 0; i < sizes.length; i++) {
- sizes[i] = samples.get(i).getSize();
- }
- track2SampleSizes.put(track, sizes);
- }
-
- Box moov = createMovieBox(currentMp4Movie);
- moov.getBox(fc);
- fos.flush();
-
- fc.close();
- fos.close();
- }
-
- protected FileTypeBox createFileTypeBox() {
- LinkedList<String> minorBrands = new LinkedList<>();
- minorBrands.add("isom");
- minorBrands.add("3gp4");
- return new FileTypeBox("isom", 0, minorBrands);
- }
-
- private class InterleaveChunkMdat implements Box {
- private Container parent;
- private long contentSize = 1024 * 1024 * 1024;
- private long dataOffset = 0;
-
- public Container getParent() {
- return parent;
- }
-
- public long getOffset() {
- return dataOffset;
- }
-
- public void setDataOffset(long offset) {
- dataOffset = offset;
- }
-
- public void setParent(Container parent) {
- this.parent = parent;
- }
-
- public void setContentSize(long contentSize) {
- this.contentSize = contentSize;
- }
-
- public long getContentSize() {
- return contentSize;
- }
-
- public String getType() {
- return "mdat";
- }
-
- public long getSize() {
- return 16 + contentSize;
- }
-
- private boolean isSmallBox(long contentSize) {
- return (contentSize + 8) < 4294967296L;
- }
-
- @Override
- public void parse(DataSource dataSource, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
-
- }
-
- public void getBox(WritableByteChannel writableByteChannel) throws IOException {
- ByteBuffer bb = ByteBuffer.allocate(16);
- long size = getSize();
- if (isSmallBox(size)) {
- IsoTypeWriter.writeUInt32(bb, size);
- } else {
- IsoTypeWriter.writeUInt32(bb, 1);
- }
- bb.put(IsoFile.fourCCtoBytes("mdat"));
- if (isSmallBox(size)) {
- bb.put(new byte[8]);
- } else {
- IsoTypeWriter.writeUInt64(bb, size);
- }
- bb.rewind();
- writableByteChannel.write(bb);
- }
- }
-
- public static long gcd(long a, long b) {
- if (b == 0) {
- return a;
- }
- return gcd(b, a % b);
- }
-
- public long getTimescale(Mp4Movie mp4Movie) {
- long timescale = 0;
- if (!mp4Movie.getTracks().isEmpty()) {
- timescale = mp4Movie.getTracks().iterator().next().getTimeScale();
- }
- for (Track track : mp4Movie.getTracks()) {
- timescale = gcd(track.getTimeScale(), timescale);
- }
- return timescale;
- }
-
- protected MovieBox createMovieBox(Mp4Movie movie) {
- MovieBox movieBox = new MovieBox();
- MovieHeaderBox mvhd = new MovieHeaderBox();
-
- mvhd.setCreationTime(new Date());
- mvhd.setModificationTime(new Date());
- mvhd.setMatrix(Matrix.ROTATE_0);
- long movieTimeScale = getTimescale(movie);
- long duration = 0;
-
- for (Track track : movie.getTracks()) {
- long tracksDuration = track.getDuration() * movieTimeScale / track.getTimeScale();
- if (tracksDuration > duration) {
- duration = tracksDuration;
- }
- }
-
- mvhd.setDuration(duration);
- mvhd.setTimescale(movieTimeScale);
- mvhd.setNextTrackId(movie.getTracks().size() + 1);
-
- movieBox.addBox(mvhd);
- for (Track track : movie.getTracks()) {
- movieBox.addBox(createTrackBox(track, movie));
- }
- return movieBox;
- }
-
- protected TrackBox createTrackBox(Track track, Mp4Movie movie) {
- TrackBox trackBox = new TrackBox();
- TrackHeaderBox tkhd = new TrackHeaderBox();
-
- tkhd.setEnabled(true);
- tkhd.setInMovie(true);
- tkhd.setInPreview(true);
- if (track.isAudio()) {
- tkhd.setMatrix(Matrix.ROTATE_0);
- } else {
- tkhd.setMatrix(movie.getMatrix());
- }
- tkhd.setAlternateGroup(0);
- tkhd.setCreationTime(track.getCreationTime());
- tkhd.setDuration(track.getDuration() * getTimescale(movie) / track.getTimeScale());
- tkhd.setHeight(track.getHeight());
- tkhd.setWidth(track.getWidth());
- tkhd.setLayer(0);
- tkhd.setModificationTime(new Date());
- tkhd.setTrackId(track.getTrackId() + 1);
- tkhd.setVolume(track.getVolume());
-
- trackBox.addBox(tkhd);
-
- MediaBox mdia = new MediaBox();
- trackBox.addBox(mdia);
- MediaHeaderBox mdhd = new MediaHeaderBox();
- mdhd.setCreationTime(track.getCreationTime());
- mdhd.setDuration(track.getDuration());
- mdhd.setTimescale(track.getTimeScale());
- mdhd.setLanguage("eng");
- mdia.addBox(mdhd);
- HandlerBox hdlr = new HandlerBox();
- hdlr.setName(track.isAudio() ? "SoundHandle" : "VideoHandle");
- hdlr.setHandlerType(track.getHandler());
-
- mdia.addBox(hdlr);
-
- MediaInformationBox minf = new MediaInformationBox();
- minf.addBox(track.getMediaHeaderBox());
-
- DataInformationBox dinf = new DataInformationBox();
- DataReferenceBox dref = new DataReferenceBox();
- dinf.addBox(dref);
- DataEntryUrlBox url = new DataEntryUrlBox();
- url.setFlags(1);
- dref.addBox(url);
- minf.addBox(dinf);
-
- Box stbl = createStbl(track);
- minf.addBox(stbl);
- mdia.addBox(minf);
-
- return trackBox;
- }
-
- protected Box createStbl(Track track) {
- SampleTableBox stbl = new SampleTableBox();
-
- createStsd(track, stbl);
- createStts(track, stbl);
- createStss(track, stbl);
- createStsc(track, stbl);
- createStsz(track, stbl);
- createStco(track, stbl);
-
- return stbl;
- }
-
- protected void createStsd(Track track, SampleTableBox stbl) {
- stbl.addBox(track.getSampleDescriptionBox());
- }
-
- protected void createStts(Track track, SampleTableBox stbl) {
- TimeToSampleBox.Entry lastEntry = null;
- List<TimeToSampleBox.Entry> entries = new ArrayList<>();
-
- for (long delta : track.getSampleDurations()) {
- if (lastEntry != null && lastEntry.getDelta() == delta) {
- lastEntry.setCount(lastEntry.getCount() + 1);
- } else {
- lastEntry = new TimeToSampleBox.Entry(1, delta);
- entries.add(lastEntry);
- }
- }
- TimeToSampleBox stts = new TimeToSampleBox();
- stts.setEntries(entries);
- stbl.addBox(stts);
- }
-
- protected void createStss(Track track, SampleTableBox stbl) {
- long[] syncSamples = track.getSyncSamples();
- if (syncSamples != null && syncSamples.length > 0) {
- SyncSampleBox stss = new SyncSampleBox();
- stss.setSampleNumber(syncSamples);
- stbl.addBox(stss);
- }
- }
-
- protected void createStsc(Track track, SampleTableBox stbl) {
- SampleToChunkBox stsc = new SampleToChunkBox();
- stsc.setEntries(new LinkedList<SampleToChunkBox.Entry>());
-
- long lastOffset = -1;
- int lastChunkNumber = 1;
- int lastSampleCount = 0;
-
- int previousWritedChunkCount = -1;
-
- int samplesCount = track.getSamples().size();
- for (int a = 0; a < samplesCount; a++) {
- Sample sample = track.getSamples().get(a);
- long offset = sample.getOffset();
- long size = sample.getSize();
-
- lastOffset = offset + size;
- lastSampleCount++;
-
- boolean write = false;
- if (a != samplesCount - 1) {
- Sample nextSample = track.getSamples().get(a + 1);
- if (lastOffset != nextSample.getOffset()) {
- write = true;
- }
- } else {
- write = true;
- }
- if (write) {
- if (previousWritedChunkCount != lastSampleCount) {
- stsc.getEntries().add(new SampleToChunkBox.Entry(lastChunkNumber, lastSampleCount, 1));
- previousWritedChunkCount = lastSampleCount;
- }
- lastSampleCount = 0;
- lastChunkNumber++;
- }
- }
- stbl.addBox(stsc);
- }
-
- protected void createStsz(Track track, SampleTableBox stbl) {
- SampleSizeBox stsz = new SampleSizeBox();
- stsz.setSampleSizes(track2SampleSizes.get(track));
- stbl.addBox(stsz);
- }
-
- protected void createStco(Track track, SampleTableBox stbl) {
- ArrayList<Long> chunksOffsets = new ArrayList<>();
- long lastOffset = -1;
- for (Sample sample : track.getSamples()) {
- long offset = sample.getOffset();
- if (lastOffset != -1 && lastOffset != offset) {
- lastOffset = -1;
- }
- if (lastOffset == -1) {
- chunksOffsets.add(offset);
- }
- lastOffset = offset + sample.getSize();
- }
- long[] chunkOffsetsLong = new long[chunksOffsets.size()];
- for (int a = 0; a < chunksOffsets.size(); a++) {
- chunkOffsetsLong[a] = chunksOffsets.get(a);
- }
-
- StaticChunkOffsetBox stco = new StaticChunkOffsetBox();
- stco.setChunkOffsets(chunkOffsetsLong);
- stbl.addBox(stco);
- }
-}