From ae663440952fe0cffcfe4413b7268f045727454d Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Wed, 25 Jan 2017 21:22:15 +0100 Subject: reworked videocompression --- .../pixart/messenger/utils/video/InputSurface.java | 136 ----- .../pixart/messenger/utils/video/MP4Builder.java | 445 -------------- .../messenger/utils/video/MediaController.java | 649 --------------------- .../de/pixart/messenger/utils/video/Mp4Movie.java | 81 --- .../messenger/utils/video/OutputSurface.java | 207 ------- .../de/pixart/messenger/utils/video/Sample.java | 27 - .../messenger/utils/video/TextureRenderer.java | 213 ------- .../de/pixart/messenger/utils/video/Track.java | 263 --------- 8 files changed, 2021 deletions(-) delete mode 100644 src/main/java/de/pixart/messenger/utils/video/InputSurface.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/MP4Builder.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/MediaController.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/OutputSurface.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/Sample.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java delete mode 100644 src/main/java/de/pixart/messenger/utils/video/Track.java (limited to 'src/main/java/de/pixart/messenger/utils') diff --git a/src/main/java/de/pixart/messenger/utils/video/InputSurface.java b/src/main/java/de/pixart/messenger/utils/video/InputSurface.java deleted file mode 100644 index 3376b4b87..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/InputSurface.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package de.pixart.messenger.utils.video; - -import android.annotation.TargetApi; -import android.opengl.EGL14; -import android.opengl.EGLConfig; -import android.opengl.EGLContext; -import android.opengl.EGLDisplay; -import android.opengl.EGLExt; -import android.opengl.EGLSurface; -import android.os.Build; -import android.view.Surface; - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) -public class InputSurface { - private static final boolean VERBOSE = false; - private static final int EGL_RECORDABLE_ANDROID = 0x3142; - private static final int EGL_OPENGL_ES2_BIT = 4; - private EGLDisplay mEGLDisplay; - private EGLContext mEGLContext; - private EGLSurface mEGLSurface; - private Surface mSurface; - - public InputSurface(Surface surface) { - if (surface == null) { - throw new NullPointerException(); - } - mSurface = surface; - eglSetup(); - } - - private void eglSetup() { - mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); - if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) { - throw new RuntimeException("unable to get EGL14 display"); - } - int[] version = new int[2]; - if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) { - mEGLDisplay = null; - throw new RuntimeException("unable to initialize EGL14"); - } - - int[] attribList = { - EGL14.EGL_RED_SIZE, 8, - EGL14.EGL_GREEN_SIZE, 8, - EGL14.EGL_BLUE_SIZE, 8, - EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RECORDABLE_ANDROID, 1, - EGL14.EGL_NONE - }; - EGLConfig[] configs = new EGLConfig[1]; - int[] numConfigs = new int[1]; - if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length, - numConfigs, 0)) { - throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config"); - } - - int[] attrib_list = { - EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, - EGL14.EGL_NONE - }; - - mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0); - checkEglError("eglCreateContext"); - if (mEGLContext == null) { - throw new RuntimeException("null context"); - } - - int[] surfaceAttribs = { - EGL14.EGL_NONE - }; - mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface, - surfaceAttribs, 0); - checkEglError("eglCreateWindowSurface"); - if (mEGLSurface == null) { - throw new RuntimeException("surface was null"); - } - } - - public void release() { - if (EGL14.eglGetCurrentContext().equals(mEGLContext)) { - EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT); - } - EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface); - EGL14.eglDestroyContext(mEGLDisplay, mEGLContext); - mSurface.release(); - mEGLDisplay = null; - mEGLContext = null; - mEGLSurface = null; - mSurface = null; - } - - public void makeCurrent() { - if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) { - throw new RuntimeException("eglMakeCurrent failed"); - } - } - - public boolean swapBuffers() { - return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface); - } - - public Surface getSurface() { - return mSurface; - } - - public void setPresentationTime(long nsecs) { - EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs); - } - - private void checkEglError(String msg) { - boolean failed = false; - int error; - while ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) { - failed = true; - } - if (failed) { - throw new RuntimeException("EGL error encountered (see log)"); - } - } -} 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 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 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 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 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()); - - 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 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); - } -} diff --git a/src/main/java/de/pixart/messenger/utils/video/MediaController.java b/src/main/java/de/pixart/messenger/utils/video/MediaController.java deleted file mode 100644 index 2b47afade..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/MediaController.java +++ /dev/null @@ -1,649 +0,0 @@ -package de.pixart.messenger.utils.video; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.media.MediaCodec; -import android.media.MediaCodecInfo; -import android.media.MediaCodecList; -import android.media.MediaExtractor; -import android.media.MediaFormat; -import android.media.MediaMetadataRetriever; -import android.os.Build; -import android.util.Log; - -import java.io.File; -import java.nio.ByteBuffer; - -import de.pixart.messenger.Config; - -@SuppressLint("NewApi") -public class MediaController { - - public final static String MIME_TYPE = "video/avc"; - private final static int PROCESSOR_TYPE_OTHER = 0; - private final static int PROCESSOR_TYPE_QCOM = 1; - private final static int PROCESSOR_TYPE_INTEL = 2; - private final static int PROCESSOR_TYPE_MTK = 3; - private final static int PROCESSOR_TYPE_SEC = 4; - private final static int PROCESSOR_TYPE_TI = 5; - private static volatile MediaController Instance = null; - private boolean videoConvertFirstWrite = true; - private int resultHeight = 0; - private int resultWidth = 0; - - public static MediaController getInstance() { - MediaController localInstance = Instance; - if (localInstance == null) { - synchronized (MediaController.class) { - localInstance = Instance; - if (localInstance == null) { - Instance = localInstance = new MediaController(); - } - } - } - return localInstance; - } - - @SuppressLint("NewApi") - public static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) { - MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType); - int lastColorFormat = 0; - for (int i = 0; i < capabilities.colorFormats.length; i++) { - int colorFormat = capabilities.colorFormats[i]; - if (isRecognizedFormat(colorFormat)) { - lastColorFormat = colorFormat; - if (!(codecInfo.getName().equals("OMX.SEC.AVC.Encoder") && colorFormat == 19)) { - return colorFormat; - } - } - } - return lastColorFormat; - } - - private static boolean isRecognizedFormat(int colorFormat) { - switch (colorFormat) { - case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar: - case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar: - case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar: - case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar: - case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar: - return true; - default: - return false; - } - } - - public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap); - - private void didWriteData(final boolean last, final boolean error) { - final boolean firstWrite = videoConvertFirstWrite; - if (firstWrite) { - videoConvertFirstWrite = false; - } - } - - public static MediaCodecInfo selectCodec(String mimeType) { - int numCodecs = MediaCodecList.getCodecCount(); - MediaCodecInfo lastCodecInfo = null; - for (int i = 0; i < numCodecs; i++) { - MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); - if (!codecInfo.isEncoder()) { - continue; - } - String[] types = codecInfo.getSupportedTypes(); - for (String type : types) { - if (type.equalsIgnoreCase(mimeType)) { - lastCodecInfo = codecInfo; - if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) { - return lastCodecInfo; - } else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) { - return lastCodecInfo; - } - } - } - } - return lastCodecInfo; - } - - @TargetApi(16) - private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception { - int trackIndex = selectTrack(extractor, isAudio); - if (trackIndex >= 0) { - extractor.selectTrack(trackIndex); - MediaFormat trackFormat = extractor.getTrackFormat(trackIndex); - int muxerTrackIndex = mediaMuxer.addTrack(trackFormat, isAudio); - int maxBufferSize = trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); - boolean inputDone = false; - if (start > 0) { - extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); - } else { - extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); - } - ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize); - long startTime = -1; - - while (!inputDone) { - - boolean eof = false; - int index = extractor.getSampleTrackIndex(); - if (index == trackIndex) { - info.size = extractor.readSampleData(buffer, 0); - - if (info.size < 0) { - info.size = 0; - eof = true; - } else { - info.presentationTimeUs = extractor.getSampleTime(); - if (start > 0 && startTime == -1) { - startTime = info.presentationTimeUs; - } - if (end < 0 || info.presentationTimeUs < end) { - info.offset = 0; - info.flags = extractor.getSampleFlags(); - if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info, isAudio)) { - // didWriteData(messageObject, file, false, false); - } - extractor.advance(); - } else { - eof = true; - } - } - } else if (index == -1) { - eof = true; - } - if (eof) { - inputDone = true; - } - } - - extractor.unselectTrack(trackIndex); - return startTime; - } - return -1; - } - - @TargetApi(16) - private int selectTrack(MediaExtractor extractor, boolean audio) { - int numTracks = extractor.getTrackCount(); - for (int i = 0; i < numTracks; i++) { - MediaFormat format = extractor.getTrackFormat(i); - String mime = format.getString(MediaFormat.KEY_MIME); - if (audio) { - if (mime.startsWith("audio/")) { - return i; - } - } else { - if (mime.startsWith("video/")) { - return i; - } - } - } - return -5; - } - - @TargetApi(16) - public boolean convertVideo(final String path, final String compressed_path) { - - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(path); - String height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT); - String width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH); - String rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); - - int video_height = Integer.parseInt(height); - int video_width = Integer.parseInt(width); - - long startTime = -1; - long endTime = -1; - - int rotationValue = Integer.valueOf(rotation); - int originalWidth = Integer.valueOf(width); - int originalHeight = Integer.valueOf(height); - float ratio = (float) video_width / (float) video_height; // 16:9 = 1,7778, 4:3 = 1,3333 - - if (video_height > video_width) { - resultHeight = Config.VIDEO_SIZE; - resultWidth = Math.round(resultHeight * ratio); - } else if (video_width > video_height) { - resultWidth = Config.VIDEO_SIZE; - resultHeight = Math.round(resultWidth / ratio); - } - - if (resultHeight > originalHeight) { - resultHeight = originalHeight; - } - - if (resultWidth > originalWidth) { - resultWidth = originalWidth; - } - - Log.d(Config.LOGTAG, "Video dimensions: height: " + video_height + " width: " + video_width + " rotation: " + rotation + " ratio: " + ratio); - Log.d(Config.LOGTAG, "Video dimensions: Result height: " + resultHeight + " Result width: " + resultWidth + " rotation: " + rotation + " ratio: " + ratio); - - int bitrate = Config.VIDEO_BITRATE; - int rotateRender = 0; - - File cacheFile = new File(compressed_path); - - if (Build.VERSION.SDK_INT < 18 && resultHeight > resultWidth && resultWidth != originalWidth && resultHeight != originalHeight) { - int temp = resultHeight; - resultHeight = resultWidth; - resultWidth = temp; - rotationValue = 90; - rotateRender = 270; - } else if (Build.VERSION.SDK_INT > 20) { - if (rotationValue == 90) { - int temp = resultHeight; - resultHeight = resultWidth; - resultWidth = temp; - rotationValue = 0; - rotateRender = 270; - } else if (rotationValue == 180) { - rotateRender = 180; - rotationValue = 0; - } else if (rotationValue == 270) { - int temp = resultHeight; - resultHeight = resultWidth; - resultWidth = temp; - rotationValue = 0; - rotateRender = 90; - } - } - - - File inputFile = new File(path); - Log.d(Config.LOGTAG, "Input file is: " + inputFile.toString()); - if (!inputFile.canRead()) { - didWriteData(true, true); - Log.d(Config.LOGTAG, "Compression failed. Input file could not be read."); - return false; - } - - videoConvertFirstWrite = true; - boolean error = false; - long videoStartTime = startTime; - - long time = System.currentTimeMillis(); - - if (resultWidth != 0 && resultHeight != 0) { - MP4Builder mediaMuxer = null; - MediaExtractor extractor = null; - - try { - MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); - Mp4Movie movie = new Mp4Movie(); - movie.setCacheFile(cacheFile); - movie.setRotation(rotationValue); - movie.setSize(resultWidth, resultHeight); - mediaMuxer = new MP4Builder().createMovie(movie); - extractor = new MediaExtractor(); - extractor.setDataSource(inputFile.toString()); - - - if (resultWidth != originalWidth || resultHeight != originalHeight) { - int videoIndex; - videoIndex = selectTrack(extractor, false); - - if (videoIndex >= 0) { - MediaCodec decoder = null; - MediaCodec encoder = null; - InputSurface inputSurface = null; - OutputSurface outputSurface = null; - - try { - long videoTime = -1; - boolean outputDone = false; - boolean inputDone = false; - boolean decoderDone = false; - int swapUV = 0; - int videoTrackIndex = -5; - - int colorFormat; - int processorType = PROCESSOR_TYPE_OTHER; - String manufacturer = Build.MANUFACTURER.toLowerCase(); - if (Build.VERSION.SDK_INT < 18) { - MediaCodecInfo codecInfo = selectCodec(MIME_TYPE); - colorFormat = selectColorFormat(codecInfo, MIME_TYPE); - if (colorFormat == 0) { - throw new RuntimeException("no supported color format"); - } - String codecName = codecInfo.getName(); - if (codecName.contains("OMX.qcom.")) { - processorType = PROCESSOR_TYPE_QCOM; - if (Build.VERSION.SDK_INT == 16) { - if (manufacturer.equals("lge") || manufacturer.equals("nokia")) { - swapUV = 1; - } - } - } else if (codecName.contains("OMX.Intel.")) { - processorType = PROCESSOR_TYPE_INTEL; - } else if (codecName.equals("OMX.MTK.VIDEO.ENCODER.AVC")) { - processorType = PROCESSOR_TYPE_MTK; - } else if (codecName.equals("OMX.SEC.AVC.Encoder")) { - processorType = PROCESSOR_TYPE_SEC; - swapUV = 1; - } else if (codecName.equals("OMX.TI.DUCATI1.VIDEO.H264E")) { - processorType = PROCESSOR_TYPE_TI; - } - Log.d(Config.LOGTAG, "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer + "device = " + Build.MODEL); - } else { - colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface; - } - Log.d(Config.LOGTAG, "colorFormat = " + colorFormat); - - int resultHeightAligned = resultHeight; - int padding = 0; - int bufferSize = resultWidth * resultHeight * 3 / 2; - if (processorType == PROCESSOR_TYPE_OTHER) { - if (resultHeight % 16 != 0) { - resultHeightAligned += (16 - (resultHeight % 16)); - padding = resultWidth * (resultHeightAligned - resultHeight); - bufferSize += padding * 5 / 4; - } - } else if (processorType == PROCESSOR_TYPE_QCOM) { - if (!manufacturer.toLowerCase().equals("lge")) { - int uvoffset = (resultWidth * resultHeight + 2047) & ~2047; - padding = uvoffset - (resultWidth * resultHeight); - bufferSize += padding; - } - } else if (processorType == PROCESSOR_TYPE_TI) { - resultHeightAligned = 368; - bufferSize = resultWidth * resultHeightAligned * 3 / 2; - resultHeightAligned += (16 - (resultHeight % 16)); - padding = resultWidth * (resultHeightAligned - resultHeight); - bufferSize += padding * 5 / 4; - } else if (processorType == PROCESSOR_TYPE_MTK) { - if (manufacturer.equals("baidu")) { - resultHeightAligned += (16 - (resultHeight % 16)); - padding = resultWidth * (resultHeightAligned - resultHeight); - bufferSize += padding * 5 / 4; - } - } - - extractor.selectTrack(videoIndex); - if (startTime > 0) { - extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); - } else { - extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); - } - MediaFormat inputFormat = extractor.getTrackFormat(videoIndex); - - MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight); - outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); - outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate != 0 ? bitrate : 921600); - outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25); - outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); - if (Build.VERSION.SDK_INT < 18) { - outputFormat.setInteger("stride", resultWidth + 32); - outputFormat.setInteger("slice-height", resultHeight); - } - - encoder = MediaCodec.createEncoderByType(MIME_TYPE); - encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); - if (Build.VERSION.SDK_INT >= 18) { - inputSurface = new InputSurface(encoder.createInputSurface()); - inputSurface.makeCurrent(); - } - encoder.start(); - - decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME)); - if (Build.VERSION.SDK_INT >= 18) { - outputSurface = new OutputSurface(); - } else { - outputSurface = new OutputSurface(resultWidth, resultHeight, rotateRender); - } - decoder.configure(inputFormat, outputSurface.getSurface(), null, 0); - decoder.start(); - - final int TIMEOUT_USEC = 2500; - ByteBuffer[] decoderInputBuffers = null; - ByteBuffer[] encoderOutputBuffers = null; - ByteBuffer[] encoderInputBuffers = null; - if (Build.VERSION.SDK_INT < 21) { - decoderInputBuffers = decoder.getInputBuffers(); - encoderOutputBuffers = encoder.getOutputBuffers(); - if (Build.VERSION.SDK_INT < 18) { - encoderInputBuffers = encoder.getInputBuffers(); - } - } - - while (!outputDone) { - if (!inputDone) { - boolean eof = false; - int index = extractor.getSampleTrackIndex(); - if (index == videoIndex) { - int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufIndex >= 0) { - ByteBuffer inputBuf; - if (Build.VERSION.SDK_INT < 21) { - inputBuf = decoderInputBuffers[inputBufIndex]; - } else { - inputBuf = decoder.getInputBuffer(inputBufIndex); - } - int chunkSize = extractor.readSampleData(inputBuf, 0); - if (chunkSize < 0) { - decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - inputDone = true; - } else { - decoder.queueInputBuffer(inputBufIndex, 0, chunkSize, extractor.getSampleTime(), 0); - extractor.advance(); - } - } - } else if (index == -1) { - eof = true; - } - if (eof) { - int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufIndex >= 0) { - decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - inputDone = true; - } - } - } - - boolean decoderOutputAvailable = !decoderDone; - boolean encoderOutputAvailable = true; - while (decoderOutputAvailable || encoderOutputAvailable) { - int encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC); - if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { - encoderOutputAvailable = false; - } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { - if (Build.VERSION.SDK_INT < 21) { - encoderOutputBuffers = encoder.getOutputBuffers(); - } - } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { - MediaFormat newFormat = encoder.getOutputFormat(); - if (videoTrackIndex == -5) { - videoTrackIndex = mediaMuxer.addTrack(newFormat, false); - } - } else if (encoderStatus < 0) { - throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus); - } else { - ByteBuffer encodedData; - if (Build.VERSION.SDK_INT < 21) { - encodedData = encoderOutputBuffers[encoderStatus]; - } else { - encodedData = encoder.getOutputBuffer(encoderStatus); - } - if (encodedData == null) { - throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null"); - } - if (info.size > 1) { - if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) { - didWriteData(false, false); - } - } else if (videoTrackIndex == -5) { - byte[] csd = new byte[info.size]; - encodedData.limit(info.offset + info.size); - encodedData.position(info.offset); - encodedData.get(csd); - ByteBuffer sps = null; - ByteBuffer pps = null; - for (int a = info.size - 1; a >= 0; a--) { - if (a > 3) { - if (csd[a] == 1 && csd[a - 1] == 0 && csd[a - 2] == 0 && csd[a - 3] == 0) { - sps = ByteBuffer.allocate(a - 3); - pps = ByteBuffer.allocate(info.size - (a - 3)); - sps.put(csd, 0, a - 3).position(0); - pps.put(csd, a - 3, info.size - (a - 3)).position(0); - break; - } - } else { - break; - } - } - - MediaFormat newFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight); - if (sps != null && pps != null) { - newFormat.setByteBuffer("csd-0", sps); - newFormat.setByteBuffer("csd-1", pps); - } - videoTrackIndex = mediaMuxer.addTrack(newFormat, false); - } - } - outputDone = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0; - encoder.releaseOutputBuffer(encoderStatus, false); - } - if (encoderStatus != MediaCodec.INFO_TRY_AGAIN_LATER) { - continue; - } - - if (!decoderDone) { - int decoderStatus = decoder.dequeueOutputBuffer(info, TIMEOUT_USEC); - if (decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) { - decoderOutputAvailable = false; - } else if (decoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { - - } else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { - MediaFormat newFormat = decoder.getOutputFormat(); - Log.d(Config.LOGTAG, "newFormat = " + newFormat); - } else if (decoderStatus < 0) { - throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus); - } else { - boolean doRender; - if (Build.VERSION.SDK_INT >= 18) { - doRender = info.size != 0; - } else { - doRender = info.size != 0 || info.presentationTimeUs != 0; - } - if (endTime > 0 && info.presentationTimeUs >= endTime) { - inputDone = true; - decoderDone = true; - doRender = false; - info.flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM; - } - if (startTime > 0 && videoTime == -1) { - if (info.presentationTimeUs < startTime) { - doRender = false; - Log.d(Config.LOGTAG, "drop frame startTime = " + startTime + " present time = " + info.presentationTimeUs); - } else { - videoTime = info.presentationTimeUs; - } - } - decoder.releaseOutputBuffer(decoderStatus, doRender); - if (doRender) { - boolean errorWait = false; - try { - outputSurface.awaitNewImage(); - } catch (Exception e) { - errorWait = true; - Log.d(Config.LOGTAG, e.getMessage()); - } - if (!errorWait) { - if (Build.VERSION.SDK_INT >= 18) { - outputSurface.drawImage(false); - inputSurface.setPresentationTime(info.presentationTimeUs * 1000); - inputSurface.swapBuffers(); - } else { - int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufIndex >= 0) { - outputSurface.drawImage(true); - ByteBuffer rgbBuf = outputSurface.getFrame(); - ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex]; - yuvBuf.clear(); - convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV); - encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0); - } else { - Log.d(Config.LOGTAG, "input buffer not available"); - } - } - } - } - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - decoderOutputAvailable = false; - Log.d(Config.LOGTAG, "decoder stream end"); - if (Build.VERSION.SDK_INT >= 18) { - encoder.signalEndOfInputStream(); - } else { - int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC); - if (inputBufIndex >= 0) { - encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM); - } - } - } - } - } - } - } - if (videoTime != -1) { - videoStartTime = videoTime; - } - } catch (Exception e) { - Log.d(Config.LOGTAG, e.getMessage()); - error = true; - } - - extractor.unselectTrack(videoIndex); - - if (outputSurface != null) { - outputSurface.release(); - } - if (inputSurface != null) { - inputSurface.release(); - } - if (decoder != null) { - decoder.stop(); - decoder.release(); - } - if (encoder != null) { - encoder.stop(); - encoder.release(); - } - } - } else { - long videoTime = readAndWriteTrack(extractor, mediaMuxer, info, startTime, endTime, cacheFile, false); - if (videoTime != -1) { - videoStartTime = videoTime; - } - } - if (!error) { - readAndWriteTrack(extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true); - } - } catch (Exception e) { - error = true; - Log.d(Config.LOGTAG, e.getMessage()); - } finally { - if (extractor != null) { - extractor.release(); - } - if (mediaMuxer != null) { - try { - mediaMuxer.finishMovie(false); - } catch (Exception e) { - Log.d(Config.LOGTAG, e.getMessage()); - } - } - Log.d(Config.LOGTAG, "time = " + (System.currentTimeMillis() - time)); - } - } else { - didWriteData(true, true); - Log.d(Config.LOGTAG, "Compression failed."); - return false; - } - didWriteData(true, error); - Log.d(Config.LOGTAG, "Compression succeed. Save compressed video to " + cacheFile.toString()); - //inputFile.delete(); - return true; - } -} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java b/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java deleted file mode 100644 index 4cf206d26..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java +++ /dev/null @@ -1,81 +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.googlecode.mp4parser.util.Matrix; - -import java.io.File; -import java.util.ArrayList; - -@TargetApi(16) -public class Mp4Movie { - private Matrix matrix = Matrix.ROTATE_0; - private ArrayList tracks = new ArrayList(); - private File cacheFile; - private int width; - private int height; - - public Matrix getMatrix() { - return matrix; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setCacheFile(File file) { - cacheFile = file; - } - - public void setRotation(int angle) { - if (angle == 0) { - matrix = Matrix.ROTATE_0; - } else if (angle == 90) { - matrix = Matrix.ROTATE_90; - } else if (angle == 180) { - matrix = Matrix.ROTATE_180; - } else if (angle == 270) { - matrix = Matrix.ROTATE_270; - } - } - - public void setSize(int w, int h) { - width = w; - height = h; - } - - public ArrayList getTracks() { - return tracks; - } - - public File getCacheFile() { - return cacheFile; - } - - public void addSample(int trackIndex, long offset, MediaCodec.BufferInfo bufferInfo) throws Exception { - if (trackIndex < 0 || trackIndex >= tracks.size()) { - return; - } - Track track = tracks.get(trackIndex); - track.addSample(offset, bufferInfo); - } - - public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception { - tracks.add(new Track(tracks.size(), mediaFormat, isAudio)); - return tracks.size() - 1; - } -} diff --git a/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java b/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java deleted file mode 100644 index 75ceb46ac..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package de.pixart.messenger.utils.video; - -import android.annotation.TargetApi; -import android.graphics.SurfaceTexture; -import android.opengl.GLES20; -import android.view.Surface; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; - -@TargetApi(16) -public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener { - - private static final int EGL_OPENGL_ES2_BIT = 4; - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - private EGL10 mEGL; - private EGLDisplay mEGLDisplay = null; - private EGLContext mEGLContext = null; - private EGLSurface mEGLSurface = null; - private SurfaceTexture mSurfaceTexture; - private Surface mSurface; - private final Object mFrameSyncObject = new Object(); - private boolean mFrameAvailable; - private TextureRenderer mTextureRender; - private int mWidth; - private int mHeight; - private int rotateRender = 0; - private ByteBuffer mPixelBuf; - - public OutputSurface(int width, int height, int rotate) { - if (width <= 0 || height <= 0) { - throw new IllegalArgumentException(); - } - mWidth = width; - mHeight = height; - rotateRender = rotate; - mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4); - mPixelBuf.order(ByteOrder.LITTLE_ENDIAN); - eglSetup(width, height); - makeCurrent(); - setup(); - } - - public OutputSurface() { - setup(); - } - - private void setup() { - mTextureRender = new TextureRenderer(rotateRender); - mTextureRender.surfaceCreated(); - mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId()); - mSurfaceTexture.setOnFrameAvailableListener(this); - mSurface = new Surface(mSurfaceTexture); - } - - private void eglSetup(int width, int height) { - mEGL = (EGL10) EGLContext.getEGL(); - mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("unable to get EGL10 display"); - } - - if (!mEGL.eglInitialize(mEGLDisplay, null)) { - mEGLDisplay = null; - throw new RuntimeException("unable to initialize EGL10"); - } - - int[] attribList = { - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 8, - EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT, - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_NONE - }; - EGLConfig[] configs = new EGLConfig[1]; - int[] numConfigs = new int[1]; - if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, configs.length, numConfigs)) { - throw new RuntimeException("unable to find RGB888+pbuffer EGL config"); - } - int[] attrib_list = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL10.EGL_NONE - }; - mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT, attrib_list); - checkEglError("eglCreateContext"); - if (mEGLContext == null) { - throw new RuntimeException("null context"); - } - int[] surfaceAttribs = { - EGL10.EGL_WIDTH, width, - EGL10.EGL_HEIGHT, height, - EGL10.EGL_NONE - }; - mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs); - checkEglError("eglCreatePbufferSurface"); - if (mEGLSurface == null) { - throw new RuntimeException("surface was null"); - } - } - - public void release() { - if (mEGL != null) { - if (mEGL.eglGetCurrentContext().equals(mEGLContext)) { - mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - } - mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface); - mEGL.eglDestroyContext(mEGLDisplay, mEGLContext); - } - mSurface.release(); - mEGLDisplay = null; - mEGLContext = null; - mEGLSurface = null; - mEGL = null; - mTextureRender = null; - mSurface = null; - mSurfaceTexture = null; - } - - public void makeCurrent() { - if (mEGL == null) { - throw new RuntimeException("not configured for makeCurrent"); - } - checkEglError("before makeCurrent"); - if (!mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) { - throw new RuntimeException("eglMakeCurrent failed"); - } - } - - public Surface getSurface() { - return mSurface; - } - - public void changeFragmentShader(String fragmentShader) { - mTextureRender.changeFragmentShader(fragmentShader); - } - - public void awaitNewImage() { - final int TIMEOUT_MS = 5000; - synchronized (mFrameSyncObject) { - while (!mFrameAvailable) { - try { - mFrameSyncObject.wait(TIMEOUT_MS); - if (!mFrameAvailable) { - throw new RuntimeException("Surface frame wait timed out"); - } - } catch (InterruptedException ie) { - throw new RuntimeException(ie); - } - } - mFrameAvailable = false; - } - mTextureRender.checkGlError("before updateTexImage"); - mSurfaceTexture.updateTexImage(); - } - - public void drawImage(boolean invert) { - mTextureRender.drawFrame(mSurfaceTexture, invert); - } - - @Override - public void onFrameAvailable(SurfaceTexture st) { - synchronized (mFrameSyncObject) { - if (mFrameAvailable) { - throw new RuntimeException("mFrameAvailable already set, frame could be dropped"); - } - mFrameAvailable = true; - mFrameSyncObject.notifyAll(); - } - } - - public ByteBuffer getFrame() { - mPixelBuf.rewind(); - GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf); - return mPixelBuf; - } - - private void checkEglError(String msg) { - if (mEGL.eglGetError() != EGL10.EGL_SUCCESS) { - throw new RuntimeException("EGL error encountered (see log)"); - } - } -} diff --git a/src/main/java/de/pixart/messenger/utils/video/Sample.java b/src/main/java/de/pixart/messenger/utils/video/Sample.java deleted file mode 100644 index f00ee5311..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/Sample.java +++ /dev/null @@ -1,27 +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; - -public class Sample { - private long offset = 0; - private long size = 0; - - public Sample(long offset, long size) { - this.offset = offset; - this.size = size; - } - - public long getOffset() { - return offset; - } - - public long getSize() { - return size; - } -} diff --git a/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java b/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java deleted file mode 100644 index 3c53941ea..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package de.pixart.messenger.utils.video; - -import android.annotation.TargetApi; -import android.graphics.SurfaceTexture; -import android.opengl.GLES11Ext; -import android.opengl.GLES20; -import android.opengl.Matrix; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; - -@TargetApi(16) -public class TextureRenderer { - - private static final int FLOAT_SIZE_BYTES = 4; - private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; - private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; - private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; - private static final float[] mTriangleVerticesData = { - -1.0f, -1.0f, 0, 0.f, 0.f, - 1.0f, -1.0f, 0, 1.f, 0.f, - -1.0f, 1.0f, 0, 0.f, 1.f, - 1.0f, 1.0f, 0, 1.f, 1.f, - }; - private FloatBuffer mTriangleVertices; - - private static final String VERTEX_SHADER = - "uniform mat4 uMVPMatrix;\n" + - "uniform mat4 uSTMatrix;\n" + - "attribute vec4 aPosition;\n" + - "attribute vec4 aTextureCoord;\n" + - "varying vec2 vTextureCoord;\n" + - "void main() {\n" + - " gl_Position = uMVPMatrix * aPosition;\n" + - " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + - "}\n"; - - private static final String FRAGMENT_SHADER = - "#extension GL_OES_EGL_image_external : require\n" + - "precision mediump float;\n" + - "varying vec2 vTextureCoord;\n" + - "uniform samplerExternalOES sTexture;\n" + - "void main() {\n" + - " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + - "}\n"; - - private float[] mMVPMatrix = new float[16]; - private float[] mSTMatrix = new float[16]; - private int mProgram; - private int mTextureID = -12345; - private int muMVPMatrixHandle; - private int muSTMatrixHandle; - private int maPositionHandle; - private int maTextureHandle; - private int rotationAngle = 0; - - public TextureRenderer(int rotation) { - rotationAngle = rotation; - mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); - mTriangleVertices.put(mTriangleVerticesData).position(0); - Matrix.setIdentityM(mSTMatrix, 0); - } - - public int getTextureId() { - return mTextureID; - } - - public void drawFrame(SurfaceTexture st, boolean invert) { - checkGlError("onDrawFrame start"); - st.getTransformMatrix(mSTMatrix); - - if (invert) { - mSTMatrix[5] = -mSTMatrix[5]; - mSTMatrix[13] = 1.0f - mSTMatrix[13]; - } - - GLES20.glUseProgram(mProgram); - checkGlError("glUseProgram"); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID); - mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); - GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); - checkGlError("glVertexAttribPointer maPosition"); - GLES20.glEnableVertexAttribArray(maPositionHandle); - checkGlError("glEnableVertexAttribArray maPositionHandle"); - mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); - GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); - checkGlError("glVertexAttribPointer maTextureHandle"); - GLES20.glEnableVertexAttribArray(maTextureHandle); - checkGlError("glEnableVertexAttribArray maTextureHandle"); - GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); - GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - checkGlError("glDrawArrays"); - GLES20.glFinish(); - } - - public void surfaceCreated() { - mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER); - if (mProgram == 0) { - throw new RuntimeException("failed creating program"); - } - maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); - checkGlError("glGetAttribLocation aPosition"); - if (maPositionHandle == -1) { - throw new RuntimeException("Could not get attrib location for aPosition"); - } - maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); - checkGlError("glGetAttribLocation aTextureCoord"); - if (maTextureHandle == -1) { - throw new RuntimeException("Could not get attrib location for aTextureCoord"); - } - muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); - checkGlError("glGetUniformLocation uMVPMatrix"); - if (muMVPMatrixHandle == -1) { - throw new RuntimeException("Could not get attrib location for uMVPMatrix"); - } - muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix"); - checkGlError("glGetUniformLocation uSTMatrix"); - if (muSTMatrixHandle == -1) { - throw new RuntimeException("Could not get attrib location for uSTMatrix"); - } - int[] textures = new int[1]; - GLES20.glGenTextures(1, textures, 0); - mTextureID = textures[0]; - GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID); - checkGlError("glBindTexture mTextureID"); - GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); - GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - checkGlError("glTexParameter"); - - Matrix.setIdentityM(mMVPMatrix, 0); - if (rotationAngle != 0) { - Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1); - } - } - - public void changeFragmentShader(String fragmentShader) { - GLES20.glDeleteProgram(mProgram); - mProgram = createProgram(VERTEX_SHADER, fragmentShader); - if (mProgram == 0) { - throw new RuntimeException("failed creating program"); - } - } - - private int loadShader(int shaderType, String source) { - int shader = GLES20.glCreateShader(shaderType); - checkGlError("glCreateShader type=" + shaderType); - GLES20.glShaderSource(shader, source); - GLES20.glCompileShader(shader); - int[] compiled = new int[1]; - GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); - if (compiled[0] == 0) { - GLES20.glDeleteShader(shader); - shader = 0; - } - return shader; - } - - private int createProgram(String vertexSource, String fragmentSource) { - int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); - if (vertexShader == 0) { - return 0; - } - int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); - if (pixelShader == 0) { - return 0; - } - int program = GLES20.glCreateProgram(); - checkGlError("glCreateProgram"); - if (program == 0) { - return 0; - } - GLES20.glAttachShader(program, vertexShader); - checkGlError("glAttachShader"); - GLES20.glAttachShader(program, pixelShader); - checkGlError("glAttachShader"); - GLES20.glLinkProgram(program); - int[] linkStatus = new int[1]; - GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); - if (linkStatus[0] != GLES20.GL_TRUE) { - GLES20.glDeleteProgram(program); - program = 0; - } - return program; - } - - public void checkGlError(String op) { - int error; - if ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { - throw new RuntimeException(op + ": glError " + error); - } - } -} diff --git a/src/main/java/de/pixart/messenger/utils/video/Track.java b/src/main/java/de/pixart/messenger/utils/video/Track.java deleted file mode 100644 index 18111a675..000000000 --- a/src/main/java/de/pixart/messenger/utils/video/Track.java +++ /dev/null @@ -1,263 +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.boxes.AbstractMediaHeaderBox; -import com.coremedia.iso.boxes.SampleDescriptionBox; -import com.coremedia.iso.boxes.SoundMediaHeaderBox; -import com.coremedia.iso.boxes.VideoMediaHeaderBox; -import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry; -import com.coremedia.iso.boxes.sampleentry.VisualSampleEntry; -import com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.AudioSpecificConfig; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.DecoderConfigDescriptor; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor; -import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.SLConfigDescriptor; -import com.mp4parser.iso14496.part15.AvcConfigurationBox; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -@TargetApi(16) -public class Track { - private long trackId = 0; - private ArrayList samples = new ArrayList(); - private long duration = 0; - private String handler; - private AbstractMediaHeaderBox headerBox = null; - private SampleDescriptionBox sampleDescriptionBox = null; - private LinkedList syncSamples = null; - private int timeScale; - private Date creationTime = new Date(); - private int height; - private int width; - private float volume = 0; - private ArrayList sampleDurations = new ArrayList(); - private boolean isAudio = false; - private static Map samplingFrequencyIndexMap = new HashMap(); - private long lastPresentationTimeUs = 0; - private boolean first = true; - - static { - samplingFrequencyIndexMap.put(96000, 0x0); - samplingFrequencyIndexMap.put(88200, 0x1); - samplingFrequencyIndexMap.put(64000, 0x2); - samplingFrequencyIndexMap.put(48000, 0x3); - samplingFrequencyIndexMap.put(44100, 0x4); - samplingFrequencyIndexMap.put(32000, 0x5); - samplingFrequencyIndexMap.put(24000, 0x6); - samplingFrequencyIndexMap.put(22050, 0x7); - samplingFrequencyIndexMap.put(16000, 0x8); - samplingFrequencyIndexMap.put(12000, 0x9); - samplingFrequencyIndexMap.put(11025, 0xa); - samplingFrequencyIndexMap.put(8000, 0xb); - } - - public Track(int id, MediaFormat format, boolean isAudio) throws Exception { - trackId = id; - if (!isAudio) { - sampleDurations.add((long) 3015); - duration = 3015; - width = format.getInteger(MediaFormat.KEY_WIDTH); - height = format.getInteger(MediaFormat.KEY_HEIGHT); - timeScale = 90000; - syncSamples = new LinkedList(); - handler = "vide"; - headerBox = new VideoMediaHeaderBox(); - sampleDescriptionBox = new SampleDescriptionBox(); - String mime = format.getString(MediaFormat.KEY_MIME); - if (mime.equals("video/avc")) { - VisualSampleEntry visualSampleEntry = new VisualSampleEntry("avc1"); - visualSampleEntry.setDataReferenceIndex(1); - visualSampleEntry.setDepth(24); - visualSampleEntry.setFrameCount(1); - visualSampleEntry.setHorizresolution(72); - visualSampleEntry.setVertresolution(72); - visualSampleEntry.setWidth(width); - visualSampleEntry.setHeight(height); - - AvcConfigurationBox avcConfigurationBox = new AvcConfigurationBox(); - - if (format.getByteBuffer("csd-0") != null) { - ArrayList spsArray = new ArrayList(); - ByteBuffer spsBuff = format.getByteBuffer("csd-0"); - spsBuff.position(4); - byte[] spsBytes = new byte[spsBuff.remaining()]; - spsBuff.get(spsBytes); - spsArray.add(spsBytes); - - ArrayList ppsArray = new ArrayList(); - ByteBuffer ppsBuff = format.getByteBuffer("csd-1"); - ppsBuff.position(4); - byte[] ppsBytes = new byte[ppsBuff.remaining()]; - ppsBuff.get(ppsBytes); - ppsArray.add(ppsBytes); - avcConfigurationBox.setSequenceParameterSets(spsArray); - avcConfigurationBox.setPictureParameterSets(ppsArray); - } - //ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(spsBytes); - //SeqParameterSet seqParameterSet = SeqParameterSet.read(byteArrayInputStream); - - avcConfigurationBox.setAvcLevelIndication(13); - avcConfigurationBox.setAvcProfileIndication(100); - avcConfigurationBox.setBitDepthLumaMinus8(-1); - avcConfigurationBox.setBitDepthChromaMinus8(-1); - avcConfigurationBox.setChromaFormat(-1); - avcConfigurationBox.setConfigurationVersion(1); - avcConfigurationBox.setLengthSizeMinusOne(3); - avcConfigurationBox.setProfileCompatibility(0); - - visualSampleEntry.addBox(avcConfigurationBox); - sampleDescriptionBox.addBox(visualSampleEntry); - } else if (mime.equals("video/mp4v")) { - VisualSampleEntry visualSampleEntry = new VisualSampleEntry("mp4v"); - visualSampleEntry.setDataReferenceIndex(1); - visualSampleEntry.setDepth(24); - visualSampleEntry.setFrameCount(1); - visualSampleEntry.setHorizresolution(72); - visualSampleEntry.setVertresolution(72); - visualSampleEntry.setWidth(width); - visualSampleEntry.setHeight(height); - - sampleDescriptionBox.addBox(visualSampleEntry); - } - } else { - sampleDurations.add((long) 1024); - duration = 1024; - isAudio = true; - volume = 1; - timeScale = format.getInteger(MediaFormat.KEY_SAMPLE_RATE); - handler = "soun"; - headerBox = new SoundMediaHeaderBox(); - sampleDescriptionBox = new SampleDescriptionBox(); - AudioSampleEntry audioSampleEntry = new AudioSampleEntry("mp4a"); - audioSampleEntry.setChannelCount(format.getInteger(MediaFormat.KEY_CHANNEL_COUNT)); - audioSampleEntry.setSampleRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE)); - audioSampleEntry.setDataReferenceIndex(1); - audioSampleEntry.setSampleSize(16); - - ESDescriptorBox esds = new ESDescriptorBox(); - ESDescriptor descriptor = new ESDescriptor(); - descriptor.setEsId(0); - - SLConfigDescriptor slConfigDescriptor = new SLConfigDescriptor(); - slConfigDescriptor.setPredefined(2); - descriptor.setSlConfigDescriptor(slConfigDescriptor); - - DecoderConfigDescriptor decoderConfigDescriptor = new DecoderConfigDescriptor(); - decoderConfigDescriptor.setObjectTypeIndication(0x40); - decoderConfigDescriptor.setStreamType(5); - decoderConfigDescriptor.setBufferSizeDB(1536); - decoderConfigDescriptor.setMaxBitRate(96000); - decoderConfigDescriptor.setAvgBitRate(96000); - - AudioSpecificConfig audioSpecificConfig = new AudioSpecificConfig(); - audioSpecificConfig.setAudioObjectType(2); - audioSpecificConfig.setSamplingFrequencyIndex(samplingFrequencyIndexMap.get((int) audioSampleEntry.getSampleRate())); - audioSpecificConfig.setChannelConfiguration(audioSampleEntry.getChannelCount()); - decoderConfigDescriptor.setAudioSpecificInfo(audioSpecificConfig); - - descriptor.setDecoderConfigDescriptor(decoderConfigDescriptor); - - ByteBuffer data = descriptor.serialize(); - esds.setEsDescriptor(descriptor); - esds.setData(data); - audioSampleEntry.addBox(esds); - sampleDescriptionBox.addBox(audioSampleEntry); - } - } - - public long getTrackId() { - return trackId; - } - - public void addSample(long offset, MediaCodec.BufferInfo bufferInfo) { - boolean isSyncFrame = !isAudio && (bufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0; - samples.add(new Sample(offset, bufferInfo.size)); - if (syncSamples != null && isSyncFrame) { - syncSamples.add(samples.size()); - } - - long delta = bufferInfo.presentationTimeUs - lastPresentationTimeUs; - lastPresentationTimeUs = bufferInfo.presentationTimeUs; - delta = (delta * timeScale + 500000L) / 1000000L; - if (!first) { - sampleDurations.add(sampleDurations.size() - 1, delta); - duration += delta; - } - first = false; - } - - public ArrayList getSamples() { - return samples; - } - - public long getDuration() { - return duration; - } - - public String getHandler() { - return handler; - } - - public AbstractMediaHeaderBox getMediaHeaderBox() { - return headerBox; - } - - public SampleDescriptionBox getSampleDescriptionBox() { - return sampleDescriptionBox; - } - - public long[] getSyncSamples() { - if (syncSamples == null || syncSamples.isEmpty()) { - return null; - } - long[] returns = new long[syncSamples.size()]; - for (int i = 0; i < syncSamples.size(); i++) { - returns[i] = syncSamples.get(i); - } - return returns; - } - - public int getTimeScale() { - return timeScale; - } - - public Date getCreationTime() { - return creationTime; - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public float getVolume() { - return volume; - } - - public ArrayList getSampleDurations() { - return sampleDurations; - } - - public boolean isAudio() { - return isAudio; - } -} -- cgit v1.2.3