Video convert queue, bug fixes
|
@ -80,7 +80,7 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 8
|
||||
targetSdkVersion 19
|
||||
versionCode 330
|
||||
versionCode 331
|
||||
versionName "1.9.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ public class ContactsController {
|
|||
try {
|
||||
nameDisplayOrder = Settings.System.getInt(ApplicationLoader.applicationContext.getContentResolver(), "android.contacts.DISPLAY_ORDER");
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
//don't promt
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -586,41 +586,69 @@ public class ImageLoader {
|
|||
private HashMap<Integer, File> createMediaPaths() {
|
||||
HashMap<Integer, File> mediaDirs = new HashMap<Integer, File>();
|
||||
File cachePath = AndroidUtilities.getCacheDir();
|
||||
if (!cachePath.isDirectory()) {
|
||||
try {
|
||||
cachePath.mkdirs();
|
||||
new File(cachePath, ".nomedia").createNewFile();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_CACHE, cachePath);
|
||||
|
||||
try {
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
File telegramPath = new File(Environment.getExternalStorageDirectory(), LocaleController.getString("AppName", R.string.AppName));
|
||||
telegramPath.mkdirs();
|
||||
|
||||
if (telegramPath.isDirectory()) {
|
||||
try {
|
||||
File imagePath = new File(telegramPath, "Images");
|
||||
imagePath.mkdir();
|
||||
if (imagePath.isDirectory()) {
|
||||
new File(imagePath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_IMAGE, imagePath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File videoPath = new File(telegramPath, "Video");
|
||||
videoPath.mkdir();
|
||||
if (videoPath.isDirectory()) {
|
||||
new File(videoPath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_VIDEO, videoPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File audioPath = new File(telegramPath, "Audio");
|
||||
audioPath.mkdir();
|
||||
if (audioPath.isDirectory()) {
|
||||
new File(audioPath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_AUDIO, audioPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
try {
|
||||
File documentPath = new File(telegramPath, "Documents");
|
||||
documentPath.mkdir();
|
||||
if (documentPath.isDirectory()) {
|
||||
new File(documentPath, ".nomedia").createNewFile();
|
||||
mediaDirs.put(FileLoader.MEDIA_DIR_DOCUMENT, documentPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
return mediaDirs;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package org.telegram.android;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -21,16 +22,26 @@ import android.media.AudioFormat;
|
|||
import android.media.AudioManager;
|
||||
import android.media.AudioRecord;
|
||||
import android.media.AudioTrack;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecList;
|
||||
import android.media.MediaExtractor;
|
||||
import android.media.MediaFormat;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaRecorder;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.MediaStore;
|
||||
import android.view.View;
|
||||
|
||||
import org.telegram.android.video.InputSurface;
|
||||
import org.telegram.android.video.MP4Builder;
|
||||
import org.telegram.android.video.Mp4Movie;
|
||||
import org.telegram.android.video.OutputSurface;
|
||||
import org.telegram.messenger.ConnectionsManager;
|
||||
import org.telegram.messenger.DispatchQueue;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
|
@ -133,6 +144,17 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
|||
}
|
||||
}
|
||||
|
||||
private 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 Object videoConvertSync = new Object();
|
||||
|
||||
private ArrayList<MessageObject> videoConvertQueue = new ArrayList<MessageObject>();
|
||||
private final Object videoQueueSync = new Object();
|
||||
private boolean cancelCurrentVideoConversion = false;
|
||||
private boolean videoConvertFirstWrite = true;
|
||||
|
||||
public static final int AUTODOWNLOAD_MASK_PHOTO = 1;
|
||||
public static final int AUTODOWNLOAD_MASK_AUDIO = 2;
|
||||
public static final int AUTODOWNLOAD_MASK_VIDEO = 4;
|
||||
|
@ -1441,11 +1463,10 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
|||
public void run() {
|
||||
audioToSend.date = ConnectionsManager.getInstance().getCurrentTime();
|
||||
audioToSend.size = (int) recordingAudioFileToSend.length();
|
||||
audioToSend.path = recordingAudioFileToSend.getAbsolutePath();
|
||||
long duration = recordTimeCount;
|
||||
audioToSend.duration = (int) (duration / 1000);
|
||||
if (duration > 700) {
|
||||
SendMessagesHelper.getInstance().sendMessage(audioToSend, recordDialogId);
|
||||
SendMessagesHelper.getInstance().sendMessage(audioToSend, recordingAudioFileToSend.getAbsolutePath(), recordDialogId);
|
||||
} else {
|
||||
recordingAudioFileToSend.delete();
|
||||
}
|
||||
|
@ -1838,4 +1859,600 @@ public class MediaController implements NotificationCenter.NotificationCenterDel
|
|||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void scheduleVideoConvert(MessageObject messageObject) {
|
||||
videoConvertQueue.add(messageObject);
|
||||
if (videoConvertQueue.size() == 1) {
|
||||
startVideoConvertFromQueue();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelVideoConvert(MessageObject messageObject) {
|
||||
if (!videoConvertQueue.isEmpty()) {
|
||||
if (videoConvertQueue.get(0) == messageObject) {
|
||||
synchronized (videoConvertSync) {
|
||||
cancelCurrentVideoConversion = true;
|
||||
}
|
||||
}
|
||||
videoConvertQueue.remove(messageObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void startVideoConvertFromQueue() {
|
||||
if (!videoConvertQueue.isEmpty()) {
|
||||
MessageObject messageObject = videoConvertQueue.get(0);
|
||||
VideoConvertRunnable.runConversion(messageObject);
|
||||
}
|
||||
}
|
||||
|
||||
private 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;
|
||||
FileLog.e("tmessages", "available codec = " + codecInfo.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return lastCodecInfo;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
|
||||
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
|
||||
for (int i = 0; i < capabilities.colorFormats.length; i++) {
|
||||
int colorFormat = capabilities.colorFormats[i];
|
||||
if (isRecognizedFormat(colorFormat)) {
|
||||
return colorFormat;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
private void didWriteData(final MessageObject messageObject, final File file, final long finalSize, final boolean error) {
|
||||
final boolean firstWrite = videoConvertFirstWrite;
|
||||
if (firstWrite) {
|
||||
videoConvertFirstWrite = false;
|
||||
}
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (error) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FilePreparingFailed, messageObject, file.toString());
|
||||
} else {
|
||||
if (firstWrite) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FilePreparingStarted, messageObject, file.toString());
|
||||
}
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileNewChunkAvailable, messageObject, file.toString(), finalSize);
|
||||
}
|
||||
if (finalSize != 0) {
|
||||
synchronized (videoConvertSync) {
|
||||
cancelCurrentVideoConversion = false;
|
||||
}
|
||||
videoConvertQueue.remove(messageObject);
|
||||
startVideoConvertFromQueue();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private long readAndWriteTrack(final MessageObject messageObject, 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;
|
||||
|
||||
checkConversionCanceled();
|
||||
|
||||
while (!inputDone) {
|
||||
checkConversionCanceled();
|
||||
|
||||
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 (!isAudio) {
|
||||
buffer.limit(info.offset + info.size);
|
||||
buffer.position(info.offset);
|
||||
buffer.putInt(info.size - 4);
|
||||
}
|
||||
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
|
||||
didWriteData(messageObject, file, 0, false);
|
||||
}
|
||||
extractor.advance();
|
||||
} else {
|
||||
eof = true;
|
||||
}
|
||||
}
|
||||
} else if (index == -1) {
|
||||
eof = true;
|
||||
}
|
||||
if (eof) {
|
||||
inputDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
extractor.unselectTrack(trackIndex);
|
||||
return startTime;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static class VideoConvertRunnable implements Runnable {
|
||||
|
||||
private MessageObject messageObject;
|
||||
|
||||
private VideoConvertRunnable(MessageObject message) {
|
||||
messageObject = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
MediaController.getInstance().convertVideo(messageObject);
|
||||
}
|
||||
|
||||
public static void runConversion(final MessageObject obj) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
VideoConvertRunnable wrapper = new VideoConvertRunnable(obj);
|
||||
Thread th = new Thread(wrapper, "VideoConvertRunnable");
|
||||
th.start();
|
||||
th.join();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkConversionCanceled() throws Exception {
|
||||
boolean cancelConversion = false;
|
||||
synchronized (videoConvertSync) {
|
||||
cancelConversion = cancelCurrentVideoConversion;
|
||||
}
|
||||
if (cancelConversion) {
|
||||
throw new RuntimeException("canceled conversion");
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(16)
|
||||
private boolean convertVideo(final MessageObject messageObject) {
|
||||
String videoPath = messageObject.messageOwner.videoEditedInfo.originalPath;
|
||||
long startTime = messageObject.messageOwner.videoEditedInfo.startTime;
|
||||
long endTime = messageObject.messageOwner.videoEditedInfo.endTime;
|
||||
int resultWidth = messageObject.messageOwner.videoEditedInfo.resultWidth;
|
||||
int resultHeight = messageObject.messageOwner.videoEditedInfo.resultHeight;
|
||||
int rotationValue = messageObject.messageOwner.videoEditedInfo.rotationValue;
|
||||
int originalWidth = messageObject.messageOwner.videoEditedInfo.originalWidth;
|
||||
int originalHeight = messageObject.messageOwner.videoEditedInfo.originalHeight;
|
||||
int bitrate = messageObject.messageOwner.videoEditedInfo.bitrate;
|
||||
File cacheFile = new File(messageObject.messageOwner.attachPath);
|
||||
|
||||
File inputFile = new File(videoPath);
|
||||
if (!inputFile.canRead()) {
|
||||
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);
|
||||
resultHeight = 352;
|
||||
movie.setSize(resultWidth, resultHeight);
|
||||
mediaMuxer = new MP4Builder().createMovie(movie);
|
||||
extractor = new MediaExtractor();
|
||||
extractor.setDataSource(inputFile.toString());
|
||||
|
||||
checkConversionCanceled();
|
||||
|
||||
if (resultWidth != originalWidth || resultHeight != originalHeight) {
|
||||
int videoIndex = -5;
|
||||
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 = 0;
|
||||
int processorType = PROCESSOR_TYPE_OTHER;
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
|
||||
colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
|
||||
String manufacturer = Build.MANUFACTURER.toLowerCase();
|
||||
if (codecInfo.getName().contains("OMX.qcom.")) {
|
||||
processorType = PROCESSOR_TYPE_QCOM;
|
||||
if (Build.VERSION.SDK_INT == 16) {
|
||||
if (manufacturer.equals("lge") || manufacturer.equals("nokia")) {
|
||||
swapUV = 1;
|
||||
}
|
||||
}
|
||||
} else if (codecInfo.getName().contains("OMX.Intel.")) {
|
||||
processorType = PROCESSOR_TYPE_INTEL;
|
||||
}
|
||||
FileLog.e("tmessages", "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer);
|
||||
} else {
|
||||
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
|
||||
}
|
||||
FileLog.e("tmessages", "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 (!Build.MANUFACTURER.toLowerCase().equals("lge")) {
|
||||
int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
|
||||
padding = uvoffset - (resultWidth * resultHeight);
|
||||
bufferSize += padding;
|
||||
}
|
||||
} else if (processorType == PROCESSOR_TYPE_INTEL) {
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
outputFormat.setInteger("slice-height", resultHeightAligned);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
|
||||
decoder.start();
|
||||
|
||||
final int TIMEOUT_USEC = 2500;
|
||||
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
|
||||
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
|
||||
ByteBuffer[] encoderInputBuffers = null;
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
encoderInputBuffers = encoder.getInputBuffers();
|
||||
}
|
||||
|
||||
checkConversionCanceled();
|
||||
|
||||
while (!outputDone) {
|
||||
checkConversionCanceled();
|
||||
if (!inputDone) {
|
||||
boolean eof = false;
|
||||
int index = extractor.getSampleTrackIndex();
|
||||
if (index == videoIndex) {
|
||||
int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
|
||||
if (inputBufIndex >= 0) {
|
||||
ByteBuffer inputBuf = decoderInputBuffers[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) {
|
||||
checkConversionCanceled();
|
||||
int encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
|
||||
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
|
||||
encoderOutputAvailable = false;
|
||||
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
|
||||
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 = encoderOutputBuffers[encoderStatus];
|
||||
if (encodedData == null) {
|
||||
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
|
||||
}
|
||||
if (info.size > 1) {
|
||||
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
|
||||
encodedData.limit(info.offset + info.size);
|
||||
encodedData.position(info.offset);
|
||||
encodedData.putInt(Integer.reverseBytes(info.size - 4));
|
||||
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
|
||||
didWriteData(messageObject, cacheFile, 0, 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();
|
||||
} else if (decoderStatus < 0) {
|
||||
throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
|
||||
} else {
|
||||
boolean doRender = false;
|
||||
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;
|
||||
FileLog.e("tmessages", "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;
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
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();
|
||||
Utilities.convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV);
|
||||
encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
|
||||
} else {
|
||||
FileLog.e("tmessages", "input buffer not available");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
|
||||
decoderOutputAvailable = false;
|
||||
FileLog.e("tmessages", "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) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
extractor.unselectTrack(videoIndex);
|
||||
|
||||
if (outputSurface != null) {
|
||||
outputSurface.release();
|
||||
outputSurface = null;
|
||||
}
|
||||
if (inputSurface != null) {
|
||||
inputSurface.release();
|
||||
inputSurface = null;
|
||||
}
|
||||
if (decoder != null) {
|
||||
decoder.stop();
|
||||
decoder.release();
|
||||
decoder = null;
|
||||
}
|
||||
if (encoder != null) {
|
||||
encoder.stop();
|
||||
encoder.release();
|
||||
encoder = null;
|
||||
}
|
||||
|
||||
checkConversionCanceled();
|
||||
}
|
||||
} else {
|
||||
long videoTime = readAndWriteTrack(messageObject, extractor, mediaMuxer, info, startTime, endTime, cacheFile, false);
|
||||
if (videoTime != -1) {
|
||||
videoStartTime = videoTime;
|
||||
}
|
||||
}
|
||||
readAndWriteTrack(messageObject, extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true);
|
||||
} catch (Exception e) {
|
||||
error = true;
|
||||
FileLog.e("tmessages", e);
|
||||
} finally {
|
||||
if (extractor != null) {
|
||||
extractor.release();
|
||||
extractor = null;
|
||||
}
|
||||
if (mediaMuxer != null) {
|
||||
try {
|
||||
mediaMuxer.finishMovie(false);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
mediaMuxer = null;
|
||||
}
|
||||
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
didWriteData(messageObject, cacheFile, cacheFile.length(), error);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -623,4 +623,16 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSending() {
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SENDING;
|
||||
}
|
||||
|
||||
public boolean isSendError() {
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
}
|
||||
|
||||
public boolean isSent() {
|
||||
return messageOwner.send_state == MESSAGE_SEND_STATE_SENT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2450,7 +2450,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
|||
public void run() {
|
||||
for (HashMap.Entry<Integer, Integer> entry : corrected.entrySet()) {
|
||||
Integer oldId = entry.getKey();
|
||||
SendMessagesHelper.getInstance().setMessageSent(oldId);
|
||||
SendMessagesHelper.getInstance().processSentMessage(oldId);
|
||||
Integer newId = entry.getValue();
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newId, null);
|
||||
}
|
||||
|
@ -3464,9 +3464,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
|
|||
} else {
|
||||
MessageObject currentDialogMessage = dialogMessage.get(dialog.top_message);
|
||||
if (currentDialogMessage != null) {
|
||||
if (currentDialogMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING && lastMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (currentDialogMessage.isSending() && lastMessage.isSending()) {
|
||||
change = true;
|
||||
} else if (dialog.last_message_date < lastMessage.messageOwner.date || dialog.last_message_date == lastMessage.messageOwner.date && lastMessage.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
} else if (dialog.last_message_date < lastMessage.messageOwner.date || dialog.last_message_date == lastMessage.messageOwner.date && lastMessage.isSending()) {
|
||||
change = true;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -39,6 +39,7 @@ public class NotificationCenter {
|
|||
public static final int pushMessagesUpdated = 27;
|
||||
public static final int blockedUsersDidLoaded = 28;
|
||||
public static final int openedChatChanged = 29;
|
||||
public static final int hideEmojiKeyboard = 30;
|
||||
|
||||
public static final int wallpapersDidLoaded = 171;
|
||||
public static final int closeOtherAppActivities = 702;
|
||||
|
@ -52,6 +53,9 @@ public class NotificationCenter {
|
|||
public static final int FileLoadProgressChanged = 10003;
|
||||
public static final int FileDidLoaded = 10004;
|
||||
public static final int FileDidFailedLoad = 10005;
|
||||
public static final int FilePreparingStarted = 10006;
|
||||
public static final int FileNewChunkAvailable = 10007;
|
||||
public static final int FilePreparingFailed = 10008;
|
||||
|
||||
public final static int audioProgressDidChanged = 50001;
|
||||
public final static int audioDidReset = 50002;
|
||||
|
|
|
@ -60,7 +60,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
public SendMessagesHelper() {
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidUpload);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailUpload);
|
||||
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FilePreparingStarted);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileNewChunkAvailable);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FilePreparingFailed);
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
|
@ -72,10 +74,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
currentChatInfo = info;
|
||||
}
|
||||
|
||||
public void setMessageSent(Integer id) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, Object... args) {
|
||||
if (id == NotificationCenter.FileDidUpload) {
|
||||
|
@ -102,19 +100,23 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
media.file = file;
|
||||
performSendMessageRequest(message.sendRequest, message.obj, message.originalPath);
|
||||
} else if (message.type == 1) {
|
||||
if (media.thumb == null) {
|
||||
media.thumb = file;
|
||||
if (media.file == null) {
|
||||
media.file = file;
|
||||
performSendDelayedMessage(message);
|
||||
} else {
|
||||
media.file = file;
|
||||
media.thumb = file;
|
||||
performSendMessageRequest(message.sendRequest, message.obj, message.originalPath);
|
||||
}
|
||||
} else if (message.type == 2) {
|
||||
if (media.file == null) {
|
||||
media.file = file;
|
||||
if (media.thumb == null && message.location != null) {
|
||||
media.thumb = file;
|
||||
performSendDelayedMessage(message);
|
||||
} else {
|
||||
media.file = file;
|
||||
performSendMessageRequest(message.sendRequest, message.obj, message.originalPath);
|
||||
}
|
||||
} else {
|
||||
media.thumb = file;
|
||||
performSendMessageRequest(message.sendRequest, message.obj, message.originalPath);
|
||||
}
|
||||
} else if (message.type == 3) {
|
||||
|
@ -163,6 +165,72 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
}
|
||||
}
|
||||
});
|
||||
} else if (id == NotificationCenter.FilePreparingStarted) {
|
||||
MessageObject messageObject = (MessageObject)args[0];
|
||||
String finalPath = (String)args[1];
|
||||
|
||||
ArrayList<DelayedMessage> arr = delayedMessages.get(messageObject.messageOwner.attachPath);
|
||||
if (arr != null) {
|
||||
for (int a = 0; a < arr.size(); a++) {
|
||||
DelayedMessage message = arr.get(a);
|
||||
if (message.obj == messageObject) {
|
||||
message.videoLocation.videoEditedInfo = null;
|
||||
performSendDelayedMessage(message);
|
||||
arr.remove(a);
|
||||
a--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arr.isEmpty()) {
|
||||
delayedMessages.remove(messageObject.messageOwner.attachPath);
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.FileNewChunkAvailable) {
|
||||
MessageObject messageObject = (MessageObject)args[0];
|
||||
String finalPath = (String)args[1];
|
||||
long finalSize = (Long)args[2];
|
||||
boolean isEncrypted = ((int)messageObject.getDialogId()) == 0;
|
||||
FileLoader.getInstance().checkUploadNewDataAvailable(finalPath, isEncrypted, finalSize);
|
||||
if (finalSize != 0) {
|
||||
ArrayList<DelayedMessage> arr = delayedMessages.get(messageObject.messageOwner.attachPath);
|
||||
if (arr != null) {
|
||||
for (DelayedMessage message : arr) {
|
||||
if (message.obj == messageObject) {
|
||||
message.obj.messageOwner.videoEditedInfo = null;
|
||||
message.obj.messageOwner.message = "-1";
|
||||
|
||||
ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
|
||||
messages.add(message.obj.messageOwner);
|
||||
MessagesStorage.getInstance().putMessages(messages, false, true, false, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (arr.isEmpty()) {
|
||||
delayedMessages.remove(messageObject.messageOwner.attachPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.FilePreparingFailed) {
|
||||
MessageObject messageObject = (MessageObject)args[0];
|
||||
String finalPath = (String)args[1];
|
||||
|
||||
ArrayList<DelayedMessage> arr = delayedMessages.get(finalPath);
|
||||
if (arr != null) {
|
||||
for (int a = 0; a < arr.size(); a++) {
|
||||
DelayedMessage message = arr.get(a);
|
||||
if (message.obj == messageObject) {
|
||||
MessagesStorage.getInstance().markMessageAsSendError(message.obj.messageOwner.id);
|
||||
message.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
arr.remove(a);
|
||||
a--;
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.messageOwner.id);
|
||||
processSentMessage(message.obj.messageOwner.id);
|
||||
}
|
||||
}
|
||||
if (arr.isEmpty()) {
|
||||
delayedMessages.remove(finalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,6 +243,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
DelayedMessage message = messages.get(a);
|
||||
if (message.obj.messageOwner.id == object.messageOwner.id) {
|
||||
messages.remove(a);
|
||||
MediaController.getInstance().cancelVideoConvert(message.obj);
|
||||
if (messages.size() == 0) {
|
||||
keyToRemvoe = entry.getKey();
|
||||
if (message.sendEncryptedRequest != null) {
|
||||
|
@ -204,7 +273,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
return true;
|
||||
}
|
||||
|
||||
private void processSentMessage(int id) {
|
||||
public void processSentMessage(int id) {
|
||||
int prevSize = unsentMessages.size();
|
||||
unsentMessages.remove(id);
|
||||
if (prevSize != 0 && unsentMessages.size() == 0) {
|
||||
|
@ -220,14 +289,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo) {
|
||||
sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did);
|
||||
} else if (messageObject.messageOwner.media.audio instanceof TLRPC.TL_audio) {
|
||||
messageObject.messageOwner.media.audio.path = messageObject.messageOwner.attachPath;
|
||||
sendMessage((TLRPC.TL_audio) messageObject.messageOwner.media.audio, did);
|
||||
sendMessage((TLRPC.TL_audio) messageObject.messageOwner.media.audio, messageObject.messageOwner.attachPath, did);
|
||||
} else if (messageObject.messageOwner.media.video instanceof TLRPC.TL_video) {
|
||||
messageObject.messageOwner.media.video.path = messageObject.messageOwner.attachPath;
|
||||
sendMessage((TLRPC.TL_video) messageObject.messageOwner.media.video, null, did);
|
||||
TLRPC.TL_video video = (TLRPC.TL_video) messageObject.messageOwner.media.video;
|
||||
video.videoEditedInfo = messageObject.messageOwner.videoEditedInfo;
|
||||
sendMessage(video, null, messageObject.messageOwner.attachPath, did);
|
||||
} else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) {
|
||||
messageObject.messageOwner.media.document.path = messageObject.messageOwner.attachPath;
|
||||
sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, did);
|
||||
sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did);
|
||||
} else if (messageObject.messageOwner.media.geo instanceof TLRPC.TL_geoPoint) {
|
||||
sendMessage(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long, did);
|
||||
} else if (messageObject.messageOwner.media.phone_number != null) {
|
||||
|
@ -248,42 +316,42 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
}
|
||||
|
||||
public void sendMessage(TLRPC.User user, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, null, user, null, null, null, peer, false);
|
||||
sendMessage(null, 0, 0, null, null, null, user, null, null, null, peer, false, null);
|
||||
}
|
||||
|
||||
public void sendMessage(MessageObject message) {
|
||||
sendMessage(null, 0, 0, null, null, message, null, null, null, null, message.getDialogId(), true);
|
||||
sendMessage(null, 0, 0, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath);
|
||||
}
|
||||
|
||||
public void sendMessage(MessageObject message, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, message, null, null, null, null, peer, false);
|
||||
sendMessage(null, 0, 0, null, null, message, null, null, null, null, peer, false, message.messageOwner.attachPath);
|
||||
}
|
||||
|
||||
public void sendMessage(TLRPC.TL_document document, String originalPath, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, null, null, document, null, originalPath, peer, false);
|
||||
public void sendMessage(TLRPC.TL_document document, String originalPath, String path, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, null, null, document, null, originalPath, peer, false, path);
|
||||
}
|
||||
|
||||
public void sendMessage(String message, long peer) {
|
||||
sendMessage(message, 0, 0, null, null, null, null, null, null, null, peer, false);
|
||||
sendMessage(message, 0, 0, null, null, null, null, null, null, null, peer, false, null);
|
||||
}
|
||||
|
||||
public void sendMessage(double lat, double lon, long peer) {
|
||||
sendMessage(null, lat, lon, null, null, null, null, null, null, null, peer, false);
|
||||
sendMessage(null, lat, lon, null, null, null, null, null, null, null, peer, false, null);
|
||||
}
|
||||
|
||||
public void sendMessage(TLRPC.TL_photo photo, String originalPath, long peer) {
|
||||
sendMessage(null, 0, 0, photo, null, null, null, null, null, originalPath, peer, false);
|
||||
sendMessage(null, 0, 0, photo, null, null, null, null, null, originalPath, peer, false, null);
|
||||
}
|
||||
|
||||
public void sendMessage(TLRPC.TL_video video, String originalPath, long peer) {
|
||||
sendMessage(null, 0, 0, null, video, null, null, null, null, originalPath, peer, false);
|
||||
public void sendMessage(TLRPC.TL_video video, String originalPath, String path, long peer) {
|
||||
sendMessage(null, 0, 0, null, video, null, null, null, null, originalPath, peer, false, path);
|
||||
}
|
||||
|
||||
public void sendMessage(TLRPC.TL_audio audio, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, null, null, null, audio, null, peer, false);
|
||||
public void sendMessage(TLRPC.TL_audio audio, String path, long peer) {
|
||||
sendMessage(null, 0, 0, null, null, null, null, null, audio, null, peer, false, path);
|
||||
}
|
||||
|
||||
private void sendMessage(String message, double lat, double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry) {
|
||||
private int sendMessage(String message, double lat, double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path) {
|
||||
TLRPC.Message newMsg = null;
|
||||
int type = -1;
|
||||
if (retry) {
|
||||
|
@ -313,7 +381,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
} else {
|
||||
type = 3;
|
||||
video = (TLRPC.TL_video) newMsg.media.video;
|
||||
video.path = newMsg.attachPath;
|
||||
video.videoEditedInfo = newMsg.videoEditedInfo;
|
||||
}
|
||||
} else if (msgObj.type == 12 || msgObj.type == 13) {
|
||||
user = new TLRPC.TL_userRequest();
|
||||
|
@ -324,11 +392,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
type = 6;
|
||||
} else if (msgObj.type == 8 || msgObj.type == 9) {
|
||||
document = (TLRPC.TL_document) newMsg.media.document;
|
||||
document.path = newMsg.attachPath;
|
||||
type = 7;
|
||||
} else if (msgObj.type == 2) {
|
||||
audio = (TLRPC.TL_audio) newMsg.media.audio;
|
||||
audio.path = newMsg.attachPath;
|
||||
type = 8;
|
||||
}
|
||||
} else {
|
||||
|
@ -357,9 +423,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsg = new TLRPC.TL_message();
|
||||
newMsg.media = new TLRPC.TL_messageMediaVideo();
|
||||
newMsg.media.video = video;
|
||||
newMsg.videoEditedInfo = video.videoEditedInfo;
|
||||
type = 3;
|
||||
if (video.videoEditedInfo == null) {
|
||||
newMsg.message = "-1";
|
||||
newMsg.attachPath = video.path;
|
||||
} else {
|
||||
newMsg.message = video.videoEditedInfo.getString();
|
||||
}
|
||||
newMsg.attachPath = path;
|
||||
} else if (msgObj != null) {
|
||||
newMsg = new TLRPC.TL_messageForwarded();
|
||||
if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) {
|
||||
|
@ -394,14 +465,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsg.media.document = document;
|
||||
type = 7;
|
||||
newMsg.message = "-1";
|
||||
newMsg.attachPath = document.path;
|
||||
newMsg.attachPath = path;
|
||||
} else if (audio != null) {
|
||||
newMsg = new TLRPC.TL_message();
|
||||
newMsg.media = new TLRPC.TL_messageMediaAudio();
|
||||
newMsg.media.audio = audio;
|
||||
type = 8;
|
||||
newMsg.message = "-1";
|
||||
newMsg.attachPath = audio.path;
|
||||
newMsg.attachPath = path;
|
||||
}
|
||||
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
|
||||
newMsg.from_id = UserConfig.getClientUserId();
|
||||
|
@ -423,7 +494,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
if (high_id == 1) {
|
||||
if (currentChatInfo == null) {
|
||||
processSentMessage(newMsg.id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
sendToPeers = new ArrayList<TLRPC.InputUser>();
|
||||
for (TLRPC.TL_chatParticipant participant : currentChatInfo.participants) {
|
||||
|
@ -448,7 +519,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id);
|
||||
if (sendToUser == null) {
|
||||
processSentMessage(newMsg.id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (sendToUser instanceof TLRPC.TL_userForeign || sendToUser instanceof TLRPC.TL_userRequest) {
|
||||
sendToPeer = new TLRPC.TL_inputPeerForeign();
|
||||
|
@ -782,7 +853,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.messageOwner.id);
|
||||
processSentMessage(newMsgObj.messageOwner.id);
|
||||
return 0;
|
||||
}
|
||||
return newMsg != null ? newMsg.id : 0;
|
||||
}
|
||||
|
||||
private void performSendDelayedMessage(final DelayedMessage message) {
|
||||
|
@ -795,63 +868,78 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
FileLoader.getInstance().uploadFile(location, true, true);
|
||||
}
|
||||
} else if (message.type == 1) {
|
||||
if (message.sendRequest != null) {
|
||||
TLRPC.InputMedia media = null;
|
||||
if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) {
|
||||
media = ((TLRPC.TL_messages_sendMedia)message.sendRequest).media;
|
||||
} else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) {
|
||||
media = ((TLRPC.TL_messages_sendBroadcast)message.sendRequest).media;
|
||||
}
|
||||
if (media.thumb == null) {
|
||||
String location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
FileLoader.getInstance().uploadFile(location, false, true);
|
||||
} else {
|
||||
String location = message.videoLocation.path;
|
||||
if (message.videoLocation.videoEditedInfo != null) {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
if (location == null) {
|
||||
location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4";
|
||||
}
|
||||
putToDelayedMessages(location, message);
|
||||
if (message.videoLocation.estimatedSize) {
|
||||
MediaController.getInstance().scheduleVideoConvert(message.obj);
|
||||
} else {
|
||||
if (message.sendRequest != null) {
|
||||
TLRPC.InputMedia media = null;
|
||||
if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) {
|
||||
media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media;
|
||||
} else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) {
|
||||
media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media;
|
||||
}
|
||||
if (media.file == null) {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
if (location == null) {
|
||||
location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4";
|
||||
}
|
||||
putToDelayedMessages(location, message);
|
||||
if (message.obj.messageOwner.videoEditedInfo != null) {
|
||||
FileLoader.getInstance().uploadFile(location, false, false, message.videoLocation.size);
|
||||
} else {
|
||||
FileLoader.getInstance().uploadFile(location, false, false);
|
||||
}
|
||||
} else {
|
||||
String location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
FileLoader.getInstance().uploadFile(location, false, true);
|
||||
}
|
||||
} else {
|
||||
String location = message.videoLocation.path;
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
if (location == null) {
|
||||
location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.videoLocation.id + ".mp4";
|
||||
}
|
||||
putToDelayedMessages(location, message);
|
||||
if (message.videoLocation.estimatedSize) {
|
||||
if (message.videoLocation.videoEditedInfo != null) {
|
||||
FileLoader.getInstance().uploadFile(location, true, false, message.videoLocation.size);
|
||||
} else {
|
||||
FileLoader.getInstance().uploadFile(location, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (message.type == 2) {
|
||||
TLRPC.InputMedia media = null;
|
||||
if (message.sendRequest != null) {
|
||||
if (message.sendRequest instanceof TLRPC.TL_messages_sendMedia) {
|
||||
media = ((TLRPC.TL_messages_sendMedia)message.sendRequest).media;
|
||||
media = ((TLRPC.TL_messages_sendMedia) message.sendRequest).media;
|
||||
} else if (message.sendRequest instanceof TLRPC.TL_messages_sendBroadcast) {
|
||||
media = ((TLRPC.TL_messages_sendBroadcast)message.sendRequest).media;
|
||||
media = ((TLRPC.TL_messages_sendBroadcast) message.sendRequest).media;
|
||||
}
|
||||
if (message.sendRequest != null && media.thumb == null && message.location != null) {
|
||||
String location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
FileLoader.getInstance().uploadFile(location, false, true);
|
||||
} else {
|
||||
String location = message.documentLocation.path;
|
||||
if (media.file == null) {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
putToDelayedMessages(location, message);
|
||||
if (message.sendRequest != null) {
|
||||
FileLoader.getInstance().uploadFile(location, false, false);
|
||||
} else {
|
||||
FileLoader.getInstance().uploadFile(location, true, false);
|
||||
}
|
||||
} else if (media.thumb == null && message.location != null) {
|
||||
String location = FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
FileLoader.getInstance().uploadFile(location, false, true);
|
||||
}
|
||||
} else {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
putToDelayedMessages(location, message);
|
||||
FileLoader.getInstance().uploadFile(location, true, false);
|
||||
}
|
||||
} else if (message.type == 3) {
|
||||
String location = message.audioLocation.path;
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
putToDelayedMessages(location, message);
|
||||
if (message.sendRequest != null) {
|
||||
FileLoader.getInstance().uploadFile(location, false, true);
|
||||
|
@ -1187,7 +1275,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsg.media.video.access_hash = file.access_hash;
|
||||
newMsg.media.video.key = decryptedMessage.media.key;
|
||||
newMsg.media.video.iv = decryptedMessage.media.iv;
|
||||
newMsg.media.video.path = video.path;
|
||||
newMsg.media.video.mime_type = video.mime_type;
|
||||
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
|
||||
arr.add(newMsg);
|
||||
|
@ -1206,12 +1293,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsg.media.document.size = file.size;
|
||||
newMsg.media.document.key = decryptedMessage.media.key;
|
||||
newMsg.media.document.iv = decryptedMessage.media.iv;
|
||||
newMsg.media.document.path = document.path;
|
||||
newMsg.media.document.thumb = document.thumb;
|
||||
newMsg.media.document.dc_id = file.dc_id;
|
||||
|
||||
if (document.path != null && document.path.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) {
|
||||
File cacheFile = new File(document.path);
|
||||
if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) {
|
||||
File cacheFile = new File(newMsg.attachPath);
|
||||
File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.document);
|
||||
cacheFile.renameTo(cacheFile2);
|
||||
}
|
||||
|
@ -1233,7 +1319,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
newMsg.media.audio.dc_id = file.dc_id;
|
||||
newMsg.media.audio.key = decryptedMessage.media.key;
|
||||
newMsg.media.audio.iv = decryptedMessage.media.iv;
|
||||
newMsg.media.audio.path = audio.path;
|
||||
newMsg.media.audio.mime_type = audio.mime_type;
|
||||
|
||||
String fileName = audio.dc_id + "_" + audio.id + ".ogg";
|
||||
|
@ -1399,4 +1484,95 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
private void startConvert() throws Exception {
|
||||
IsoFile isoFile = new IsoFile(videoPath);
|
||||
TrackBox trackBox = (TrackBox) Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/avc1/../../../../../");
|
||||
AvcConfigurationBox avcConfigurationBox = (AvcConfigurationBox) Path.getPath(trackBox, "mdia/minf/stbl/stsd/avc1/avcC");
|
||||
avcConfigurationBox.parseDetails();
|
||||
|
||||
Movie movie = MovieCreator.build(videoPath);
|
||||
|
||||
List<Track> tracks = movie.getTracks();
|
||||
movie.setTracks(new LinkedList<Track>());
|
||||
|
||||
double startTime = 0;
|
||||
double endTime = 0;
|
||||
|
||||
for (Track track : tracks) {
|
||||
if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
|
||||
double duration = (double) track.getDuration() / (double) track.getTrackMetaData().getTimescale();
|
||||
startTime = correctTimeToSyncSample(track, videoTimelineView.getLeftProgress() * duration, false);
|
||||
endTime = videoTimelineView.getRightProgress() * duration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (Track track : tracks) {
|
||||
long currentSample = 0;
|
||||
double currentTime = 0;
|
||||
double lastTime = 0;
|
||||
long startSample = 0;
|
||||
long endSample = -1;
|
||||
|
||||
for (int i = 0; i < track.getSampleDurations().length; i++) {
|
||||
long delta = track.getSampleDurations()[i];
|
||||
if (currentTime > lastTime && currentTime <= startTime) {
|
||||
startSample = currentSample;
|
||||
}
|
||||
if (currentTime > lastTime && currentTime <= endTime) {
|
||||
endSample = currentSample;
|
||||
}
|
||||
lastTime = currentTime;
|
||||
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
|
||||
currentSample++;
|
||||
}
|
||||
movie.addTrack(new CroppedTrack(track, startSample, endSample));
|
||||
}
|
||||
Container out = new DefaultMp4Builder().build(movie);
|
||||
|
||||
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
|
||||
UserConfig.lastLocalId--;
|
||||
File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(cacheFile);
|
||||
FileChannel fc = fos.getChannel();
|
||||
out.writeContainer(fc);
|
||||
|
||||
fc.close();
|
||||
fos.close();
|
||||
if (delegate != null) {
|
||||
//delegate.didFinishedVideoConverting(cacheFile.getAbsolutePath());
|
||||
finishFragment();
|
||||
}
|
||||
}
|
||||
|
||||
private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
|
||||
double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
|
||||
long currentSample = 0;
|
||||
double currentTime = 0;
|
||||
for (int i = 0; i < track.getSampleDurations().length; i++) {
|
||||
long delta = track.getSampleDurations()[i];
|
||||
if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
|
||||
timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
|
||||
}
|
||||
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
|
||||
currentSample++;
|
||||
}
|
||||
double previous = 0;
|
||||
for (double timeOfSyncSample : timeOfSyncSamples) {
|
||||
if (timeOfSyncSample > cutHere) {
|
||||
if (next) {
|
||||
return timeOfSyncSample;
|
||||
} else {
|
||||
return previous;
|
||||
}
|
||||
}
|
||||
previous = timeOfSyncSample;
|
||||
}
|
||||
return timeOfSyncSamples[timeOfSyncSamples.length - 1];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -75,7 +75,14 @@ public class FileLoader {
|
|||
public File getDirectory(int type) {
|
||||
File dir = mediaDirs.get(type);
|
||||
if (dir == null && type != MEDIA_DIR_CACHE) {
|
||||
return mediaDirs.get(MEDIA_DIR_CACHE);
|
||||
dir = mediaDirs.get(MEDIA_DIR_CACHE);
|
||||
}
|
||||
try {
|
||||
if (!dir.isDirectory()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//don't promt
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
@ -588,6 +595,16 @@ public class FileLoader {
|
|||
return new File("");
|
||||
}
|
||||
|
||||
public static File getExistPathToAttach(TLObject attach) {
|
||||
File path = getInstance().getDirectory(MEDIA_DIR_CACHE);
|
||||
String fileName = getAttachFileName(attach);
|
||||
File attachPath = new File(path, fileName);
|
||||
if (attachPath.exists()) {
|
||||
return attachPath;
|
||||
}
|
||||
return getPathToAttach(attach);
|
||||
}
|
||||
|
||||
public static File getPathToAttach(TLObject attach) {
|
||||
File dir = null;
|
||||
if (attach instanceof TLRPC.Video) {
|
||||
|
|
|
@ -42,8 +42,9 @@ public class FileUploadOperation {
|
|||
private boolean isBigFile = false;
|
||||
private String fileKey;
|
||||
private int estimatedSize = 0;
|
||||
FileInputStream stream;
|
||||
MessageDigest mdEnc = null;
|
||||
private int uploadStartTime = 0;
|
||||
private FileInputStream stream;
|
||||
private MessageDigest mdEnc = null;
|
||||
|
||||
public static interface FileUploadOperationDelegate {
|
||||
public abstract void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile);
|
||||
|
@ -93,14 +94,16 @@ public class FileUploadOperation {
|
|||
remove(fileKey + "_ivc").commit();
|
||||
}
|
||||
|
||||
public void checkNewDataAvailable(final long finalSize) {
|
||||
protected void checkNewDataAvailable(final long finalSize) {
|
||||
Utilities.stageQueue.postRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (finalSize != 0) {
|
||||
if (estimatedSize != 0 && finalSize != 0) {
|
||||
estimatedSize = 0;
|
||||
totalFileSize = finalSize;
|
||||
totalPartsCount = (int) Math.ceil((float) totalFileSize / (float) uploadChunkSize);
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
|
||||
storeFileUploadInfo(preferences);
|
||||
}
|
||||
if (requestToken == 0) {
|
||||
startUploadRequest();
|
||||
|
@ -109,6 +112,20 @@ public class FileUploadOperation {
|
|||
});
|
||||
}
|
||||
|
||||
private void storeFileUploadInfo(SharedPreferences preferences) {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt(fileKey + "_time", uploadStartTime);
|
||||
editor.putLong(fileKey + "_size", totalFileSize);
|
||||
editor.putLong(fileKey + "_id", currentFileId);
|
||||
editor.remove(fileKey + "_uploaded");
|
||||
if (isEncrypted) {
|
||||
editor.putString(fileKey + "_iv", Utilities.bytesToHex(iv));
|
||||
editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange));
|
||||
editor.putString(fileKey + "_key", Utilities.bytesToHex(key));
|
||||
}
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
private void startUploadRequest() {
|
||||
if (state != 1) {
|
||||
return;
|
||||
|
@ -151,7 +168,7 @@ public class FileUploadOperation {
|
|||
fileKey = Utilities.MD5(uploadingFilePath + (isEncrypted ? "enc" : ""));
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("uploadinfo", Activity.MODE_PRIVATE);
|
||||
long fileSize = preferences.getLong(fileKey + "_size", 0);
|
||||
int currentTime = (int)(System.currentTimeMillis() / 1000);
|
||||
uploadStartTime = (int)(System.currentTimeMillis() / 1000);
|
||||
boolean rewrite = false;
|
||||
if (estimatedSize == 0 && fileSize == totalFileSize) {
|
||||
currentFileId = preferences.getLong(fileKey + "_id", 0);
|
||||
|
@ -170,9 +187,9 @@ public class FileUploadOperation {
|
|||
}
|
||||
}
|
||||
if (!rewrite && date != 0) {
|
||||
if (isBigFile && date < currentTime - 60 * 60 * 24) {
|
||||
if (isBigFile && date < uploadStartTime - 60 * 60 * 24) {
|
||||
date = 0;
|
||||
} else if (!isBigFile && date < currentTime - 60 * 60 * 1.5f) {
|
||||
} else if (!isBigFile && date < uploadStartTime - 60 * 60 * 1.5f) {
|
||||
date = 0;
|
||||
}
|
||||
if (date != 0) {
|
||||
|
@ -235,17 +252,7 @@ public class FileUploadOperation {
|
|||
}
|
||||
currentFileId = Utilities.random.nextLong();
|
||||
if (estimatedSize == 0) {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt(fileKey + "_time", currentTime);
|
||||
editor.putLong(fileKey + "_size", totalFileSize);
|
||||
editor.putLong(fileKey + "_id", currentFileId);
|
||||
editor.remove(fileKey + "_uploaded");
|
||||
if (isEncrypted) {
|
||||
editor.putString(fileKey + "_iv", Utilities.bytesToHex(iv));
|
||||
editor.putString(fileKey + "_ivc", Utilities.bytesToHex(ivChange));
|
||||
editor.putString(fileKey + "_key", Utilities.bytesToHex(key));
|
||||
}
|
||||
editor.commit();
|
||||
storeFileUploadInfo(preferences);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
package org.telegram.messenger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class TLRPC {
|
||||
|
@ -8539,6 +8540,7 @@ public class TLRPC {
|
|||
public int local_id = 0;
|
||||
public long dialog_id;
|
||||
public int ttl;
|
||||
public VideoEditedInfo videoEditedInfo = null;
|
||||
}
|
||||
|
||||
public static class TL_messageForwarded extends Message {
|
||||
|
@ -8559,9 +8561,13 @@ public class TLRPC {
|
|||
if (id < 0) {
|
||||
fwd_msg_id = stream.readInt32();
|
||||
}
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.equals("-1"))) {
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
|
||||
attachPath = stream.readString();
|
||||
}
|
||||
if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) {
|
||||
videoEditedInfo = new VideoEditedInfo();
|
||||
videoEditedInfo.parseString(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
|
@ -8595,9 +8601,13 @@ public class TLRPC {
|
|||
date = stream.readInt32();
|
||||
message = stream.readString();
|
||||
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.equals("-1"))) {
|
||||
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
|
||||
attachPath = stream.readString();
|
||||
}
|
||||
if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) {
|
||||
videoEditedInfo = new VideoEditedInfo();
|
||||
videoEditedInfo.parseString(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeToStream(AbsSerializedData stream) {
|
||||
|
@ -8954,6 +8964,46 @@ public class TLRPC {
|
|||
}
|
||||
}
|
||||
|
||||
public static class VideoEditedInfo {
|
||||
public long startTime;
|
||||
public long endTime;
|
||||
public int rotationValue;
|
||||
public int originalWidth;
|
||||
public int originalHeight;
|
||||
public int resultWidth;
|
||||
public int resultHeight;
|
||||
public int bitrate;
|
||||
public String originalPath;
|
||||
|
||||
public String getString() {
|
||||
return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalPath);
|
||||
}
|
||||
|
||||
public void parseString(String string) {
|
||||
if (string.length() < 6) {
|
||||
return;
|
||||
}
|
||||
String args[] = string.split("_");
|
||||
if (args.length >= 10) {
|
||||
startTime = Long.parseLong(args[1]);
|
||||
endTime = Long.parseLong(args[2]);
|
||||
rotationValue = Integer.parseInt(args[3]);
|
||||
originalWidth = Integer.parseInt(args[4]);
|
||||
originalHeight = Integer.parseInt(args[5]);
|
||||
bitrate = Integer.parseInt(args[6]);
|
||||
resultWidth = Integer.parseInt(args[7]);
|
||||
resultHeight = Integer.parseInt(args[8]);
|
||||
for (int a = 9; a < args.length; a++) {
|
||||
if (originalPath == null) {
|
||||
originalPath = args[a];
|
||||
} else {
|
||||
originalPath += "_" + args[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Video extends TLObject {
|
||||
public long id;
|
||||
public long access_hash;
|
||||
|
@ -8967,10 +9017,9 @@ public class TLRPC {
|
|||
public int dc_id;
|
||||
public int w;
|
||||
public int h;
|
||||
public String path;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
public boolean estimatedSize;
|
||||
public VideoEditedInfo videoEditedInfo = null;
|
||||
}
|
||||
|
||||
public static class Document extends TLObject {
|
||||
|
@ -8983,7 +9032,6 @@ public class TLRPC {
|
|||
public int size;
|
||||
public PhotoSize thumb;
|
||||
public int dc_id;
|
||||
public String path;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
@ -8997,7 +9045,6 @@ public class TLRPC {
|
|||
public String mime_type;
|
||||
public int size;
|
||||
public int dc_id;
|
||||
public String path;
|
||||
public byte[] key;
|
||||
public byte[] iv;
|
||||
}
|
||||
|
|
|
@ -564,17 +564,17 @@ public class ChatBaseCell extends BaseCell {
|
|||
boolean drawError = false;
|
||||
boolean isBroadcast = (int)(currentMessageObject.getDialogId() >> 32) == 1;
|
||||
|
||||
if (currentMessageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (currentMessageObject.isSending()) {
|
||||
drawCheck1 = false;
|
||||
drawCheck2 = false;
|
||||
drawClock = true;
|
||||
drawError = false;
|
||||
} else if (currentMessageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
} else if (currentMessageObject.isSendError()) {
|
||||
drawCheck1 = false;
|
||||
drawCheck2 = false;
|
||||
drawClock = false;
|
||||
drawError = true;
|
||||
} else if (currentMessageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT) {
|
||||
} else if (currentMessageObject.isSent()) {
|
||||
if (!currentMessageObject.isUnread()) {
|
||||
drawCheck1 = true;
|
||||
drawCheck2 = true;
|
||||
|
|
|
@ -52,8 +52,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
private static Drawable videoIconDrawable;
|
||||
private static Drawable docMenuInDrawable;
|
||||
private static Drawable docMenuOutDrawable;
|
||||
private static Drawable[] buttonStatesDrawables = new Drawable[4];
|
||||
private static Drawable[][] buttonStatesDrawablesDoc = new Drawable[2][2];
|
||||
private static Drawable[] buttonStatesDrawables = new Drawable[5];
|
||||
private static Drawable[][] buttonStatesDrawablesDoc = new Drawable[3][2];
|
||||
private static TextPaint infoPaint;
|
||||
private static MessageObject lastDownloadedGifMessage = null;
|
||||
private static TextPaint namePaint;
|
||||
|
@ -114,10 +114,13 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
buttonStatesDrawables[1] = getResources().getDrawable(R.drawable.photocancel);
|
||||
buttonStatesDrawables[2] = getResources().getDrawable(R.drawable.photogif);
|
||||
buttonStatesDrawables[3] = getResources().getDrawable(R.drawable.playvideo);
|
||||
buttonStatesDrawables[4] = getResources().getDrawable(R.drawable.photopause);
|
||||
buttonStatesDrawablesDoc[0][0] = getResources().getDrawable(R.drawable.docload_b);
|
||||
buttonStatesDrawablesDoc[1][0] = getResources().getDrawable(R.drawable.doccancel_b);
|
||||
buttonStatesDrawablesDoc[2][0] = getResources().getDrawable(R.drawable.docpause_b);
|
||||
buttonStatesDrawablesDoc[0][1] = getResources().getDrawable(R.drawable.docload_g);
|
||||
buttonStatesDrawablesDoc[1][1] = getResources().getDrawable(R.drawable.doccancel_g);
|
||||
buttonStatesDrawablesDoc[2][1] = getResources().getDrawable(R.drawable.docpause_g);
|
||||
videoIconDrawable = getResources().getDrawable(R.drawable.ic_video);
|
||||
docMenuInDrawable = getResources().getDrawable(R.drawable.doc_actions_b);
|
||||
docMenuOutDrawable = getResources().getDrawable(R.drawable.doc_actions_g);
|
||||
|
@ -172,7 +175,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
float y = event.getY();
|
||||
|
||||
boolean result = false;
|
||||
int side = AndroidUtilities.dp(44);
|
||||
int side = AndroidUtilities.dp(48);
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (delegate == null || delegate.canPerformActions()) {
|
||||
if (buttonState != -1 && x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
|
||||
|
@ -321,7 +324,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
buttonState = 1;
|
||||
invalidate();
|
||||
} else if (buttonState == 1) {
|
||||
if (currentMessageObject.isOut() && currentMessageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
|
||||
if (delegate != null) {
|
||||
delegate.didPressedCancelSendButton(this);
|
||||
}
|
||||
|
@ -616,7 +619,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
if (fileName == null) {
|
||||
return;
|
||||
}
|
||||
if (currentMessageObject.isOut() && currentMessageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
|
||||
if (currentMessageObject.messageOwner.attachPath != null) {
|
||||
MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this);
|
||||
progressVisible = true;
|
||||
|
@ -709,7 +712,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
}
|
||||
|
||||
private void invalidateProgress() {
|
||||
int offset = AndroidUtilities.dp(1);
|
||||
int offset = AndroidUtilities.dp(2);
|
||||
invalidate((int)progressRect.left - offset, (int)progressRect.top - offset, (int)progressRect.right + offset * 2, (int)progressRect.bottom + offset * 2);
|
||||
}
|
||||
|
||||
|
@ -742,10 +745,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
}
|
||||
}
|
||||
photoImage.setImageCoords(x, AndroidUtilities.dp(7), photoWidth, photoHeight);
|
||||
int size = AndroidUtilities.dp(44);
|
||||
int size = AndroidUtilities.dp(48);
|
||||
buttonX = (int)(x + (photoWidth - size) / 2.0f);
|
||||
buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f);
|
||||
progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(43), buttonY + AndroidUtilities.dp(43));
|
||||
progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(47), buttonY + AndroidUtilities.dp(47));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -783,7 +786,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
|
||||
if (buttonState == -1) {
|
||||
Drawable drawable = currentMessageObject.isOut() ? placeholderDocOutDrawable : placeholderDocInDrawable;
|
||||
setDrawableBounds(drawable, photoImage.getImageX() + AndroidUtilities.dp(27), photoImage.getImageY() + AndroidUtilities.dp(27));
|
||||
setDrawableBounds(drawable, photoImage.getImageX() + AndroidUtilities.dp(19), photoImage.getImageY() + AndroidUtilities.dp(19));
|
||||
drawable.draw(canvas);
|
||||
}
|
||||
if (currentMessageObject.isOut()) {
|
||||
|
@ -802,10 +805,18 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
|
|||
if (buttonState >= 0 && buttonState < 4) {
|
||||
Drawable currentButtonDrawable = null;
|
||||
if (currentMessageObject.type == 9 && !imageDrawn) {
|
||||
if (buttonState == 1 && !currentMessageObject.isSending()) {
|
||||
currentButtonDrawable = buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0];
|
||||
} else {
|
||||
currentButtonDrawable = buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOut() ? 1 : 0];
|
||||
}
|
||||
} else {
|
||||
if (buttonState == 1 && !currentMessageObject.isSending()) {
|
||||
currentButtonDrawable = buttonStatesDrawables[4];
|
||||
} else {
|
||||
currentButtonDrawable = buttonStatesDrawables[buttonState];
|
||||
}
|
||||
}
|
||||
setDrawableBounds(currentButtonDrawable, buttonX, buttonY);
|
||||
currentButtonDrawable.draw(canvas);
|
||||
}
|
||||
|
|
|
@ -528,18 +528,18 @@ public class DialogCell extends BaseCell {
|
|||
}
|
||||
|
||||
if (message.isFromMe() && message.isOut()) {
|
||||
if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (message.isSending()) {
|
||||
drawCheck1 = false;
|
||||
drawCheck2 = false;
|
||||
drawClock = true;
|
||||
drawError = false;
|
||||
} else if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
} else if (message.isSendError()) {
|
||||
drawCheck1 = false;
|
||||
drawCheck2 = false;
|
||||
drawClock = false;
|
||||
drawError = true;
|
||||
drawCount = false;
|
||||
} else if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT) {
|
||||
} else if (message.isSent()) {
|
||||
if (!message.isUnread()) {
|
||||
drawCheck1 = true;
|
||||
drawCheck2 = true;
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.content.res.Configuration;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.net.Uri;
|
||||
|
@ -1072,9 +1073,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
|
||||
private int getMessageType(MessageObject messageObject) {
|
||||
if (currentEncryptedChat == null) {
|
||||
boolean isBroadcastError = isBraodcast && messageObject.messageOwner.id <= 0 && messageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
boolean isBroadcastError = isBraodcast && messageObject.messageOwner.id <= 0 && messageObject.isSendError();
|
||||
if (!isBraodcast && messageObject.messageOwner.id <= 0 && messageObject.isOut() || isBroadcastError) {
|
||||
if (messageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
if (messageObject.isSendError()) {
|
||||
if (!(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
|
||||
return 0;
|
||||
} else {
|
||||
|
@ -1128,13 +1129,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
} else {
|
||||
if (messageObject.type == 6) {
|
||||
return -1;
|
||||
} else if (messageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
} else if (messageObject.isSendError()) {
|
||||
if (!(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
} else if (messageObject.type == 10 || messageObject.type == 11 || messageObject.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
} else if (messageObject.type == 10 || messageObject.type == 11 || messageObject.isSending()) {
|
||||
if (messageObject.messageOwner.id == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1243,6 +1244,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}
|
||||
|
||||
CharSequence printString = MessagesController.getInstance().printingStrings.get(dialog_id);
|
||||
if (printString != null) {
|
||||
printString = TextUtils.replace(printString, new String[]{"..."}, new String[]{""});
|
||||
}
|
||||
if (printString == null || printString.length() == 0) {
|
||||
lastPrintString = null;
|
||||
setTypingAnimation(false);
|
||||
|
@ -1362,7 +1366,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
fragment.setDelegate(this);
|
||||
presentFragment(fragment);
|
||||
} else {
|
||||
processSendingVideo(videoPath, null, 0, 0, 0, 0);
|
||||
processSendingVideo(videoPath, 0, 0, 0, 0, null);
|
||||
}
|
||||
} else if (requestCode == 21) {
|
||||
if (data == null || data.getData() == null) {
|
||||
|
@ -1385,13 +1389,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}
|
||||
|
||||
@Override
|
||||
public void didStartVideoConverting(String videoPath, String originalPath, long esimatedSize, int duration, int width, int height) {
|
||||
processSendingVideo(videoPath, originalPath, esimatedSize, duration, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didAppenedVideoData(String videoPath, long finalSize) {
|
||||
FileLoader.getInstance().checkUploadNewDataAvailable(videoPath, currentEncryptedChat != null, finalSize);
|
||||
public void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration) {
|
||||
TLRPC.VideoEditedInfo videoEditedInfo = new TLRPC.VideoEditedInfo();
|
||||
videoEditedInfo.startTime = startTime;
|
||||
videoEditedInfo.endTime = endTime;
|
||||
videoEditedInfo.rotationValue = rotationValue;
|
||||
videoEditedInfo.originalWidth = originalWidth;
|
||||
videoEditedInfo.originalHeight = originalHeight;
|
||||
videoEditedInfo.bitrate = bitrate;
|
||||
videoEditedInfo.resultWidth = resultWidth;
|
||||
videoEditedInfo.resultHeight = resultHeight;
|
||||
videoEditedInfo.originalPath = videoPath;
|
||||
processSendingVideo(videoPath, estimatedSize, estimatedDuration, resultWidth, resultHeight, videoEditedInfo);
|
||||
}
|
||||
|
||||
private void showAttachmentError() {
|
||||
|
@ -1525,7 +1534,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}).start();
|
||||
}
|
||||
|
||||
private void processSendingDocumentInternal(String path, String originalPath) {
|
||||
private void processSendingDocumentInternal(final String path, String originalPath) {
|
||||
if (path == null || path.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1586,14 +1595,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
document.thumb.type = "s";
|
||||
}
|
||||
}
|
||||
document.path = path;
|
||||
|
||||
final TLRPC.TL_document documentFinal = document;
|
||||
final String originalPathFinal = originalPath;
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, dialog_id);
|
||||
SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, path, dialog_id);
|
||||
if (chatListView != null) {
|
||||
chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop());
|
||||
}
|
||||
|
@ -1629,29 +1637,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
}).start();
|
||||
}
|
||||
|
||||
public void processSendingVideo(final String videoPath, final String originalFile, final long estimatedSize, final int duration, final int width, final int height) {
|
||||
public void processSendingVideo(final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final TLRPC.VideoEditedInfo videoEditedInfo) {
|
||||
if (videoPath == null || videoPath.length() == 0) {
|
||||
return;
|
||||
}
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String originalPath = null;
|
||||
if (originalFile != null) {
|
||||
originalPath = originalFile;
|
||||
} else {
|
||||
originalPath = videoPath;
|
||||
}
|
||||
String path = videoPath;
|
||||
String originalPath = videoPath;
|
||||
File temp = new File(originalPath);
|
||||
originalPath += temp.length() + "_" + temp.lastModified();
|
||||
TLRPC.TL_video video = null;// (TLRPC.TL_video)MessagesStorage.getInstance().getSentFile(originalPath, currentEncryptedChat == null ? 2 : 5);
|
||||
if (video == null) {
|
||||
Bitmap thumb = null;
|
||||
if (originalFile != null) {
|
||||
thumb = ThumbnailUtils.createVideoThumbnail(originalFile, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
} else {
|
||||
thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
if (videoEditedInfo != null) {
|
||||
originalPath += duration + "_" + videoEditedInfo.startTime + "_" + videoEditedInfo.endTime;
|
||||
}
|
||||
TLRPC.TL_video video = (TLRPC.TL_video)MessagesStorage.getInstance().getSentFile(originalPath, currentEncryptedChat == null ? 2 : 5);
|
||||
if (video == null) {
|
||||
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
|
||||
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, 90, 90, 55, currentEncryptedChat != null);
|
||||
if (size == null) {
|
||||
return;
|
||||
|
@ -1662,20 +1664,44 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
video.caption = "";
|
||||
video.mime_type = "video/mp4";
|
||||
video.id = 0;
|
||||
if (estimatedSize != 0) {
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
if (videoEditedInfo != null) {
|
||||
video.duration = (int)(duration / 1000);
|
||||
if (videoEditedInfo.rotationValue == 90 || videoEditedInfo.rotationValue == 270) {
|
||||
video.w = height;
|
||||
video.h = width;
|
||||
} else {
|
||||
video.w = width;
|
||||
video.h = height;
|
||||
}
|
||||
video.size = (int)estimatedSize;
|
||||
video.videoEditedInfo = videoEditedInfo;
|
||||
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
|
||||
UserConfig.lastLocalId--;
|
||||
File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
UserConfig.saveConfig(false);
|
||||
path = cacheFile.getAbsolutePath();
|
||||
} else {
|
||||
if (temp != null && temp.exists()) {
|
||||
video.size = (int) temp.length();
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 10) {
|
||||
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
||||
mediaMetadataRetriever.setDataSource(videoPath);
|
||||
String width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
|
||||
if (width != null) {
|
||||
video.w = Integer.parseInt(width);
|
||||
}
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
if (duration != 0) {
|
||||
video.duration = duration / 1000;
|
||||
video.w = width;
|
||||
video.h = height;
|
||||
video.estimatedSize = true;
|
||||
String height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
|
||||
if (height != null) {
|
||||
video.h = Integer.parseInt(height);
|
||||
}
|
||||
String duration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||
if (duration != null) {
|
||||
video.duration = (int) Math.ceil(Long.parseLong(duration) / 1000.0f);
|
||||
}
|
||||
mediaMetadataRetriever.release();
|
||||
} else {
|
||||
MediaPlayer mp = MediaPlayer.create(ApplicationLoader.applicationContext, Uri.fromFile(new File(videoPath)));
|
||||
if (mp == null) {
|
||||
|
@ -1687,14 +1713,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
mp.release();
|
||||
}
|
||||
}
|
||||
video.path = videoPath;
|
||||
}
|
||||
|
||||
final TLRPC.TL_video videoFinal = video;
|
||||
final String originalPathFinal = originalPath;
|
||||
final String finalPath = path;
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SendMessagesHelper.getInstance().sendMessage(videoFinal, originalPathFinal, dialog_id);
|
||||
SendMessagesHelper.getInstance().sendMessage(videoFinal, originalPathFinal, finalPath, dialog_id);
|
||||
if (chatListView != null) {
|
||||
chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop());
|
||||
}
|
||||
|
@ -1989,7 +2016,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
if (currentEncryptedChat != null && obj.messageOwner.action != null && obj.messageOwner.action instanceof TLRPC.TL_messageActionTTLChange && timerButton != null) {
|
||||
timerButton.setTime(obj.messageOwner.action.ttl);
|
||||
}
|
||||
if (obj.isOut() && obj.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (obj.isOut() && obj.isSending()) {
|
||||
scrollToLastMessage();
|
||||
return;
|
||||
}
|
||||
|
@ -3300,10 +3327,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
@Override
|
||||
public void didPressedImage(ChatMediaCell cell) {
|
||||
MessageObject message = cell.getMessageObject();
|
||||
if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
if (message.isSendError()) {
|
||||
createMenu(cell, false);
|
||||
return;
|
||||
} else if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
} else if (message.isSending()) {
|
||||
return;
|
||||
}
|
||||
if (message.type == 1) {
|
||||
|
@ -3553,17 +3580,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
|||
|
||||
if (message.isFromMe()) {
|
||||
if (halfCheckImage != null) {
|
||||
if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENDING) {
|
||||
if (message.isSending()) {
|
||||
checkImage.setVisibility(View.INVISIBLE);
|
||||
halfCheckImage.setImageResource(R.drawable.msg_clock);
|
||||
halfCheckImage.setVisibility(View.VISIBLE);
|
||||
} else if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
} else if (message.isSendError()) {
|
||||
halfCheckImage.setVisibility(View.VISIBLE);
|
||||
halfCheckImage.setImageResource(R.drawable.msg_warning);
|
||||
if (checkImage != null) {
|
||||
checkImage.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else if (message.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT) {
|
||||
} else if (message.isSent()) {
|
||||
if (!message.messageOwner.unread) {
|
||||
halfCheckImage.setVisibility(View.VISIBLE);
|
||||
checkImage.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -115,8 +115,36 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
shadowTablet.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (!actionBarLayout.fragmentsStack.isEmpty() && event.getAction() == MotionEvent.ACTION_UP) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
int location[] = new int[2];
|
||||
layersActionBarLayout.getLocationOnScreen(location);
|
||||
int viewX = location[0];
|
||||
int viewY = location[1];
|
||||
|
||||
if (x > viewX && x < viewX + layersActionBarLayout.getWidth() && y > viewY && y < viewY + layersActionBarLayout.getHeight()) {
|
||||
return false;
|
||||
} else {
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
shadowTablet.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
RelativeLayout launchLayout = (RelativeLayout)findViewById(R.id.launch_layout);
|
||||
|
@ -514,7 +542,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
Bundle args = new Bundle();
|
||||
args.putInt("user_id", push_user_id);
|
||||
ChatActivity fragment = new ChatActivity(args);
|
||||
if (actionBarLayout.presentFragment(fragment, false, true)) {
|
||||
if (actionBarLayout.presentFragment(fragment, false, true, true)) {
|
||||
pushOpened = true;
|
||||
}
|
||||
}
|
||||
|
@ -522,14 +550,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
Bundle args = new Bundle();
|
||||
args.putInt("chat_id", push_chat_id);
|
||||
ChatActivity fragment = new ChatActivity(args);
|
||||
if (actionBarLayout.presentFragment(fragment, false, true)) {
|
||||
if (actionBarLayout.presentFragment(fragment, false, true, true)) {
|
||||
pushOpened = true;
|
||||
}
|
||||
} else if (push_enc_id != 0) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("enc_id", push_enc_id);
|
||||
ChatActivity fragment = new ChatActivity(args);
|
||||
if (actionBarLayout.presentFragment(fragment, false, true)) {
|
||||
if (actionBarLayout.presentFragment(fragment, false, true, true)) {
|
||||
pushOpened = true;
|
||||
}
|
||||
} else if (showDialogsList) {
|
||||
|
@ -541,23 +569,36 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
isNew = false;
|
||||
}
|
||||
if (videoPath != null || photoPathsArray != null || sendingText != null || documentsPathsArray != null || contactsToSend != null) {
|
||||
if (!AndroidUtilities.isTablet()) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
|
||||
}
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean("onlySelect", true);
|
||||
args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo));
|
||||
MessagesActivity fragment = new MessagesActivity(args);
|
||||
fragment.setDelegate(this);
|
||||
actionBarLayout.presentFragment(fragment, false, true);
|
||||
actionBarLayout.presentFragment(fragment, false, true, true);
|
||||
pushOpened = true;
|
||||
if (PhotoViewer.getInstance().isVisible()) {
|
||||
PhotoViewer.getInstance().closePhoto(true);
|
||||
}
|
||||
}
|
||||
if (open_settings != 0) {
|
||||
actionBarLayout.presentFragment(new SettingsActivity(), false, true);
|
||||
actionBarLayout.presentFragment(new SettingsActivity(), false, true, true);
|
||||
pushOpened = true;
|
||||
}
|
||||
if (!pushOpened && !isNew) {
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
if (UserConfig.isClientActivated()) {
|
||||
if (actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
actionBarLayout.addFragmentToStack(new MessagesActivity(null));
|
||||
}
|
||||
} else {
|
||||
if (layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
layersActionBarLayout.addFragmentToStack(new LoginActivity());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
if (!UserConfig.isClientActivated()) {
|
||||
actionBarLayout.addFragmentToStack(new LoginActivity());
|
||||
|
@ -565,6 +606,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
actionBarLayout.addFragmentToStack(new MessagesActivity(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
actionBarLayout.showLastFragment();
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
layersActionBarLayout.showLastFragment();
|
||||
|
@ -589,7 +631,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean("scrollToTopOnResume", true);
|
||||
if (!AndroidUtilities.isTablet()) {
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
|
||||
}
|
||||
if (lower_part != 0) {
|
||||
if (high_id == 1) {
|
||||
args.putInt("chat_id", lower_part);
|
||||
|
@ -606,7 +650,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
ChatActivity fragment = new ChatActivity(args);
|
||||
actionBarLayout.presentFragment(fragment, true);
|
||||
if (videoPath != null) {
|
||||
fragment.processSendingVideo(videoPath, null, 0, 0, 0, 0);
|
||||
fragment.processSendingVideo(videoPath, 0, 0, 0, 0, null);
|
||||
}
|
||||
if (sendingText != null) {
|
||||
fragment.processSendingText(sendingText);
|
||||
|
@ -647,7 +691,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
}
|
||||
|
||||
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation) {
|
||||
return actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
|
||||
return actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, true);
|
||||
}
|
||||
|
||||
public void needLayout() {
|
||||
|
@ -680,18 +724,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
relativeLayoutParams.leftMargin = leftWidth;
|
||||
buttonLayoutTablet.setLayoutParams(relativeLayoutParams);
|
||||
|
||||
if (AndroidUtilities.isSmallTablet() && mainFragmentsStack.size() == 2) {
|
||||
BaseFragment chatFragment = mainFragmentsStack.get(1);
|
||||
mainFragmentsStack.remove(1);
|
||||
if (AndroidUtilities.isSmallTablet() && actionBarLayout.fragmentsStack.size() == 2) {
|
||||
BaseFragment chatFragment = actionBarLayout.fragmentsStack.get(1);
|
||||
actionBarLayout.fragmentsStack.remove(1);
|
||||
actionBarLayout.showLastFragment();
|
||||
rightFragmentsStack.add(chatFragment);
|
||||
rightActionBarLayout.fragmentsStack.add(chatFragment);
|
||||
rightActionBarLayout.showLastFragment();
|
||||
}
|
||||
|
||||
rightActionBarLayout.setVisibility(rightFragmentsStack.isEmpty() ? View.GONE : View.VISIBLE);
|
||||
buttonLayoutTablet.setVisibility(!mainFragmentsStack.isEmpty() && rightFragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
backgroundTablet.setVisibility(rightFragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
shadowTabletSide.setVisibility(!mainFragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
rightActionBarLayout.setVisibility(rightActionBarLayout.fragmentsStack.isEmpty() ? View.GONE : View.VISIBLE);
|
||||
buttonLayoutTablet.setVisibility(!actionBarLayout.fragmentsStack.isEmpty() && rightActionBarLayout.fragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
backgroundTablet.setVisibility(rightActionBarLayout.fragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
shadowTabletSide.setVisibility(!actionBarLayout.fragmentsStack.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
tabletFullSize = true;
|
||||
|
||||
|
@ -702,13 +746,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
|
||||
shadowTabletSide.setVisibility(View.GONE);
|
||||
rightActionBarLayout.setVisibility(View.GONE);
|
||||
backgroundTablet.setVisibility(View.GONE);
|
||||
backgroundTablet.setVisibility(!actionBarLayout.fragmentsStack.isEmpty() ? View.GONE : View.VISIBLE);
|
||||
buttonLayoutTablet.setVisibility(View.GONE);
|
||||
|
||||
if (rightFragmentsStack.size() == 1) {
|
||||
BaseFragment chatFragment = rightFragmentsStack.get(0);
|
||||
rightFragmentsStack.remove(0);
|
||||
actionBarLayout.presentFragment(chatFragment, false, true);
|
||||
if (rightActionBarLayout.fragmentsStack.size() == 1) {
|
||||
BaseFragment chatFragment = rightActionBarLayout.fragmentsStack.get(0);
|
||||
rightActionBarLayout.fragmentsStack.remove(0);
|
||||
actionBarLayout.presentFragment(chatFragment, false, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -831,8 +875,22 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
protected void onSaveInstanceState(Bundle outState) {
|
||||
try {
|
||||
super.onSaveInstanceState(outState);
|
||||
BaseFragment lastFragment = null;
|
||||
if (AndroidUtilities.isTablet()) {
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
lastFragment = layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1);
|
||||
} else if (!rightActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
lastFragment = rightActionBarLayout.fragmentsStack.get(rightActionBarLayout.fragmentsStack.size() - 1);
|
||||
} else if (!actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
lastFragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
|
||||
}
|
||||
} else {
|
||||
if (!actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
BaseFragment lastFragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
|
||||
lastFragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastFragment != null) {
|
||||
Bundle args = lastFragment.getArguments();
|
||||
if (lastFragment instanceof ChatActivity && args != null) {
|
||||
outState.putBundle("args", args);
|
||||
|
@ -943,35 +1001,52 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
MessagesActivity messagesActivity = (MessagesActivity)fragment;
|
||||
if (messagesActivity.getDelegate() == null && layout != actionBarLayout) {
|
||||
actionBarLayout.removeAllFragments();
|
||||
actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
|
||||
actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, false);
|
||||
layersActionBarLayout.removeAllFragments();
|
||||
layersActionBarLayout.setVisibility(View.GONE);
|
||||
if (!tabletFullSize) {
|
||||
shadowTabletSide.setVisibility(View.VISIBLE);
|
||||
if (rightFragmentsStack.isEmpty()) {
|
||||
if (rightActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
buttonLayoutTablet.setVisibility(View.VISIBLE);
|
||||
backgroundTablet.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (fragment instanceof ChatActivity) {
|
||||
}
|
||||
if (fragment instanceof ChatActivity) {
|
||||
if (!tabletFullSize && layout != rightActionBarLayout) {
|
||||
rightActionBarLayout.setVisibility(View.VISIBLE);
|
||||
buttonLayoutTablet.setVisibility(View.GONE);
|
||||
backgroundTablet.setVisibility(View.GONE);
|
||||
rightActionBarLayout.removeAllFragments();
|
||||
rightActionBarLayout.presentFragment(fragment, removeLast, true);
|
||||
if (removeLast) {
|
||||
layout.closeLastFragment(true);
|
||||
rightActionBarLayout.presentFragment(fragment, removeLast, true, false);
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
return false;
|
||||
} else if (tabletFullSize && layout != actionBarLayout) {
|
||||
actionBarLayout.presentFragment(fragment, false, forceWithoutAnimation);
|
||||
if (removeLast) {
|
||||
layout.closeLastFragment(true);
|
||||
actionBarLayout.presentFragment(fragment, actionBarLayout.fragmentsStack.size() > 1, forceWithoutAnimation, false);
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
}
|
||||
} else if (layout != layersActionBarLayout) {
|
||||
layersActionBarLayout.setVisibility(View.VISIBLE);
|
||||
|
@ -983,7 +1058,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
} else {
|
||||
shadowTablet.setBackgroundColor(0x7F000000);
|
||||
}
|
||||
layersActionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
|
||||
layersActionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1004,7 +1079,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
layersActionBarLayout.setVisibility(View.GONE);
|
||||
if (!tabletFullSize) {
|
||||
shadowTabletSide.setVisibility(View.VISIBLE);
|
||||
if (rightFragmentsStack.isEmpty()) {
|
||||
if (rightActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
buttonLayoutTablet.setVisibility(View.VISIBLE);
|
||||
backgroundTablet.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
@ -1018,9 +1093,23 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
backgroundTablet.setVisibility(View.GONE);
|
||||
rightActionBarLayout.removeAllFragments();
|
||||
rightActionBarLayout.addFragmentToStack(fragment);
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
return false;
|
||||
} else if (tabletFullSize && layout != actionBarLayout) {
|
||||
actionBarLayout.addFragmentToStack(fragment);
|
||||
if (!layersActionBarLayout.fragmentsStack.isEmpty()) {
|
||||
for (int a = 0; a < layersActionBarLayout.fragmentsStack.size() - 1; a++) {
|
||||
layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.fragmentsStack.get(0));
|
||||
a--;
|
||||
}
|
||||
layersActionBarLayout.closeLastFragment(true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if (layout != layersActionBarLayout) {
|
||||
|
@ -1054,6 +1143,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
|
|||
buttonLayoutTablet.setVisibility(View.VISIBLE);
|
||||
backgroundTablet.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (layout == layersActionBarLayout && actionBarLayout.fragmentsStack.isEmpty()) {
|
||||
onFinish();
|
||||
finish();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (layout.fragmentsStack.size() <= 1) {
|
||||
|
|
|
@ -288,6 +288,7 @@ public class PhotoCropActivity extends BaseFragment {
|
|||
|
||||
@Override
|
||||
public boolean onFragmentCreate() {
|
||||
swipeBackEnabled = false;
|
||||
String photoPath = getArguments().getString("photoPath");
|
||||
Uri photoUri = getArguments().getParcelable("photoUri");
|
||||
if (photoPath == null && photoUri == null) {
|
||||
|
|
|
@ -645,7 +645,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
|||
return;
|
||||
}
|
||||
MessageObject obj = imagesArr.get(currentIndex);
|
||||
if (obj.messageOwner.send_state == MessageObject.MESSAGE_SEND_STATE_SENT) {
|
||||
if (obj.isSent()) {
|
||||
ArrayList<Integer> arr = new ArrayList<Integer>();
|
||||
arr.add(obj.messageOwner.id);
|
||||
MessagesController.getInstance().deleteMessages(arr, null, null);
|
||||
|
@ -1061,7 +1061,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
|||
return;
|
||||
}
|
||||
if (currentFileName.endsWith("mp4")) {
|
||||
if (currentMessageObject.messageOwner.send_state != MessageObject.MESSAGE_SEND_STATE_SENDING && currentMessageObject.messageOwner.send_state != MessageObject.MESSAGE_SEND_STATE_SEND_ERROR) {
|
||||
if (!currentMessageObject.isSending() && !currentMessageObject.isSendError()) {
|
||||
currentOverlay.setVisibility(View.VISIBLE);
|
||||
boolean load = false;
|
||||
if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() != 0) {
|
||||
|
@ -1393,7 +1393,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
|
|||
if (currentThumb != null && imageReceiver == centerImage) {
|
||||
placeHolder = currentThumb;
|
||||
}
|
||||
imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, size[0]);
|
||||
imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(null, placeHolder) : null, 0);
|
||||
} else {
|
||||
imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder));
|
||||
}
|
||||
|
|
|
@ -11,13 +11,7 @@ package org.telegram.ui;
|
|||
import android.annotation.TargetApi;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.media.MediaCodec;
|
||||
import android.media.MediaCodecInfo;
|
||||
import android.media.MediaCodecList;
|
||||
import android.media.MediaExtractor;
|
||||
import android.media.MediaFormat;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -32,31 +26,18 @@ import android.widget.TextView;
|
|||
|
||||
import com.coremedia.iso.IsoFile;
|
||||
import com.coremedia.iso.boxes.Box;
|
||||
import com.coremedia.iso.boxes.Container;
|
||||
import com.coremedia.iso.boxes.MediaBox;
|
||||
import com.coremedia.iso.boxes.MediaHeaderBox;
|
||||
import com.coremedia.iso.boxes.SampleSizeBox;
|
||||
import com.coremedia.iso.boxes.TrackBox;
|
||||
import com.coremedia.iso.boxes.TrackHeaderBox;
|
||||
import com.coremedia.iso.boxes.h264.AvcConfigurationBox;
|
||||
import com.googlecode.mp4parser.authoring.Movie;
|
||||
import com.googlecode.mp4parser.authoring.Track;
|
||||
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
|
||||
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
|
||||
import com.googlecode.mp4parser.authoring.tracks.CroppedTrack;
|
||||
import com.googlecode.mp4parser.util.Matrix;
|
||||
import com.googlecode.mp4parser.util.Path;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.LocaleController;
|
||||
import org.telegram.android.video.InputSurface;
|
||||
import org.telegram.android.video.MP4Builder;
|
||||
import org.telegram.android.video.Mp4Movie;
|
||||
import org.telegram.android.video.OutputSurface;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarLayer;
|
||||
import org.telegram.ui.Views.ActionBar.ActionBarMenu;
|
||||
|
@ -65,11 +46,6 @@ import org.telegram.ui.Views.VideoSeekBarView;
|
|||
import org.telegram.ui.Views.VideoTimelineView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(16)
|
||||
|
@ -80,10 +56,6 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
private final static int OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
|
||||
private final static int OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002;
|
||||
private final static int OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04;
|
||||
private final static String MIME_TYPE = "video/avc";
|
||||
|
||||
private final static int PROCESSOR_TYPE_OTHER = 0;
|
||||
private final static int PROCESSOR_TYPE_QCOM = 1;
|
||||
|
||||
private MediaPlayer videoPlayer = null;
|
||||
private VideoTimelineView videoTimelineView = null;
|
||||
|
@ -95,14 +67,15 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
private VideoSeekBarView videoSeekBarView = null;
|
||||
private TextureView textureView = null;
|
||||
private View controlView = null;
|
||||
private boolean playerPrepared = false;
|
||||
|
||||
private String videoPath = null;
|
||||
private float lastProgress = 0;
|
||||
private boolean needSeek = false;
|
||||
private VideoEditorActivityDelegate delegate;
|
||||
|
||||
private boolean firstWrite = true;
|
||||
//MediaMetadataRetriever TODO
|
||||
private final Object sync = new Object();
|
||||
private Thread thread = null;
|
||||
|
||||
private int rotationValue = 0;
|
||||
private int originalWidth = 0;
|
||||
|
@ -119,14 +92,17 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
private long esimatedDuration = 0;
|
||||
|
||||
public interface VideoEditorActivityDelegate {
|
||||
public abstract void didStartVideoConverting(String videoPath, String originalPath, long estimatedSize, int duration, int width, int height);
|
||||
public abstract void didAppenedVideoData(String videoPath, long finalSize);
|
||||
public abstract void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration);
|
||||
}
|
||||
|
||||
private Runnable progressRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (videoPlayer != null && videoPlayer.isPlaying()) {
|
||||
boolean playerCheck = false;
|
||||
synchronized (sync) {
|
||||
playerCheck = videoPlayer != null && videoPlayer.isPlaying();
|
||||
}
|
||||
while (playerCheck) {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -160,6 +136,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
synchronized (sync) {
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -185,6 +164,20 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
});
|
||||
}
|
||||
});
|
||||
videoPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
playerPrepared = true;
|
||||
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
|
||||
}
|
||||
});
|
||||
try {
|
||||
videoPlayer.setDataSource(videoPath);
|
||||
videoPlayer.prepareAsync();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
||||
return super.onFragmentCreate();
|
||||
}
|
||||
|
||||
|
@ -209,6 +202,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
if (id == -1) {
|
||||
finishFragment();
|
||||
} else if (id == 1) {
|
||||
synchronized (sync) {
|
||||
if (videoPlayer != null) {
|
||||
try {
|
||||
videoPlayer.stop();
|
||||
|
@ -218,12 +212,11 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
//startConvert();
|
||||
VideoEditWrapper.runTest(VideoEditorActivity.this);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.didFinishEditVideo(videoPath, startTime, endTime, resultWidth, resultHeight, rotationValue, originalWidth, originalHeight, bitrate, estimatedSize, esimatedDuration);
|
||||
}
|
||||
finishFragment();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -250,7 +243,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
videoTimelineView.setDelegate(new VideoTimelineView.VideoTimelineViewDelegate() {
|
||||
@Override
|
||||
public void onLeftProgressChanged(float progress) {
|
||||
if (videoPlayer == null) {
|
||||
if (videoPlayer == null || !playerPrepared) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -270,7 +263,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
|
||||
@Override
|
||||
public void onRifhtProgressChanged(float progress) {
|
||||
if (videoPlayer == null) {
|
||||
if (videoPlayer == null || !playerPrepared) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -293,7 +286,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
videoSeekBarView.delegate = new VideoSeekBarView.SeekBarDelegate() {
|
||||
@Override
|
||||
public void onSeekBarDrag(float progress) {
|
||||
if (videoPlayer == null) {
|
||||
if (videoPlayer == null || !playerPrepared) {
|
||||
return;
|
||||
}
|
||||
if (videoPlayer.isPlaying()) {
|
||||
|
@ -353,9 +346,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
try {
|
||||
Surface s = new Surface(surface);
|
||||
videoPlayer.setSurface(s);
|
||||
videoPlayer.setDataSource(videoPath);
|
||||
videoPlayer.prepare();
|
||||
if (playerPrepared) {
|
||||
videoPlayer.seekTo((int) (videoTimelineView.getLeftProgress() * videoDuration));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
@ -400,8 +393,9 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
int width = rotationValue == 90 || rotationValue == 270 ? originalHeight : originalWidth;
|
||||
int height = rotationValue == 90 || rotationValue == 270 ? originalWidth : originalHeight;
|
||||
String videoDimension = String.format("%dx%d", width, height);
|
||||
int minutes = (int)(videoDuration / 1000 / 60);
|
||||
int seconds = (int) Math.ceil(videoDuration / 1000) - minutes * 60;
|
||||
long duration = (long)Math.ceil(videoDuration);
|
||||
int minutes = (int)(duration / 1000 / 60);
|
||||
int seconds = (int) Math.ceil(duration / 1000) - minutes * 60;
|
||||
String videoTimeSize = String.format("%d:%02d, %s", minutes, seconds, Utilities.formatFileSize(file.length()));
|
||||
originalSizeTextView.setText(String.format("%s, %s", videoDimension, videoTimeSize));
|
||||
}
|
||||
|
@ -414,7 +408,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
int height = rotationValue == 90 || rotationValue == 270 ? resultWidth : resultHeight;
|
||||
String videoDimension = String.format("%dx%d", width, height);
|
||||
|
||||
esimatedDuration = (long)Math.max(1000, (videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration);
|
||||
esimatedDuration = (long)Math.ceil((videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration);
|
||||
estimatedSize = calculateEstimatedSize((float)esimatedDuration / videoDuration);
|
||||
if (videoTimelineView.getLeftProgress() == 0) {
|
||||
startTime = -1;
|
||||
|
@ -546,7 +540,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
}
|
||||
|
||||
private void play() {
|
||||
if (videoPlayer == null) {
|
||||
if (videoPlayer == null || !playerPrepared) {
|
||||
return;
|
||||
}
|
||||
if (videoPlayer.isPlaying()) {
|
||||
|
@ -576,7 +570,12 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
}
|
||||
});
|
||||
videoPlayer.start();
|
||||
new Thread(progressRunnable).start();
|
||||
synchronized (sync) {
|
||||
if (thread != null) {
|
||||
thread = new Thread(progressRunnable);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
|
@ -587,170 +586,6 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static class VideoEditWrapper implements Runnable {
|
||||
private VideoEditorActivity mTest;
|
||||
private VideoEditWrapper(VideoEditorActivity test) {
|
||||
mTest = test;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mTest.startConvert2();
|
||||
}
|
||||
|
||||
public static void runTest(final VideoEditorActivity obj) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
VideoEditWrapper wrapper = new VideoEditWrapper(obj);
|
||||
Thread th = new Thread(wrapper, "encoder");
|
||||
th.start();
|
||||
th.join();
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void didWriteData(final String videoPath, final long finalSize) {
|
||||
AndroidUtilities.RunOnUIThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (firstWrite) {
|
||||
int width = rotationValue == 90 || rotationValue == 270 ? resultHeight : resultWidth;
|
||||
int height = rotationValue == 90 || rotationValue == 270 ? resultWidth : resultHeight;
|
||||
delegate.didStartVideoConverting(videoPath, VideoEditorActivity.this.videoPath, estimatedSize, (int)esimatedDuration, width, height);
|
||||
firstWrite = false;
|
||||
finishFragment();
|
||||
} else {
|
||||
delegate.didAppenedVideoData(videoPath, finalSize);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static MediaCodecInfo selectCodec(String mimeType) {
|
||||
int numCodecs = MediaCodecList.getCodecCount();
|
||||
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)) {
|
||||
return codecInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
|
||||
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
|
||||
for (int i = 0; i < capabilities.colorFormats.length; i++) {
|
||||
int colorFormat = capabilities.colorFormats[i];
|
||||
if (isRecognizedFormat(colorFormat)) {
|
||||
return colorFormat;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 (!isAudio) {
|
||||
buffer.limit(info.offset + info.size);
|
||||
buffer.position(info.offset);
|
||||
buffer.putInt(info.size - 4);
|
||||
}
|
||||
if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info)) {
|
||||
didWriteData(file.toString(), 0);
|
||||
}
|
||||
extractor.advance();
|
||||
} else {
|
||||
eof = true;
|
||||
}
|
||||
}
|
||||
} else if (index == -1) {
|
||||
eof = true;
|
||||
}
|
||||
if (eof) {
|
||||
inputDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
extractor.unselectTrack(trackIndex);
|
||||
return startTime;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private boolean processOpenVideo() {
|
||||
try {
|
||||
IsoFile isoFile = new IsoFile(videoPath);
|
||||
|
@ -767,7 +602,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
for (long size : sampleSizeBox.getSampleSizes()) {
|
||||
sampleSizes += size;
|
||||
}
|
||||
videoDuration = mediaHeaderBox.getDuration() / mediaHeaderBox.getTimescale();
|
||||
videoDuration = (float)mediaHeaderBox.getDuration() / (float)mediaHeaderBox.getTimescale();
|
||||
trackBitrate = (int)(sampleSizes * 8 / videoDuration);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
|
@ -826,444 +661,4 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
|
|||
size += size / (32 * 1024) * 16;
|
||||
return size;
|
||||
}
|
||||
|
||||
private boolean startConvert2() {
|
||||
File inputFile = new File(videoPath);
|
||||
if (!inputFile.canRead()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
firstWrite = true;
|
||||
File cacheFile = null;
|
||||
boolean error = false;
|
||||
long videoStartTime = startTime;
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
if (resultWidth != 0 && resultHeight != 0) {
|
||||
MP4Builder mediaMuxer = null;
|
||||
MediaExtractor extractor = null;
|
||||
|
||||
MediaCodec decoder = null;
|
||||
MediaCodec encoder = null;
|
||||
InputSurface inputSurface = null;
|
||||
OutputSurface outputSurface = null;
|
||||
|
||||
try {
|
||||
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
|
||||
UserConfig.lastLocalId--;
|
||||
cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
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 = -5;
|
||||
videoIndex = selectTrack(extractor, false);
|
||||
if (videoIndex >= 0) {
|
||||
boolean outputDone = false;
|
||||
boolean inputDone = false;
|
||||
boolean decoderDone = false;
|
||||
int swapUV = 0;
|
||||
int videoTrackIndex = -5;
|
||||
long videoTime = -1;
|
||||
|
||||
int colorFormat = 0;
|
||||
int processorType = PROCESSOR_TYPE_OTHER;
|
||||
if (Build.VERSION.SDK_INT < 18) {
|
||||
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
|
||||
colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
|
||||
if (codecInfo.getName().contains("OMX.qcom.")) {
|
||||
processorType = PROCESSOR_TYPE_QCOM;
|
||||
if (Build.VERSION.SDK_INT == 16) { //nokia, lge
|
||||
swapUV = 1;
|
||||
}
|
||||
}
|
||||
FileLog.e("tmessages", "codec = " + codecInfo.getName());
|
||||
} else {
|
||||
colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
|
||||
}
|
||||
FileLog.e("tmessages", "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 (!Build.MANUFACTURER.toLowerCase().equals("lge")) {
|
||||
int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
|
||||
padding = uvoffset - (resultWidth * resultHeight);
|
||||
bufferSize += padding;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
outputFormat.setInteger("slice-height", resultHeightAligned);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
|
||||
decoder.start();
|
||||
|
||||
final int TIMEOUT_USEC = 2500;
|
||||
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
|
||||
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
|
||||
ByteBuffer[] encoderInputBuffers = null;
|
||||
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 = decoderInputBuffers[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) {
|
||||
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 = encoderOutputBuffers[encoderStatus];
|
||||
if (encodedData == null) {
|
||||
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
|
||||
}
|
||||
if (info.size > 1) {
|
||||
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
|
||||
encodedData.limit(info.offset + info.size);
|
||||
encodedData.position(info.offset);
|
||||
encodedData.putInt(Integer.reverseBytes(info.size - 4));
|
||||
if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info)) {
|
||||
didWriteData(cacheFile.toString(), 0);
|
||||
}
|
||||
} 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();
|
||||
} else if (decoderStatus < 0) {
|
||||
throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
|
||||
} else {
|
||||
boolean doRender = false;
|
||||
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;
|
||||
FileLog.e("tmessages", "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;
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
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();
|
||||
Utilities.convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV);
|
||||
encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
|
||||
} else {
|
||||
FileLog.e("tmessages", "input buffer not available");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
|
||||
decoderOutputAvailable = false;
|
||||
FileLog.e("tmessages", "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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
extractor.unselectTrack(videoIndex);
|
||||
if (videoTime != -1) {
|
||||
videoStartTime = videoTime;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
long videoTime = readAndWriteTrack(extractor, mediaMuxer, info, startTime, endTime, cacheFile, false);
|
||||
if (videoTime != -1) {
|
||||
videoStartTime = videoTime;
|
||||
}
|
||||
}
|
||||
readAndWriteTrack(extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true);
|
||||
} catch (Exception e) {
|
||||
error = true;
|
||||
FileLog.e("tmessages", e);
|
||||
} finally {
|
||||
if (extractor != null) {
|
||||
extractor.release();
|
||||
extractor = null;
|
||||
}
|
||||
if (outputSurface != null) {
|
||||
outputSurface.release();
|
||||
outputSurface = null;
|
||||
}
|
||||
if (inputSurface != null) {
|
||||
inputSurface.release();
|
||||
inputSurface = null;
|
||||
}
|
||||
if (decoder != null) {
|
||||
decoder.stop();
|
||||
decoder.release();
|
||||
decoder = null;
|
||||
}
|
||||
if (encoder != null) {
|
||||
encoder.stop();
|
||||
encoder.release();
|
||||
encoder = null;
|
||||
}
|
||||
if (mediaMuxer != null) {
|
||||
try {
|
||||
mediaMuxer.finishMovie(false);
|
||||
} catch (Exception e) {
|
||||
FileLog.e("tmessages", e);
|
||||
}
|
||||
mediaMuxer = null;
|
||||
}
|
||||
FileLog.e("tmessages", "time = " + (System.currentTimeMillis() - time));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (!error && cacheFile != null) {
|
||||
didWriteData(cacheFile.toString(), cacheFile.length());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startConvert() throws Exception {
|
||||
IsoFile isoFile = new IsoFile(videoPath);
|
||||
TrackBox trackBox = (TrackBox) Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/avc1/../../../../../");
|
||||
AvcConfigurationBox avcConfigurationBox = (AvcConfigurationBox) Path.getPath(trackBox, "mdia/minf/stbl/stsd/avc1/avcC");
|
||||
avcConfigurationBox.parseDetails();
|
||||
|
||||
Movie movie = MovieCreator.build(videoPath);
|
||||
|
||||
List<Track> tracks = movie.getTracks();
|
||||
movie.setTracks(new LinkedList<Track>());
|
||||
|
||||
double startTime = 0;
|
||||
double endTime = 0;
|
||||
|
||||
for (Track track : tracks) {
|
||||
if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
|
||||
double duration = (double) track.getDuration() / (double) track.getTrackMetaData().getTimescale();
|
||||
startTime = correctTimeToSyncSample(track, videoTimelineView.getLeftProgress() * duration, false);
|
||||
endTime = videoTimelineView.getRightProgress() * duration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (Track track : tracks) {
|
||||
long currentSample = 0;
|
||||
double currentTime = 0;
|
||||
double lastTime = 0;
|
||||
long startSample = 0;
|
||||
long endSample = -1;
|
||||
|
||||
for (int i = 0; i < track.getSampleDurations().length; i++) {
|
||||
long delta = track.getSampleDurations()[i];
|
||||
if (currentTime > lastTime && currentTime <= startTime) {
|
||||
startSample = currentSample;
|
||||
}
|
||||
if (currentTime > lastTime && currentTime <= endTime) {
|
||||
endSample = currentSample;
|
||||
}
|
||||
lastTime = currentTime;
|
||||
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
|
||||
currentSample++;
|
||||
}
|
||||
movie.addTrack(new CroppedTrack(track, startSample, endSample));
|
||||
}
|
||||
Container out = new DefaultMp4Builder().build(movie);
|
||||
|
||||
String fileName = Integer.MIN_VALUE + "_" + UserConfig.lastLocalId + ".mp4";
|
||||
UserConfig.lastLocalId--;
|
||||
File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
|
||||
UserConfig.saveConfig(false);
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(cacheFile);
|
||||
FileChannel fc = fos.getChannel();
|
||||
out.writeContainer(fc);
|
||||
|
||||
fc.close();
|
||||
fos.close();
|
||||
if (delegate != null) {
|
||||
//delegate.didFinishedVideoConverting(cacheFile.getAbsolutePath());
|
||||
finishFragment();
|
||||
}
|
||||
}
|
||||
|
||||
private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
|
||||
double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
|
||||
long currentSample = 0;
|
||||
double currentTime = 0;
|
||||
for (int i = 0; i < track.getSampleDurations().length; i++) {
|
||||
long delta = track.getSampleDurations()[i];
|
||||
if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
|
||||
timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
|
||||
}
|
||||
currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
|
||||
currentSample++;
|
||||
}
|
||||
double previous = 0;
|
||||
for (double timeOfSyncSample : timeOfSyncSamples) {
|
||||
if (timeOfSyncSample > cutHere) {
|
||||
if (next) {
|
||||
return timeOfSyncSample;
|
||||
} else {
|
||||
return previous;
|
||||
}
|
||||
}
|
||||
previous = timeOfSyncSample;
|
||||
}
|
||||
return timeOfSyncSamples[timeOfSyncSamples.length - 1];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.view.animation.AnimationUtils;
|
|||
import android.widget.FrameLayout;
|
||||
|
||||
import org.telegram.android.AndroidUtilities;
|
||||
import org.telegram.android.NotificationCenter;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.R;
|
||||
|
||||
|
@ -199,11 +200,11 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
|
||||
private void onSlideAnimationEnd(boolean backAnimation) {
|
||||
containerView.setX(0);
|
||||
containerViewBack.setX(0);
|
||||
containerView.setTranslationX(0);
|
||||
containerViewBack.setTranslationX(0);
|
||||
actionBar.stopMoving(backAnimation);
|
||||
shadowView.setVisibility(View.INVISIBLE);
|
||||
shadowView.setX(-AndroidUtilities.dp(2));
|
||||
shadowView.setTranslationX(-AndroidUtilities.dp(2));
|
||||
if (!backAnimation) {
|
||||
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1);
|
||||
lastFragment.onPause();
|
||||
|
@ -240,7 +241,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
startedTracking = true;
|
||||
startedTrackingX = (int) ev.getX();
|
||||
shadowView.setVisibility(View.VISIBLE);
|
||||
shadowView.setX(-AndroidUtilities.dp(2));
|
||||
shadowView.setTranslationX(-AndroidUtilities.dp(2));
|
||||
containerViewBack.setVisibility(View.VISIBLE);
|
||||
beginTrackingSent = false;
|
||||
|
||||
|
@ -297,8 +298,8 @@ public class ActionBarLayout extends FrameLayout {
|
|||
beginTrackingSent = true;
|
||||
}
|
||||
actionBar.moveActionBarByX(dx);
|
||||
containerView.setX(dx);
|
||||
shadowView.setX(dx - AndroidUtilities.dp(2));
|
||||
containerView.setTranslationX(dx);
|
||||
shadowView.setTranslationX(dx - AndroidUtilities.dp(2));
|
||||
}
|
||||
} else if (ev != null && ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) {
|
||||
if (velocityTracker == null) {
|
||||
|
@ -488,19 +489,20 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
|
||||
public boolean presentFragment(BaseFragment fragment) {
|
||||
return presentFragment(fragment, false, false);
|
||||
return presentFragment(fragment, false, false, true);
|
||||
}
|
||||
|
||||
public boolean presentFragment(BaseFragment fragment, boolean removeLast) {
|
||||
return presentFragment(fragment, removeLast, false);
|
||||
return presentFragment(fragment, removeLast, false, true);
|
||||
}
|
||||
|
||||
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation) {
|
||||
if (checkTransitionAnimation() || delegate != null && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) {
|
||||
public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check) {
|
||||
if (checkTransitionAnimation() || delegate != null && check && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) {
|
||||
return false;
|
||||
}
|
||||
if (parentActivity.getCurrentFocus() != null) {
|
||||
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
|
||||
NotificationCenter.getInstance().postNotificationName(NotificationCenter.hideEmojiKeyboard);
|
||||
}
|
||||
boolean needAnimation = openAnimation != null && !forceWithoutAnimation && parentActivity.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).getBoolean("view_animations", true);
|
||||
if (useAlphaAnimations && fragmentsStack.size() == 0 && alphaOpenAnimation == null) {
|
||||
|
@ -533,6 +535,9 @@ public class ActionBarLayout extends FrameLayout {
|
|||
|
||||
if (!needAnimation) {
|
||||
presentFragmentInternalRemoveOld(removeLast, currentFragment);
|
||||
if (backgroundView != null) {
|
||||
backgroundView.setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (needAnimation) {
|
||||
|
|
|
@ -157,12 +157,15 @@ public class BaseFragment {
|
|||
if (parentLayout == null) {
|
||||
return;
|
||||
}
|
||||
parentLayout.presentFragment(fragment, removeLast, forceWithoutAnimation);
|
||||
parentLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, true);
|
||||
}
|
||||
|
||||
public Activity getParentActivity() {
|
||||
if (parentLayout != null) {
|
||||
return parentLayout.parentActivity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void showActionBar() {
|
||||
if (parentLayout != null) {
|
||||
|
|
|
@ -45,6 +45,8 @@ import org.telegram.messenger.R;
|
|||
import org.telegram.messenger.TLRPC;
|
||||
import org.telegram.ui.ApplicationLoader;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ChatActivityEnterView implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate {
|
||||
|
||||
public static interface ChatActivityEnterViewDelegate {
|
||||
|
@ -87,6 +89,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
|
|||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeChats);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidSent);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.emojiDidLoaded);
|
||||
NotificationCenter.getInstance().addObserver(this, NotificationCenter.hideEmojiKeyboard);
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
sendByEnter = preferences.getBoolean("send_by_enter", false);
|
||||
}
|
||||
|
@ -99,6 +102,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
|
|||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidSent);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded);
|
||||
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.hideEmojiKeyboard);
|
||||
if (mWakeLock != null) {
|
||||
try {
|
||||
mWakeLock.release();
|
||||
|
@ -507,6 +511,15 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
|
|||
}
|
||||
});
|
||||
emojiPopup = new PopupWindow(emojiView);
|
||||
|
||||
/*Utry {
|
||||
Method method = emojiPopup.getClass().getMethod("setWindowLayoutType", int.class);
|
||||
if (method != null) {
|
||||
method.invoke(emojiPopup, WindowManager.LayoutParams.LAST_SUB_WINDOW);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//don't promt
|
||||
}*/
|
||||
}
|
||||
|
||||
public void setDelegate(ChatActivityEnterViewDelegate delegate) {
|
||||
|
@ -646,6 +659,8 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen
|
|||
if (delegate != null) {
|
||||
delegate.onMessageSend();
|
||||
}
|
||||
} else if (id == NotificationCenter.hideEmojiKeyboard) {
|
||||
hideEmojiPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,30 +213,26 @@ public class EmojiView extends LinearLayout {
|
|||
}
|
||||
|
||||
public int getCount() {
|
||||
return this.data.length;
|
||||
return data.length;
|
||||
}
|
||||
|
||||
public Object getItem(int paramInt)
|
||||
{
|
||||
public Object getItem(int i) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long getItemId(int paramInt)
|
||||
{
|
||||
return this.data[paramInt];
|
||||
public long getItemId(int i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
public View getView(int paramInt, View paramView, ViewGroup paramViewGroup) {
|
||||
ImageView localObject;
|
||||
if (paramView != null) {
|
||||
localObject = (ImageView)paramView;
|
||||
} else {
|
||||
localObject = new ImageView(EmojiView.this.getContext()) {
|
||||
public View getView(int i, View view, ViewGroup paramViewGroup) {
|
||||
ImageView imageView = (ImageView)view;
|
||||
if (imageView == null) {
|
||||
imageView = new ImageView(EmojiView.this.getContext()) {
|
||||
public void onMeasure(int paramAnonymousInt1, int paramAnonymousInt2) {
|
||||
setMeasuredDimension(View.MeasureSpec.getSize(paramAnonymousInt1), View.MeasureSpec.getSize(paramAnonymousInt1));
|
||||
}
|
||||
};
|
||||
localObject.setOnClickListener(new View.OnClickListener() {
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
if (EmojiView.this.listener != null) {
|
||||
EmojiView.this.listener.onEmojiSelected(EmojiView.this.convert((Long)view.getTag()));
|
||||
|
@ -244,13 +240,12 @@ public class EmojiView extends LinearLayout {
|
|||
EmojiView.this.addToRecent((Long)view.getTag());
|
||||
}
|
||||
});
|
||||
localObject.setBackgroundResource(R.drawable.list_selector);
|
||||
localObject.setScaleType(ImageView.ScaleType.CENTER);
|
||||
imageView.setBackgroundResource(R.drawable.list_selector);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
}
|
||||
|
||||
localObject.setImageDrawable(Emoji.getEmojiBigDrawable(this.data[paramInt]));
|
||||
localObject.setTag(this.data[paramInt]);
|
||||
return localObject;
|
||||
imageView.setImageDrawable(Emoji.getEmojiBigDrawable(data[i]));
|
||||
imageView.setTag(data[i]);
|
||||
return imageView;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,7 +12,6 @@ import java.util.Locale;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
|
@ -42,15 +41,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
public int getPageIconResId(int position);
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
private static final int[] ATTRS = new int[] {
|
||||
android.R.attr.textSize,
|
||||
android.R.attr.textColor
|
||||
};
|
||||
// @formatter:on
|
||||
|
||||
private LinearLayout.LayoutParams defaultTabLayoutParams;
|
||||
private LinearLayout.LayoutParams expandedTabLayoutParams;
|
||||
|
||||
private final PageListener pageListener = new PageListener();
|
||||
public OnPageChangeListener delegatePageListener;
|
||||
|
@ -66,8 +57,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
private Paint rectPaint;
|
||||
private Paint dividerPaint;
|
||||
|
||||
private boolean checkedTabWidths = false;
|
||||
|
||||
private int indicatorColor = 0xFF666666;
|
||||
private int underlineColor = 0x1A000000;
|
||||
private int dividerColor = 0x1A000000;
|
||||
|
@ -122,33 +111,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
dividerWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm);
|
||||
tabTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);
|
||||
|
||||
// get system attrs (android:textSize and android:textColor)
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
|
||||
|
||||
tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
|
||||
tabTextColor = a.getColor(1, tabTextColor);
|
||||
|
||||
a.recycle();
|
||||
|
||||
// get custom attrs
|
||||
|
||||
a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlidingTabStrip);
|
||||
|
||||
indicatorColor = a.getColor(R.styleable.PagerSlidingTabStrip_indicatorColor, indicatorColor);
|
||||
underlineColor = a.getColor(R.styleable.PagerSlidingTabStrip_underlineColor, underlineColor);
|
||||
dividerColor = a.getColor(R.styleable.PagerSlidingTabStrip_dividerColor, dividerColor);
|
||||
indicatorHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_indicatorHeight, indicatorHeight);
|
||||
underlineHeight = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_underlineHeight, underlineHeight);
|
||||
dividerPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_dividerPadding1, dividerPadding);
|
||||
tabPadding = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_tabPaddingLeftRight, tabPadding);
|
||||
tabBackgroundResId = a.getResourceId(R.styleable.PagerSlidingTabStrip_tabBackground, tabBackgroundResId);
|
||||
shouldExpand = a.getBoolean(R.styleable.PagerSlidingTabStrip_shouldExpand, shouldExpand);
|
||||
scrollOffset = a.getDimensionPixelSize(R.styleable.PagerSlidingTabStrip_scrollOffset, scrollOffset);
|
||||
textAllCaps = a.getBoolean(R.styleable.PagerSlidingTabStrip_textAllCaps1, textAllCaps);
|
||||
|
||||
a.recycle();
|
||||
|
||||
rectPaint = new Paint();
|
||||
rectPaint.setAntiAlias(true);
|
||||
rectPaint.setStyle(Style.FILL);
|
||||
|
@ -158,7 +120,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
dividerPaint.setStrokeWidth(dividerWidth);
|
||||
|
||||
defaultTabLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
|
||||
expandedTabLayoutParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f);
|
||||
|
||||
if (locale == null) {
|
||||
locale = getResources().getConfiguration().locale;
|
||||
|
@ -199,8 +160,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
|
||||
updateTabStyles();
|
||||
|
||||
checkedTabWidths = false;
|
||||
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -296,7 +255,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -312,7 +270,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
}
|
||||
|
||||
private void scrollToChild(int position, int offset) {
|
||||
|
||||
if (tabCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -327,7 +284,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
lastScrollX = newScrollX;
|
||||
scrollTo(newScrollX, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -615,5 +571,4 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/doccancel_b.png
Normal file
After Width: | Height: | Size: 483 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 490 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/docload_b.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/docload_g.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.5 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/docpause_b.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/docpause_g.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
TMessagesProj/src/main/res/drawable-hdpi/photocancel.png
Executable file → Normal file
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/photogif.png
Executable file → Normal file
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/photoload.png
Executable file → Normal file
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
TMessagesProj/src/main/res/drawable-hdpi/photopause.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 599 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 613 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 314 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 299 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 965 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 964 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/docpause_b.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/docpause_g.png
Normal file
After Width: | Height: | Size: 203 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/photocancel.png
Executable file → Normal file
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 724 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/photogif.png
Executable file → Normal file
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 853 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/photoload.png
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 708 B |
BIN
TMessagesProj/src/main/res/drawable-ldpi/photopause.png
Normal file
After Width: | Height: | Size: 578 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 795 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 786 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 803 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 410 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
TMessagesProj/src/main/res/drawable-mdpi/docpause_b.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
TMessagesProj/src/main/res/drawable-mdpi/docpause_g.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
TMessagesProj/src/main/res/drawable-mdpi/photocancel.png
Executable file → Normal file
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1 KiB |
BIN
TMessagesProj/src/main/res/drawable-mdpi/photogif.png
Executable file → Normal file
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
TMessagesProj/src/main/res/drawable-mdpi/photoload.png
Executable file → Normal file
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 899 B |
BIN
TMessagesProj/src/main/res/drawable-mdpi/photopause.png
Normal file
After Width: | Height: | Size: 781 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 674 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/docpause_b.png
Normal file
After Width: | Height: | Size: 298 B |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/docpause_g.png
Normal file
After Width: | Height: | Size: 315 B |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/photocancel.png
Executable file → Normal file
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2 KiB |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/photogif.png
Executable file → Normal file
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/photoload.png
Executable file → Normal file
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.8 KiB |
BIN
TMessagesProj/src/main/res/drawable-xhdpi/photopause.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 831 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 831 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/docpause_b.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/docpause_g.png
Normal file
After Width: | Height: | Size: 406 B |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/photocancel.png
Executable file → Normal file
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.8 KiB |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/photogif.png
Executable file → Normal file
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.1 KiB |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/photoload.png
Executable file → Normal file
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
TMessagesProj/src/main/res/drawable-xxhdpi/photopause.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.2 KiB |
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">تحرير الفيديو</string>
|
||||
<string name="OriginalVideo">الفيديو الأصلي</string>
|
||||
<string name="EditedVideo">تم تحرير الفيديو</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">التالي</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Video bearbeiten</string>
|
||||
<string name="OriginalVideo">Originalvideo</string>
|
||||
<string name="EditedVideo">Bearbeitetes Video</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Weiter</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Editar vídeo</string>
|
||||
<string name="OriginalVideo">Vídeo original</string>
|
||||
<string name="EditedVideo">Vídeo editado</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Siguiente</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Modifica video</string>
|
||||
<string name="OriginalVideo">Video originale</string>
|
||||
<string name="EditedVideo">Video modificato</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Avanti</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Video bewerken</string>
|
||||
<string name="OriginalVideo">Originele video</string>
|
||||
<string name="EditedVideo">Bewerkte video</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Volgende</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Editar Vídeo</string>
|
||||
<string name="OriginalVideo">Vídeo Original</string>
|
||||
<string name="EditedVideo">Vídeo Editado</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Próximo</string>
|
||||
|
|
|
@ -317,6 +317,7 @@
|
|||
<string name="EditVideo">Edit Video</string>
|
||||
<string name="OriginalVideo">Original Video</string>
|
||||
<string name="EditedVideo">Edited Video</string>
|
||||
<string name="SendingVideo">Sending video...</string>
|
||||
|
||||
<!--button titles-->
|
||||
<string name="Next">Seguinte</string>
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="PagerSlidingTabStrip">
|
||||
<attr name="indicatorColor" format="color" />
|
||||
<attr name="underlineColor" format="color" />
|
||||
<attr name="dividerColor" format="color" />
|
||||
<attr name="indicatorHeight" format="dimension" />
|
||||
<attr name="underlineHeight" format="dimension" />
|
||||
<attr name="dividerPadding1" format="dimension" />
|
||||
<attr name="tabPaddingLeftRight" format="dimension" />
|
||||
<attr name="scrollOffset" format="dimension" />
|
||||
<attr name="tabBackground" format="reference" />
|
||||
<attr name="shouldExpand" format="boolean" />
|
||||
<attr name="textAllCaps1" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|