Video convert queue, bug fixes

This commit is contained in:
DrKLO 2014-09-28 17:37:26 +04:00
parent 27972c8ec5
commit dff98476dd
101 changed files with 1413 additions and 1015 deletions

View file

@ -80,7 +80,7 @@ android {
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
versionCode 330
versionCode 331
versionName "1.9.0"
}
}

View file

@ -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
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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 {

View file

@ -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;

View file

@ -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];
}
*/
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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) {

View file

@ -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) {

View file

@ -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));
}

View file

@ -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];
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -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();
}
}
}

View file

@ -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

View file

@ -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 {
}
};
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

BIN
TMessagesProj/src/main/res/drawable-hdpi/photocancel.png Executable file → Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

BIN
TMessagesProj/src/main/res/drawable-ldpi/photocancel.png Executable file → Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

BIN
TMessagesProj/src/main/res/drawable-mdpi/photocancel.png Executable file → Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

BIN
TMessagesProj/src/main/res/drawable-xhdpi/photocancel.png Executable file → Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

Some files were not shown because too many files have changed in this diff Show more