aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--build.gradle6
-rw-r--r--src/main/AndroidManifest.xml2
-rw-r--r--src/main/java/de/pixart/messenger/Config.java4
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java280
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationActivity.java70
-rw-r--r--src/main/java/de/pixart/messenger/ui/ShareWithActivity.java35
-rw-r--r--src/main/java/de/pixart/messenger/ui/ShowFullscreenMessageActivity.java35
-rw-r--r--src/main/java/de/pixart/messenger/ui/UiInformableCallback.java5
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/InputSurface.java136
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/MP4Builder.java445
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/MediaController.java649
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java81
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/OutputSurface.java207
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/Sample.java27
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java213
-rw-r--r--src/main/java/de/pixart/messenger/utils/video/Track.java263
-rw-r--r--src/main/res/layout/conversation_list_row.xml1
-rw-r--r--src/main/res/values-de/strings.xml1
-rw-r--r--src/main/res/values/strings.xml1
19 files changed, 135 insertions, 2326 deletions
diff --git a/build.gradle b/build.gradle
index 863c70814..ce3dea532 100644
--- a/build.gradle
+++ b/build.gradle
@@ -62,6 +62,7 @@ dependencies {
compile 'pub.devrel:easypermissions:0.1.9'
compile 'com.wefika:flowlayout:0.4.1'
compile 'com.googlecode.ez-vcard:ez-vcard:0.10.0'
+ compile 'net.ypresto.androidtranscoder:android-transcoder:0.2.0'
}
ext {
@@ -79,9 +80,8 @@ android {
minSdkVersion 14
targetSdkVersion 25
- versionCode 182
- //versionName "1.15.4"
- versionName "1.15.5 beta (2017-01-09)"
+ versionCode 183
+ versionName "1.16.0 beta (2017-01-25)"
archivesBaseName += "-$versionName"
applicationId "de.pixart.messenger"
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index c1895848a..c8b696605 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -23,6 +23,8 @@
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" />
+ <uses-sdk tools:overrideLibrary="net.ypresto.androidtranscoder" />
+
<application
android:name="android.support.multidex.MultiDexApplication"
android:allowBackup="true"
diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java
index 9141f3944..058e3a85e 100644
--- a/src/main/java/de/pixart/messenger/Config.java
+++ b/src/main/java/de/pixart/messenger/Config.java
@@ -77,10 +77,6 @@ public final class Config {
public static final int IMAGE_QUALITY = 75;
public static final int IMAGE_MAX_SIZE = 1 * 1024 * 1024; // 1 MiB
- public static final int VIDEO_SIZE = 640;
- public static final int VIDEO_BITRATE = 2 * 1000 * 1000; // 2 Mbps
- public static final int VIDEO_MAX_SIZE = 10 * 1024 * 1024; // 10 MiB
-
public static final int DEFAULT_ZOOM = 15; //for locations
public static final int MESSAGE_MERGE_WINDOW = 20;
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 4578ef99a..35fb22a3f 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -16,12 +16,12 @@ import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
@@ -29,7 +29,6 @@ import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.security.KeyChain;
-import android.support.v4.app.NotificationCompat;
import android.support.v4.app.RemoteInput;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -41,16 +40,15 @@ import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionID;
import net.java.otr4j.session.SessionImpl;
import net.java.otr4j.session.SessionStatus;
+import net.ypresto.androidtranscoder.MediaTranscoder;
+import net.ypresto.androidtranscoder.format.MediaFormatStrategyPresets;
import org.openintents.openpgp.IOpenPgpService2;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpServiceConnection;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
@@ -61,7 +59,6 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@@ -108,11 +105,10 @@ import de.pixart.messenger.persistance.DatabaseBackend;
import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.ui.SettingsActivity;
import de.pixart.messenger.ui.UiCallback;
+import de.pixart.messenger.ui.UiInformableCallback;
import de.pixart.messenger.utils.ConversationsFileObserver;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.ExceptionHelper;
-import de.pixart.messenger.utils.FileUtils;
-import de.pixart.messenger.utils.FileWriterException;
import de.pixart.messenger.utils.MimeUtils;
import de.pixart.messenger.utils.OnPhoneContactsLoadedListener;
import de.pixart.messenger.utils.PRNGFixes;
@@ -121,7 +117,6 @@ import de.pixart.messenger.utils.ReplacingSerialSingleThreadExecutor;
import de.pixart.messenger.utils.SerialSingleThreadExecutor;
import de.pixart.messenger.utils.Xmlns;
import de.pixart.messenger.utils.XmppUri;
-import de.pixart.messenger.utils.video.MediaController;
import de.pixart.messenger.xml.Element;
import de.pixart.messenger.xmpp.OnBindListener;
import de.pixart.messenger.xmpp.OnContactStatusChanged;
@@ -147,8 +142,6 @@ import de.pixart.messenger.xmpp.stanzas.MessagePacket;
import de.pixart.messenger.xmpp.stanzas.PresencePacket;
import me.leolin.shortcutbadger.ShortcutBadger;
-import static de.pixart.messenger.persistance.FileBackend.close;
-
public class XmppConnectionService extends Service {
public static final String ACTION_REPLY_TO_CONVERSATION = "reply_to_conversations";
@@ -160,10 +153,8 @@ public class XmppConnectionService extends Service {
public static final String ACTION_GCM_TOKEN_REFRESH = "gcm_token_refresh";
public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received";
private static final String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
- public static VideoCompressor CompressVideo;
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor();
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor();
- private final SerialSingleThreadExecutor mCopyVideoExecutor = new SerialSingleThreadExecutor();
private final IBinder mBinder = new XmppConnectionBinder();
private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
private final IqGenerator mIqGenerator = new IqGenerator(this);
@@ -172,7 +163,6 @@ public class XmppConnectionService extends Service {
public DatabaseBackend databaseBackend;
private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
private WakeLock wakeLock;
- private WakeLock VideoCompressionWakeLock;
private long mLastActivity = 0;
private NotificationManager mNotifyManager;
private ContentObserver contactObserver = new ContentObserver(null) {
@@ -474,11 +464,9 @@ public class XmppConnectionService extends Service {
}
message.setCounterpart(conversation.getNextCounterpart());
message.setType(Message.TYPE_FILE);
- final String path = getFileBackend().getOriginalPath(uri);
- Log.d(Config.LOGTAG, "File path = " + path);
mFileAddingExecutor.execute(new Runnable() {
- @Override
- public void run() {
+ private void processAsFile() {
+ final String path = getFileBackend().getOriginalPath(uri);
if (path != null) {
message.setRelativeFilePath(path);
getFileBackend().updateFileParams(message);
@@ -506,6 +494,72 @@ public class XmppConnectionService extends Service {
}
}
}
+
+ private void processAsVideo() throws FileNotFoundException {
+ Log.d(Config.LOGTAG, "processing file as video");
+ message.setRelativeFilePath(message.getUuid() + ".mp4");
+ final DownloadableFile file = getFileBackend().getFile(message);
+ file.getParentFile().mkdirs();
+ ParcelFileDescriptor parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
+ FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
+ final ArrayList<Integer> progressTracker = new ArrayList<>();
+ final UiInformableCallback<Message> informableCallback;
+ if (callback instanceof UiInformableCallback) {
+ informableCallback = (UiInformableCallback<Message>) callback;
+ } else {
+ informableCallback = null;
+ }
+ MediaTranscoder.Listener listener = new MediaTranscoder.Listener() {
+ @Override
+ public void onTranscodeProgress(double progress) {
+ int p = ((int) Math.round(progress * 100) / 5) * 5;
+ if (!progressTracker.contains(p) && p != 100 && p != 0) {
+ progressTracker.add(p);
+ if (informableCallback != null) {
+
+ informableCallback.inform(getString(R.string.transcoding_video_progress, p));
+ }
+ }
+ }
+
+ @Override
+ public void onTranscodeCompleted() {
+ if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
+ getPgpEngine().encrypt(message, callback);
+ } else {
+ callback.success(message);
+ }
+ }
+
+ @Override
+ public void onTranscodeCanceled() {
+ processAsFile();
+ }
+
+ @Override
+ public void onTranscodeFailed(Exception e) {
+ Log.d(Config.LOGTAG, "video transcoding failed " + e.getMessage());
+ processAsFile();
+ }
+ };
+ MediaTranscoder.getInstance().transcodeVideo(fileDescriptor, file.getAbsolutePath(),
+ MediaFormatStrategyPresets.createAndroid720pStrategy(), listener);
+ }
+
+ @Override
+ public void run() {
+ final String mimeType = MimeUtils.guessMimeTypeFromUri(XmppConnectionService.this, uri);
+ if (mimeType != null && mimeType.startsWith("video/") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ try {
+ processAsVideo();
+ } catch (Throwable e) {
+ processAsFile();
+ }
+ } else {
+ processAsFile();
+ }
+
+ }
});
}
@@ -555,143 +609,6 @@ public class XmppConnectionService extends Service {
});
}
- public void attachVideoToConversation(final Conversation conversation, final Uri uri, final UiCallback<Message> callback) {
- final Integer NOTIFICATION_ID = (int) (new Date().getTime() / 1000);
- final int[] success = {-1};
- File outputDir = this.getCacheDir();
- File file = null;
- try {
- file = File.createTempFile("temp-", "." + FileUtils.getExtension(this, uri), outputDir);
- } catch (IOException e) {
- Log.d(Config.LOGTAG, "error creating temp file");
- }
- long filesize = 0;
- String path = null;
- Boolean error = false;
-
- final File finalFile = file;
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- try {
- finalFile.getParentFile().mkdirs();
- Log.d(Config.LOGTAG, "copy video (" + uri.toString() + ") to temporarly storage " + finalFile.getAbsolutePath());
- OutputStream os = null;
- InputStream is = null;
- try {
- finalFile.createNewFile();
- os = new FileOutputStream(finalFile);
- is = XmppConnectionService.this.getContentResolver().openInputStream(uri);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
- try {
- os.write(buffer, 0, length);
- } catch (IOException e) {
- throw new FileWriterException();
- }
- }
- try {
- os.flush();
- } catch (IOException e) {
- throw new FileWriterException();
- }
- } catch (Exception e) {
- Log.d(Config.LOGTAG, "cannot copy video " + e);
- success[0] = 2;
- } finally {
- success[0] = 1;
- close(os);
- close(is);
- }
- } catch (Exception e) {
- Log.d(Config.LOGTAG, "cannot copy video " + e);
- }
- }
- }).start();
-
- while (success[0] == -1) {
- //ignored
- //Log.d(Config.LOGTAG, "Wait while copying video");
- }
- if (success[0] == 2) {
- mNotifyManager.cancel(NOTIFICATION_ID);
- callback.error(R.string.error_file_corrupt, null);
- return;
- }
- if (success[0] == 1) {
- try {
- filesize = file.length();
- path = file.toString();
- } catch (Exception e) {
- error = true;
- Log.d(Config.LOGTAG, "Error retrieving file path " + e);
- }
- final String compressVideos = getCompressVideoPreference();
- boolean sendVideoAsIs = false;
- mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
- mBuilder.setContentTitle(getString(R.string.app_name))
- .setContentText(getString(R.string.compressing_video))
- .setSmallIcon(R.drawable.ic_play_box_outline_white_24dp)
- .setOngoing(true)
- .setProgress(0, 0, true);
- mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
- if (FileBackend.weOwnFile(this, uri)) {
- Log.d(Config.LOGTAG, "trying to attach video that belonged to us");
- mNotifyManager.cancel(NOTIFICATION_ID);
- callback.error(R.string.security_error_invalid_file_access, null);
- return;
- }
- if (file == null) {
- error = true;
- }
- if (filesize == 0) {
- error = true;
- }
- if (error) {
- Log.d(Config.LOGTAG, "Error with file, size = 0");
- mNotifyManager.cancel(NOTIFICATION_ID);
- callback.error(R.string.error_file_corrupt, null);
- return;
- }
- Log.d(Config.LOGTAG, "Video file (size) :" + file.toString() + "(" + filesize / 1024 / 1024 + "MB)");
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
- File compressed_file = new File(FileBackend.getConversationsVideoDirectory() + "/"
- + dateFormat.format(new Date())
- + "_komp.mp4");
- final String compressed_path = compressed_file.toString();
- final Uri compressed_uri = Uri.fromFile(compressed_file);
- if ("never".equals(compressVideos)) {
- sendVideoAsIs = true;
- } else if ("always".equals(compressVideos) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- sendVideoAsIs = false;
- } else if ("auto".equals(compressVideos) && filesize > Config.VIDEO_MAX_SIZE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- sendVideoAsIs = false;
- } else {
- sendVideoAsIs = true;
- }
- if (!sendVideoAsIs) {
- CompressVideo = new VideoCompressor(path, compressed_path, new Interface() {
- @Override
- public void videocompressed(boolean result) {
- if (result) {
- Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending compressed video.");
- mNotifyManager.cancel(NOTIFICATION_ID);
- attachFileToConversation(conversation, compressed_uri, callback);
- }
- }
- });
- CompressVideo.execute();
- } else {
- Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": not compressing video. sending as file");
- mNotifyManager.cancel(NOTIFICATION_ID);
- attachFileToConversation(conversation, uri, callback);
- }
- }
- }
-
public Conversation find(Bookmark bookmark) {
return find(bookmark.getAccount(), bookmark.getJid());
}
@@ -941,10 +858,6 @@ public class XmppConnectionService extends Service {
return getPreferences().getString("picture_compression", "auto");
}
- private String getCompressVideoPreference() {
- return getPreferences().getString("video_compression", "auto");
- }
-
private Presence.Status getTargetPresence() {
if (xaOnSilentMode() && isPhoneSilenced()) {
return Presence.Status.XA;
@@ -1110,7 +1023,6 @@ public class XmppConnectionService extends Service {
this.pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "XmppConnectionService");
- this.VideoCompressionWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VideoCompression");
toggleForegroundService();
updateUnreadCountBadge();
toggleScreenEventReceiver();
@@ -3943,10 +3855,6 @@ public class XmppConnectionService extends Service {
}
}
- public interface Interface {
- void videocompressed(boolean result);
- }
-
public interface OnMamPreferencesFetched {
void onPreferencesFetched(Element prefs);
@@ -4026,46 +3934,6 @@ public class XmppConnectionService extends Service {
void onShowErrorToast(int resId);
}
- class VideoCompressor extends AsyncTask<String, Void, Boolean> {
- private String originalpath;
- private String compressedpath;
- private Interface mListener;
-
- VideoCompressor(String path, String compressed_path, Interface mListener) {
- originalpath = path;
- compressedpath = compressed_path;
- this.mListener = mListener;
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- Log.d(Config.LOGTAG, "Start video compression");
- VideoCompressionWakeLock.acquire();
- }
-
- @Override
- protected Boolean doInBackground(String... params) {
- return MediaController.getInstance().convertVideo(originalpath, compressedpath);
- }
-
- @Override
- protected void onPostExecute(Boolean compressed) {
- super.onPostExecute(compressed);
- File video = new File(compressedpath);
- if (mListener != null) {
- if (video.exists() && video.length() > 0) {
- mListener.videocompressed(compressed);
- Log.d(Config.LOGTAG, "Compression successfully!");
- } else {
- mListener.videocompressed(false);
- Log.d(Config.LOGTAG, "Compression failed!");
- }
- }
- VideoCompressionWakeLock.release();
- }
- }
-
public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() {
return XmppConnectionService.this;
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
index a68765632..529c926aa 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
@@ -117,7 +117,6 @@ public class ConversationActivity extends XmppActivity
final private List<Uri> mPendingImageUris = new ArrayList<>();
final private List<Uri> mPendingPhotoUris = new ArrayList<>();
final private List<Uri> mPendingFileUris = new ArrayList<>();
- final private List<Uri> mPendingVideoUris = new ArrayList<>();
private String mOpenConversation = null;
private boolean mPanelOpen = true;
private AtomicBoolean mShouldPanelBeOpen = new AtomicBoolean(false);
@@ -674,9 +673,10 @@ public class ConversationActivity extends XmppActivity
chooser = true;
break;
case ATTACHMENT_CHOICE_CHOOSE_VIDEO:
- intent.setAction(Intent.ACTION_GET_CONTENT);
- intent.setType("video/*");
chooser = true;
+ intent.setType("video/*");
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setAction(Intent.ACTION_GET_CONTENT);
break;
case ATTACHMENT_CHOICE_TAKE_PHOTO:
Uri uri = xmppConnectionService.getFileBackend().getTakePhotoUri();
@@ -1370,7 +1370,6 @@ public class ConversationActivity extends XmppActivity
private void clearPending() {
mPendingImageUris.clear();
mPendingFileUris.clear();
- mPendingVideoUris.clear();
mPendingPhotoUris.clear();
mPendingGeoUri = null;
mPostponedActivityResult = null;
@@ -1509,11 +1508,6 @@ public class ConversationActivity extends XmppActivity
attachPhotoToConversation(getSelectedConversation(), i.next());
}
- for (Iterator<Uri> i = mPendingVideoUris.iterator(); i.hasNext(); i.remove()) {
- Log.d(Config.LOGTAG, "ConversationActivity.onBackendConnected() - attaching video to conversations. stopping=" + Boolean.toString(stopping));
- attachVideoToConversation(getSelectedConversation(), i.next());
- }
-
for (Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) {
Log.d(Config.LOGTAG, "ConversationActivity.onBackendConnected() - attaching file to conversations. stopping=" + Boolean.toString(stopping));
attachFileToConversation(getSelectedConversation(), i.next());
@@ -1659,7 +1653,7 @@ public class ConversationActivity extends XmppActivity
}
}
}
- } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) {
+ } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE || requestCode == ATTACHMENT_CHOICE_CHOOSE_VIDEO) {
final List<Uri> uris = extractUriFromIntent(data);
final Conversation c = getSelectedConversation();
final OnPresenceSelected callback = new OnPresenceSelected() {
@@ -1682,29 +1676,6 @@ public class ConversationActivity extends XmppActivity
} else {
selectPresence(c, callback);
}
- } else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_VIDEO) {
- final List<Uri> uris = extractUriFromIntent(data);
- final Conversation c = getSelectedConversation();
- final OnPresenceSelected callback = new OnPresenceSelected() {
- @Override
- public void onPresenceSelected() {
- mPendingVideoUris.clear();
- mPendingVideoUris.addAll(uris);
- if (xmppConnectionServiceBound) {
- for (Iterator<Uri> i = mPendingVideoUris.iterator(); i.hasNext(); i.remove()) {
- Log.d(Config.LOGTAG, "ConversationActivity.onActivityResult() - attaching video to conversations. CHOOSE_VIDEO");
- attachVideoToConversation(c, i.next());
- }
- }
- }
- };
- if (c == null || c.getMode() == Conversation.MODE_MULTI
- || FileBackend.allFilesUnderSize(this, uris, getMaxHttpUploadSize(c))
- || c.getNextEncryption() == Message.ENCRYPTION_OTR) {
- callback.onPresenceSelected();
- } else {
- selectPresence(c, callback);
- }
} else if (requestCode == ATTACHMENT_CHOICE_TAKE_PHOTO) {
if (mPendingPhotoUris.size() == 1) {
Uri uri = FileBackend.getIndexableTakePhotoUri(mPendingPhotoUris.get(0));
@@ -1831,41 +1802,26 @@ public class ConversationActivity extends XmppActivity
}
final Toast prepareFileToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_file), Toast.LENGTH_LONG);
prepareFileToast.show();
- xmppConnectionService.attachFileToConversation(conversation, uri, new UiCallback<Message>() {
+ xmppConnectionService.attachFileToConversation(conversation, uri, new UiInformableCallback<Message>() {
@Override
- public void success(Message message) {
- hidePrepareFileToast(prepareFileToast);
- xmppConnectionService.sendMessage(message);
- }
-
- @Override
- public void error(final int errorCode, Message message) {
+ public void inform(final String text) {
hidePrepareFileToast(prepareFileToast);
runOnUiThread(new Runnable() {
@Override
public void run() {
- replaceToast(getString(errorCode));
+ replaceToast(text);
}
});
-
- }
-
- @Override
- public void userInputRequried(PendingIntent pi, Message message) {
- hidePrepareFileToast(prepareFileToast);
}
- });
- }
- private void attachVideoToConversation(Conversation conversation, final Uri uri) {
- if (conversation == null) {
- return;
- }
- final Toast prepareFileToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_video), Toast.LENGTH_LONG);
- prepareFileToast.show();
- xmppConnectionService.attachVideoToConversation(conversation, uri, new UiCallback<Message>() {
@Override
public void success(Message message) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ hideToast();
+ }
+ });
hidePrepareFileToast(prepareFileToast);
xmppConnectionService.sendMessage(message);
}
diff --git a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
index 870812cc4..c2cf95241 100644
--- a/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ShareWithActivity.java
@@ -49,7 +49,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
private class Share {
public List<Uri> uris = new ArrayList<>();
public boolean image;
- public boolean video;
public String account;
public String contact;
public String text;
@@ -66,7 +65,17 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
private Toast mToast;
private AtomicInteger attachmentCounter = new AtomicInteger(0);
- private UiCallback<Message> attachFileCallback = new UiCallback<Message>() {
+ private UiInformableCallback<Message> attachFileCallback = new UiInformableCallback<Message>() {
+
+ @Override
+ public void inform(final String text) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ replaceToast(text);
+ }
+ });
+ }
@Override
public void userInputRequried(PendingIntent pi, Message object) {
@@ -86,8 +95,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
resId = R.string.shared_images_with_x;
} else if (share.image) {
resId = R.string.shared_image_with_x;
- } else if (share.video) {
- resId = R.string.shared_video_with_x;
} else {
resId = R.string.shared_file_with_x;
}
@@ -219,7 +226,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
this.share.uris.clear();
this.share.uris.add(uri);
this.share.image = type.startsWith("image/") || isImage(uri);
- this.share.video = type.startsWith("video/") || isVideo(uri);
} else {
if (subject != null) {
this.share.text = format("[%s]%n%s", subject, text);
@@ -265,15 +271,6 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
}
}
- protected boolean isVideo(Uri uri) {
- try {
- String guess = URLConnection.guessContentTypeFromName(uri.toString());
- return (guess != null && guess.startsWith("video/"));
- } catch (final StringIndexOutOfBoundsException ignored) {
- return false;
- }
- }
-
@Override
void onBackendConnected() {
if (xmppConnectionServiceBound && share != null
@@ -341,24 +338,16 @@ public class ShareWithActivity extends XmppActivity implements XmppConnectionSer
.attachImageToConversation(conversation, i.next(),
attachFileCallback);
}
- } else if (share.video) {
- Log.d(Config.LOGTAG, "ShareWithActivity share() video " + share.uris.size() + " uri(s) " + share.uris.toString());
- replaceToast(getString(R.string.preparing_video));
- ShareWithActivity.this.xmppConnectionService
- .attachVideoToConversation(conversation, share.uris.get(0),
- attachFileCallback);
} else {
Log.d(Config.LOGTAG, "ShareWithActivity share() file " + share.uris.size() + " uri(s) " + share.uris.toString());
replaceToast(getString(R.string.preparing_file));
ShareWithActivity.this.xmppConnectionService
- .attachFileToConversation(conversation, share.uris.get(0),
- attachFileCallback);
+ .attachFileToConversation(conversation, share.uris.get(0), attachFileCallback);
}
}
};
if (account.httpUploadAvailable()
&& ((share.image && !neverCompressPictures())
- || share.video
|| conversation.getMode() == Conversation.MODE_MULTI
|| FileBackend.allFilesUnderSize(this, share.uris, max))
&& conversation.getNextEncryption() != Message.ENCRYPTION_OTR) {
diff --git a/src/main/java/de/pixart/messenger/ui/ShowFullscreenMessageActivity.java b/src/main/java/de/pixart/messenger/ui/ShowFullscreenMessageActivity.java
index 5f1fdc3c7..a8253fd1c 100644
--- a/src/main/java/de/pixart/messenger/ui/ShowFullscreenMessageActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ShowFullscreenMessageActivity.java
@@ -30,8 +30,6 @@ import java.io.InputStream;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
-import de.pixart.messenger.persistance.FileBackend;
-import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.utils.ExifHelper;
import uk.co.senab.photoview.PhotoView;
import uk.co.senab.photoview.PhotoViewAttacher;
@@ -50,8 +48,6 @@ public class ShowFullscreenMessageActivity extends Activity {
int height = 0;
int width = 0;
int rotation = 0;
- FileBackend mFileBackend;
- XmppConnectionService mXmppConnectionService;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -194,18 +190,35 @@ public class ShowFullscreenMessageActivity extends Activity {
retriever.setDataSource(uri.getPath());
height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
- Log.d(Config.LOGTAG, "Video height: " + height + ", width: " + width);
+ rotation = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION));
+ Log.d(Config.LOGTAG, "Video height: " + height + ", width: " + width + ", rotation: " + rotation);
if (width > height) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
+ if (rotation == 0 || rotation == 180) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ }
} else {
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
}
} else if (width <= height) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
+ if (rotation == 90 || rotation == 270) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
} else {
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
}
}
try {
diff --git a/src/main/java/de/pixart/messenger/ui/UiInformableCallback.java b/src/main/java/de/pixart/messenger/ui/UiInformableCallback.java
new file mode 100644
index 000000000..53ed044cc
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/UiInformableCallback.java
@@ -0,0 +1,5 @@
+package de.pixart.messenger.ui;
+
+public interface UiInformableCallback<T> extends UiCallback<T> {
+ void inform(String text);
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/video/InputSurface.java b/src/main/java/de/pixart/messenger/utils/video/InputSurface.java
deleted file mode 100644
index 3376b4b87..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/InputSurface.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.opengl.EGL14;
-import android.opengl.EGLConfig;
-import android.opengl.EGLContext;
-import android.opengl.EGLDisplay;
-import android.opengl.EGLExt;
-import android.opengl.EGLSurface;
-import android.os.Build;
-import android.view.Surface;
-
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
-public class InputSurface {
- private static final boolean VERBOSE = false;
- private static final int EGL_RECORDABLE_ANDROID = 0x3142;
- private static final int EGL_OPENGL_ES2_BIT = 4;
- private EGLDisplay mEGLDisplay;
- private EGLContext mEGLContext;
- private EGLSurface mEGLSurface;
- private Surface mSurface;
-
- public InputSurface(Surface surface) {
- if (surface == null) {
- throw new NullPointerException();
- }
- mSurface = surface;
- eglSetup();
- }
-
- private void eglSetup() {
- mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
- throw new RuntimeException("unable to get EGL14 display");
- }
- int[] version = new int[2];
- if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
- mEGLDisplay = null;
- throw new RuntimeException("unable to initialize EGL14");
- }
-
- int[] attribList = {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RECORDABLE_ANDROID, 1,
- EGL14.EGL_NONE
- };
- EGLConfig[] configs = new EGLConfig[1];
- int[] numConfigs = new int[1];
- if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
- numConfigs, 0)) {
- throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
- }
-
- int[] attrib_list = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL14.EGL_NONE
- };
-
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0);
- checkEglError("eglCreateContext");
- if (mEGLContext == null) {
- throw new RuntimeException("null context");
- }
-
- int[] surfaceAttribs = {
- EGL14.EGL_NONE
- };
- mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
- surfaceAttribs, 0);
- checkEglError("eglCreateWindowSurface");
- if (mEGLSurface == null) {
- throw new RuntimeException("surface was null");
- }
- }
-
- public void release() {
- if (EGL14.eglGetCurrentContext().equals(mEGLContext)) {
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- }
- EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
- EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
- mSurface.release();
- mEGLDisplay = null;
- mEGLContext = null;
- mEGLSurface = null;
- mSurface = null;
- }
-
- public void makeCurrent() {
- if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
- throw new RuntimeException("eglMakeCurrent failed");
- }
- }
-
- public boolean swapBuffers() {
- return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
- }
-
- public Surface getSurface() {
- return mSurface;
- }
-
- public void setPresentationTime(long nsecs) {
- EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
- }
-
- private void checkEglError(String msg) {
- boolean failed = false;
- int error;
- while ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
- failed = true;
- }
- if (failed) {
- throw new RuntimeException("EGL error encountered (see log)");
- }
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java b/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java
deleted file mode 100644
index ee8b83e27..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/MP4Builder.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * This is the source code of Telegram for Android v. 1.7.x.
- * It is licensed under GNU GPL v. 2 or later.
- * You should have received a copy of the license in this archive (see LICENSE).
- *
- * Copyright Nikolai Kudashov, 2013-2014.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-
-import com.coremedia.iso.BoxParser;
-import com.coremedia.iso.IsoFile;
-import com.coremedia.iso.IsoTypeWriter;
-import com.coremedia.iso.boxes.Box;
-import com.coremedia.iso.boxes.Container;
-import com.coremedia.iso.boxes.DataEntryUrlBox;
-import com.coremedia.iso.boxes.DataInformationBox;
-import com.coremedia.iso.boxes.DataReferenceBox;
-import com.coremedia.iso.boxes.FileTypeBox;
-import com.coremedia.iso.boxes.HandlerBox;
-import com.coremedia.iso.boxes.MediaBox;
-import com.coremedia.iso.boxes.MediaHeaderBox;
-import com.coremedia.iso.boxes.MediaInformationBox;
-import com.coremedia.iso.boxes.MovieBox;
-import com.coremedia.iso.boxes.MovieHeaderBox;
-import com.coremedia.iso.boxes.SampleSizeBox;
-import com.coremedia.iso.boxes.SampleTableBox;
-import com.coremedia.iso.boxes.SampleToChunkBox;
-import com.coremedia.iso.boxes.StaticChunkOffsetBox;
-import com.coremedia.iso.boxes.SyncSampleBox;
-import com.coremedia.iso.boxes.TimeToSampleBox;
-import com.coremedia.iso.boxes.TrackBox;
-import com.coremedia.iso.boxes.TrackHeaderBox;
-import com.googlecode.mp4parser.DataSource;
-import com.googlecode.mp4parser.util.Matrix;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-
-@TargetApi(16)
-public class MP4Builder {
-
- private InterleaveChunkMdat mdat = null;
- private Mp4Movie currentMp4Movie = null;
- private FileOutputStream fos = null;
- private FileChannel fc = null;
- private long dataOffset = 0;
- private long writedSinceLastMdat = 0;
- private boolean writeNewMdat = true;
- private HashMap<Track, long[]> track2SampleSizes = new HashMap<>();
- private ByteBuffer sizeBuffer = null;
-
- public MP4Builder createMovie(Mp4Movie mp4Movie) throws Exception {
- currentMp4Movie = mp4Movie;
-
- fos = new FileOutputStream(mp4Movie.getCacheFile());
- fc = fos.getChannel();
-
- FileTypeBox fileTypeBox = createFileTypeBox();
- fileTypeBox.getBox(fc);
- dataOffset += fileTypeBox.getSize();
- writedSinceLastMdat += dataOffset;
-
- mdat = new InterleaveChunkMdat();
-
- sizeBuffer = ByteBuffer.allocateDirect(4);
-
- return this;
- }
-
- private void flushCurrentMdat() throws Exception {
- long oldPosition = fc.position();
- fc.position(mdat.getOffset());
- mdat.getBox(fc);
- fc.position(oldPosition);
- mdat.setDataOffset(0);
- mdat.setContentSize(0);
- fos.flush();
- }
-
- public boolean writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo, boolean isAudio) throws Exception {
- if (writeNewMdat) {
- mdat.setContentSize(0);
- mdat.getBox(fc);
- mdat.setDataOffset(dataOffset);
- dataOffset += 16;
- writedSinceLastMdat += 16;
- writeNewMdat = false;
- }
-
- mdat.setContentSize(mdat.getContentSize() + bufferInfo.size);
- writedSinceLastMdat += bufferInfo.size;
-
- boolean flush = false;
- if (writedSinceLastMdat >= 32 * 1024) {
- flushCurrentMdat();
- writeNewMdat = true;
- flush = true;
- writedSinceLastMdat -= 32 * 1024;
- }
-
- currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo);
- byteBuf.position(bufferInfo.offset + (isAudio ? 0 : 4));
- byteBuf.limit(bufferInfo.offset + bufferInfo.size);
-
- if (!isAudio) {
- sizeBuffer.position(0);
- sizeBuffer.putInt(bufferInfo.size - 4);
- sizeBuffer.position(0);
- fc.write(sizeBuffer);
- }
-
- fc.write(byteBuf);
- dataOffset += bufferInfo.size;
-
- if (flush) {
- fos.flush();
- }
- return flush;
- }
-
- public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception {
- return currentMp4Movie.addTrack(mediaFormat, isAudio);
- }
-
- public void finishMovie(boolean error) throws Exception {
- if (mdat.getContentSize() != 0) {
- flushCurrentMdat();
- }
-
- for (Track track : currentMp4Movie.getTracks()) {
- List<Sample> samples = track.getSamples();
- long[] sizes = new long[samples.size()];
- for (int i = 0; i < sizes.length; i++) {
- sizes[i] = samples.get(i).getSize();
- }
- track2SampleSizes.put(track, sizes);
- }
-
- Box moov = createMovieBox(currentMp4Movie);
- moov.getBox(fc);
- fos.flush();
-
- fc.close();
- fos.close();
- }
-
- protected FileTypeBox createFileTypeBox() {
- LinkedList<String> minorBrands = new LinkedList<>();
- minorBrands.add("isom");
- minorBrands.add("3gp4");
- return new FileTypeBox("isom", 0, minorBrands);
- }
-
- private class InterleaveChunkMdat implements Box {
- private Container parent;
- private long contentSize = 1024 * 1024 * 1024;
- private long dataOffset = 0;
-
- public Container getParent() {
- return parent;
- }
-
- public long getOffset() {
- return dataOffset;
- }
-
- public void setDataOffset(long offset) {
- dataOffset = offset;
- }
-
- public void setParent(Container parent) {
- this.parent = parent;
- }
-
- public void setContentSize(long contentSize) {
- this.contentSize = contentSize;
- }
-
- public long getContentSize() {
- return contentSize;
- }
-
- public String getType() {
- return "mdat";
- }
-
- public long getSize() {
- return 16 + contentSize;
- }
-
- private boolean isSmallBox(long contentSize) {
- return (contentSize + 8) < 4294967296L;
- }
-
- @Override
- public void parse(DataSource dataSource, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
-
- }
-
- public void getBox(WritableByteChannel writableByteChannel) throws IOException {
- ByteBuffer bb = ByteBuffer.allocate(16);
- long size = getSize();
- if (isSmallBox(size)) {
- IsoTypeWriter.writeUInt32(bb, size);
- } else {
- IsoTypeWriter.writeUInt32(bb, 1);
- }
- bb.put(IsoFile.fourCCtoBytes("mdat"));
- if (isSmallBox(size)) {
- bb.put(new byte[8]);
- } else {
- IsoTypeWriter.writeUInt64(bb, size);
- }
- bb.rewind();
- writableByteChannel.write(bb);
- }
- }
-
- public static long gcd(long a, long b) {
- if (b == 0) {
- return a;
- }
- return gcd(b, a % b);
- }
-
- public long getTimescale(Mp4Movie mp4Movie) {
- long timescale = 0;
- if (!mp4Movie.getTracks().isEmpty()) {
- timescale = mp4Movie.getTracks().iterator().next().getTimeScale();
- }
- for (Track track : mp4Movie.getTracks()) {
- timescale = gcd(track.getTimeScale(), timescale);
- }
- return timescale;
- }
-
- protected MovieBox createMovieBox(Mp4Movie movie) {
- MovieBox movieBox = new MovieBox();
- MovieHeaderBox mvhd = new MovieHeaderBox();
-
- mvhd.setCreationTime(new Date());
- mvhd.setModificationTime(new Date());
- mvhd.setMatrix(Matrix.ROTATE_0);
- long movieTimeScale = getTimescale(movie);
- long duration = 0;
-
- for (Track track : movie.getTracks()) {
- long tracksDuration = track.getDuration() * movieTimeScale / track.getTimeScale();
- if (tracksDuration > duration) {
- duration = tracksDuration;
- }
- }
-
- mvhd.setDuration(duration);
- mvhd.setTimescale(movieTimeScale);
- mvhd.setNextTrackId(movie.getTracks().size() + 1);
-
- movieBox.addBox(mvhd);
- for (Track track : movie.getTracks()) {
- movieBox.addBox(createTrackBox(track, movie));
- }
- return movieBox;
- }
-
- protected TrackBox createTrackBox(Track track, Mp4Movie movie) {
- TrackBox trackBox = new TrackBox();
- TrackHeaderBox tkhd = new TrackHeaderBox();
-
- tkhd.setEnabled(true);
- tkhd.setInMovie(true);
- tkhd.setInPreview(true);
- if (track.isAudio()) {
- tkhd.setMatrix(Matrix.ROTATE_0);
- } else {
- tkhd.setMatrix(movie.getMatrix());
- }
- tkhd.setAlternateGroup(0);
- tkhd.setCreationTime(track.getCreationTime());
- tkhd.setDuration(track.getDuration() * getTimescale(movie) / track.getTimeScale());
- tkhd.setHeight(track.getHeight());
- tkhd.setWidth(track.getWidth());
- tkhd.setLayer(0);
- tkhd.setModificationTime(new Date());
- tkhd.setTrackId(track.getTrackId() + 1);
- tkhd.setVolume(track.getVolume());
-
- trackBox.addBox(tkhd);
-
- MediaBox mdia = new MediaBox();
- trackBox.addBox(mdia);
- MediaHeaderBox mdhd = new MediaHeaderBox();
- mdhd.setCreationTime(track.getCreationTime());
- mdhd.setDuration(track.getDuration());
- mdhd.setTimescale(track.getTimeScale());
- mdhd.setLanguage("eng");
- mdia.addBox(mdhd);
- HandlerBox hdlr = new HandlerBox();
- hdlr.setName(track.isAudio() ? "SoundHandle" : "VideoHandle");
- hdlr.setHandlerType(track.getHandler());
-
- mdia.addBox(hdlr);
-
- MediaInformationBox minf = new MediaInformationBox();
- minf.addBox(track.getMediaHeaderBox());
-
- DataInformationBox dinf = new DataInformationBox();
- DataReferenceBox dref = new DataReferenceBox();
- dinf.addBox(dref);
- DataEntryUrlBox url = new DataEntryUrlBox();
- url.setFlags(1);
- dref.addBox(url);
- minf.addBox(dinf);
-
- Box stbl = createStbl(track);
- minf.addBox(stbl);
- mdia.addBox(minf);
-
- return trackBox;
- }
-
- protected Box createStbl(Track track) {
- SampleTableBox stbl = new SampleTableBox();
-
- createStsd(track, stbl);
- createStts(track, stbl);
- createStss(track, stbl);
- createStsc(track, stbl);
- createStsz(track, stbl);
- createStco(track, stbl);
-
- return stbl;
- }
-
- protected void createStsd(Track track, SampleTableBox stbl) {
- stbl.addBox(track.getSampleDescriptionBox());
- }
-
- protected void createStts(Track track, SampleTableBox stbl) {
- TimeToSampleBox.Entry lastEntry = null;
- List<TimeToSampleBox.Entry> entries = new ArrayList<>();
-
- for (long delta : track.getSampleDurations()) {
- if (lastEntry != null && lastEntry.getDelta() == delta) {
- lastEntry.setCount(lastEntry.getCount() + 1);
- } else {
- lastEntry = new TimeToSampleBox.Entry(1, delta);
- entries.add(lastEntry);
- }
- }
- TimeToSampleBox stts = new TimeToSampleBox();
- stts.setEntries(entries);
- stbl.addBox(stts);
- }
-
- protected void createStss(Track track, SampleTableBox stbl) {
- long[] syncSamples = track.getSyncSamples();
- if (syncSamples != null && syncSamples.length > 0) {
- SyncSampleBox stss = new SyncSampleBox();
- stss.setSampleNumber(syncSamples);
- stbl.addBox(stss);
- }
- }
-
- protected void createStsc(Track track, SampleTableBox stbl) {
- SampleToChunkBox stsc = new SampleToChunkBox();
- stsc.setEntries(new LinkedList<SampleToChunkBox.Entry>());
-
- long lastOffset = -1;
- int lastChunkNumber = 1;
- int lastSampleCount = 0;
-
- int previousWritedChunkCount = -1;
-
- int samplesCount = track.getSamples().size();
- for (int a = 0; a < samplesCount; a++) {
- Sample sample = track.getSamples().get(a);
- long offset = sample.getOffset();
- long size = sample.getSize();
-
- lastOffset = offset + size;
- lastSampleCount++;
-
- boolean write = false;
- if (a != samplesCount - 1) {
- Sample nextSample = track.getSamples().get(a + 1);
- if (lastOffset != nextSample.getOffset()) {
- write = true;
- }
- } else {
- write = true;
- }
- if (write) {
- if (previousWritedChunkCount != lastSampleCount) {
- stsc.getEntries().add(new SampleToChunkBox.Entry(lastChunkNumber, lastSampleCount, 1));
- previousWritedChunkCount = lastSampleCount;
- }
- lastSampleCount = 0;
- lastChunkNumber++;
- }
- }
- stbl.addBox(stsc);
- }
-
- protected void createStsz(Track track, SampleTableBox stbl) {
- SampleSizeBox stsz = new SampleSizeBox();
- stsz.setSampleSizes(track2SampleSizes.get(track));
- stbl.addBox(stsz);
- }
-
- protected void createStco(Track track, SampleTableBox stbl) {
- ArrayList<Long> chunksOffsets = new ArrayList<>();
- long lastOffset = -1;
- for (Sample sample : track.getSamples()) {
- long offset = sample.getOffset();
- if (lastOffset != -1 && lastOffset != offset) {
- lastOffset = -1;
- }
- if (lastOffset == -1) {
- chunksOffsets.add(offset);
- }
- lastOffset = offset + sample.getSize();
- }
- long[] chunkOffsetsLong = new long[chunksOffsets.size()];
- for (int a = 0; a < chunksOffsets.size(); a++) {
- chunkOffsetsLong[a] = chunksOffsets.get(a);
- }
-
- StaticChunkOffsetBox stco = new StaticChunkOffsetBox();
- stco.setChunkOffsets(chunkOffsetsLong);
- stbl.addBox(stco);
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/MediaController.java b/src/main/java/de/pixart/messenger/utils/video/MediaController.java
deleted file mode 100644
index 2b47afade..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/MediaController.java
+++ /dev/null
@@ -1,649 +0,0 @@
-package de.pixart.messenger.utils.video;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.os.Build;
-import android.util.Log;
-
-import java.io.File;
-import java.nio.ByteBuffer;
-
-import de.pixart.messenger.Config;
-
-@SuppressLint("NewApi")
-public class MediaController {
-
- public final static String MIME_TYPE = "video/avc";
- private final static int PROCESSOR_TYPE_OTHER = 0;
- private final static int PROCESSOR_TYPE_QCOM = 1;
- private final static int PROCESSOR_TYPE_INTEL = 2;
- private final static int PROCESSOR_TYPE_MTK = 3;
- private final static int PROCESSOR_TYPE_SEC = 4;
- private final static int PROCESSOR_TYPE_TI = 5;
- private static volatile MediaController Instance = null;
- private boolean videoConvertFirstWrite = true;
- private int resultHeight = 0;
- private int resultWidth = 0;
-
- public static MediaController getInstance() {
- MediaController localInstance = Instance;
- if (localInstance == null) {
- synchronized (MediaController.class) {
- localInstance = Instance;
- if (localInstance == null) {
- Instance = localInstance = new MediaController();
- }
- }
- }
- return localInstance;
- }
-
- @SuppressLint("NewApi")
- public static int selectColorFormat(MediaCodecInfo codecInfo, String mimeType) {
- MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
- int lastColorFormat = 0;
- for (int i = 0; i < capabilities.colorFormats.length; i++) {
- int colorFormat = capabilities.colorFormats[i];
- if (isRecognizedFormat(colorFormat)) {
- lastColorFormat = colorFormat;
- if (!(codecInfo.getName().equals("OMX.SEC.AVC.Encoder") && colorFormat == 19)) {
- return colorFormat;
- }
- }
- }
- return lastColorFormat;
- }
-
- private static boolean isRecognizedFormat(int colorFormat) {
- switch (colorFormat) {
- case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
- case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
- case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
- case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
- case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
- return true;
- default:
- return false;
- }
- }
-
- public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap);
-
- private void didWriteData(final boolean last, final boolean error) {
- final boolean firstWrite = videoConvertFirstWrite;
- if (firstWrite) {
- videoConvertFirstWrite = false;
- }
- }
-
- public static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- MediaCodecInfo lastCodecInfo = null;
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
- if (!codecInfo.isEncoder()) {
- continue;
- }
- String[] types = codecInfo.getSupportedTypes();
- for (String type : types) {
- if (type.equalsIgnoreCase(mimeType)) {
- lastCodecInfo = codecInfo;
- if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
- return lastCodecInfo;
- } else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
- return lastCodecInfo;
- }
- }
- }
- }
- return lastCodecInfo;
- }
-
- @TargetApi(16)
- private long readAndWriteTrack(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, File file, boolean isAudio) throws Exception {
- int trackIndex = selectTrack(extractor, isAudio);
- if (trackIndex >= 0) {
- extractor.selectTrack(trackIndex);
- MediaFormat trackFormat = extractor.getTrackFormat(trackIndex);
- int muxerTrackIndex = mediaMuxer.addTrack(trackFormat, isAudio);
- int maxBufferSize = trackFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
- boolean inputDone = false;
- if (start > 0) {
- extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
- } else {
- extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
- }
- ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
- long startTime = -1;
-
- while (!inputDone) {
-
- boolean eof = false;
- int index = extractor.getSampleTrackIndex();
- if (index == trackIndex) {
- info.size = extractor.readSampleData(buffer, 0);
-
- if (info.size < 0) {
- info.size = 0;
- eof = true;
- } else {
- info.presentationTimeUs = extractor.getSampleTime();
- if (start > 0 && startTime == -1) {
- startTime = info.presentationTimeUs;
- }
- if (end < 0 || info.presentationTimeUs < end) {
- info.offset = 0;
- info.flags = extractor.getSampleFlags();
- if (mediaMuxer.writeSampleData(muxerTrackIndex, buffer, info, isAudio)) {
- // didWriteData(messageObject, file, false, false);
- }
- extractor.advance();
- } else {
- eof = true;
- }
- }
- } else if (index == -1) {
- eof = true;
- }
- if (eof) {
- inputDone = true;
- }
- }
-
- extractor.unselectTrack(trackIndex);
- return startTime;
- }
- return -1;
- }
-
- @TargetApi(16)
- private int selectTrack(MediaExtractor extractor, boolean audio) {
- int numTracks = extractor.getTrackCount();
- for (int i = 0; i < numTracks; i++) {
- MediaFormat format = extractor.getTrackFormat(i);
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (audio) {
- if (mime.startsWith("audio/")) {
- return i;
- }
- } else {
- if (mime.startsWith("video/")) {
- return i;
- }
- }
- }
- return -5;
- }
-
- @TargetApi(16)
- public boolean convertVideo(final String path, final String compressed_path) {
-
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- retriever.setDataSource(path);
- String height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
- String width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
- String rotation = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
-
- int video_height = Integer.parseInt(height);
- int video_width = Integer.parseInt(width);
-
- long startTime = -1;
- long endTime = -1;
-
- int rotationValue = Integer.valueOf(rotation);
- int originalWidth = Integer.valueOf(width);
- int originalHeight = Integer.valueOf(height);
- float ratio = (float) video_width / (float) video_height; // 16:9 = 1,7778, 4:3 = 1,3333
-
- if (video_height > video_width) {
- resultHeight = Config.VIDEO_SIZE;
- resultWidth = Math.round(resultHeight * ratio);
- } else if (video_width > video_height) {
- resultWidth = Config.VIDEO_SIZE;
- resultHeight = Math.round(resultWidth / ratio);
- }
-
- if (resultHeight > originalHeight) {
- resultHeight = originalHeight;
- }
-
- if (resultWidth > originalWidth) {
- resultWidth = originalWidth;
- }
-
- Log.d(Config.LOGTAG, "Video dimensions: height: " + video_height + " width: " + video_width + " rotation: " + rotation + " ratio: " + ratio);
- Log.d(Config.LOGTAG, "Video dimensions: Result height: " + resultHeight + " Result width: " + resultWidth + " rotation: " + rotation + " ratio: " + ratio);
-
- int bitrate = Config.VIDEO_BITRATE;
- int rotateRender = 0;
-
- File cacheFile = new File(compressed_path);
-
- if (Build.VERSION.SDK_INT < 18 && resultHeight > resultWidth && resultWidth != originalWidth && resultHeight != originalHeight) {
- int temp = resultHeight;
- resultHeight = resultWidth;
- resultWidth = temp;
- rotationValue = 90;
- rotateRender = 270;
- } else if (Build.VERSION.SDK_INT > 20) {
- if (rotationValue == 90) {
- int temp = resultHeight;
- resultHeight = resultWidth;
- resultWidth = temp;
- rotationValue = 0;
- rotateRender = 270;
- } else if (rotationValue == 180) {
- rotateRender = 180;
- rotationValue = 0;
- } else if (rotationValue == 270) {
- int temp = resultHeight;
- resultHeight = resultWidth;
- resultWidth = temp;
- rotationValue = 0;
- rotateRender = 90;
- }
- }
-
-
- File inputFile = new File(path);
- Log.d(Config.LOGTAG, "Input file is: " + inputFile.toString());
- if (!inputFile.canRead()) {
- didWriteData(true, true);
- Log.d(Config.LOGTAG, "Compression failed. Input file could not be read.");
- return false;
- }
-
- videoConvertFirstWrite = true;
- boolean error = false;
- long videoStartTime = startTime;
-
- long time = System.currentTimeMillis();
-
- if (resultWidth != 0 && resultHeight != 0) {
- MP4Builder mediaMuxer = null;
- MediaExtractor extractor = null;
-
- try {
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
- Mp4Movie movie = new Mp4Movie();
- movie.setCacheFile(cacheFile);
- movie.setRotation(rotationValue);
- movie.setSize(resultWidth, resultHeight);
- mediaMuxer = new MP4Builder().createMovie(movie);
- extractor = new MediaExtractor();
- extractor.setDataSource(inputFile.toString());
-
-
- if (resultWidth != originalWidth || resultHeight != originalHeight) {
- int videoIndex;
- videoIndex = selectTrack(extractor, false);
-
- if (videoIndex >= 0) {
- MediaCodec decoder = null;
- MediaCodec encoder = null;
- InputSurface inputSurface = null;
- OutputSurface outputSurface = null;
-
- try {
- long videoTime = -1;
- boolean outputDone = false;
- boolean inputDone = false;
- boolean decoderDone = false;
- int swapUV = 0;
- int videoTrackIndex = -5;
-
- int colorFormat;
- int processorType = PROCESSOR_TYPE_OTHER;
- String manufacturer = Build.MANUFACTURER.toLowerCase();
- if (Build.VERSION.SDK_INT < 18) {
- MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
- colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
- if (colorFormat == 0) {
- throw new RuntimeException("no supported color format");
- }
- String codecName = codecInfo.getName();
- if (codecName.contains("OMX.qcom.")) {
- processorType = PROCESSOR_TYPE_QCOM;
- if (Build.VERSION.SDK_INT == 16) {
- if (manufacturer.equals("lge") || manufacturer.equals("nokia")) {
- swapUV = 1;
- }
- }
- } else if (codecName.contains("OMX.Intel.")) {
- processorType = PROCESSOR_TYPE_INTEL;
- } else if (codecName.equals("OMX.MTK.VIDEO.ENCODER.AVC")) {
- processorType = PROCESSOR_TYPE_MTK;
- } else if (codecName.equals("OMX.SEC.AVC.Encoder")) {
- processorType = PROCESSOR_TYPE_SEC;
- swapUV = 1;
- } else if (codecName.equals("OMX.TI.DUCATI1.VIDEO.H264E")) {
- processorType = PROCESSOR_TYPE_TI;
- }
- Log.d(Config.LOGTAG, "codec = " + codecInfo.getName() + " manufacturer = " + manufacturer + "device = " + Build.MODEL);
- } else {
- colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
- }
- Log.d(Config.LOGTAG, "colorFormat = " + colorFormat);
-
- int resultHeightAligned = resultHeight;
- int padding = 0;
- int bufferSize = resultWidth * resultHeight * 3 / 2;
- if (processorType == PROCESSOR_TYPE_OTHER) {
- if (resultHeight % 16 != 0) {
- resultHeightAligned += (16 - (resultHeight % 16));
- padding = resultWidth * (resultHeightAligned - resultHeight);
- bufferSize += padding * 5 / 4;
- }
- } else if (processorType == PROCESSOR_TYPE_QCOM) {
- if (!manufacturer.toLowerCase().equals("lge")) {
- int uvoffset = (resultWidth * resultHeight + 2047) & ~2047;
- padding = uvoffset - (resultWidth * resultHeight);
- bufferSize += padding;
- }
- } else if (processorType == PROCESSOR_TYPE_TI) {
- resultHeightAligned = 368;
- bufferSize = resultWidth * resultHeightAligned * 3 / 2;
- resultHeightAligned += (16 - (resultHeight % 16));
- padding = resultWidth * (resultHeightAligned - resultHeight);
- bufferSize += padding * 5 / 4;
- } else if (processorType == PROCESSOR_TYPE_MTK) {
- if (manufacturer.equals("baidu")) {
- resultHeightAligned += (16 - (resultHeight % 16));
- padding = resultWidth * (resultHeightAligned - resultHeight);
- bufferSize += padding * 5 / 4;
- }
- }
-
- extractor.selectTrack(videoIndex);
- if (startTime > 0) {
- extractor.seekTo(startTime, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
- } else {
- extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
- }
- MediaFormat inputFormat = extractor.getTrackFormat(videoIndex);
-
- MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight);
- outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
- outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate != 0 ? bitrate : 921600);
- outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 25);
- outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
- if (Build.VERSION.SDK_INT < 18) {
- outputFormat.setInteger("stride", resultWidth + 32);
- outputFormat.setInteger("slice-height", resultHeight);
- }
-
- encoder = MediaCodec.createEncoderByType(MIME_TYPE);
- encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- if (Build.VERSION.SDK_INT >= 18) {
- inputSurface = new InputSurface(encoder.createInputSurface());
- inputSurface.makeCurrent();
- }
- encoder.start();
-
- decoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
- if (Build.VERSION.SDK_INT >= 18) {
- outputSurface = new OutputSurface();
- } else {
- outputSurface = new OutputSurface(resultWidth, resultHeight, rotateRender);
- }
- decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
- decoder.start();
-
- final int TIMEOUT_USEC = 2500;
- ByteBuffer[] decoderInputBuffers = null;
- ByteBuffer[] encoderOutputBuffers = null;
- ByteBuffer[] encoderInputBuffers = null;
- if (Build.VERSION.SDK_INT < 21) {
- decoderInputBuffers = decoder.getInputBuffers();
- encoderOutputBuffers = encoder.getOutputBuffers();
- if (Build.VERSION.SDK_INT < 18) {
- encoderInputBuffers = encoder.getInputBuffers();
- }
- }
-
- while (!outputDone) {
- if (!inputDone) {
- boolean eof = false;
- int index = extractor.getSampleTrackIndex();
- if (index == videoIndex) {
- int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
- if (inputBufIndex >= 0) {
- ByteBuffer inputBuf;
- if (Build.VERSION.SDK_INT < 21) {
- inputBuf = decoderInputBuffers[inputBufIndex];
- } else {
- inputBuf = decoder.getInputBuffer(inputBufIndex);
- }
- int chunkSize = extractor.readSampleData(inputBuf, 0);
- if (chunkSize < 0) {
- decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- inputDone = true;
- } else {
- decoder.queueInputBuffer(inputBufIndex, 0, chunkSize, extractor.getSampleTime(), 0);
- extractor.advance();
- }
- }
- } else if (index == -1) {
- eof = true;
- }
- if (eof) {
- int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
- if (inputBufIndex >= 0) {
- decoder.queueInputBuffer(inputBufIndex, 0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- inputDone = true;
- }
- }
- }
-
- boolean decoderOutputAvailable = !decoderDone;
- boolean encoderOutputAvailable = true;
- while (decoderOutputAvailable || encoderOutputAvailable) {
- int encoderStatus = encoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
- if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
- encoderOutputAvailable = false;
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- if (Build.VERSION.SDK_INT < 21) {
- encoderOutputBuffers = encoder.getOutputBuffers();
- }
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- MediaFormat newFormat = encoder.getOutputFormat();
- if (videoTrackIndex == -5) {
- videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
- }
- } else if (encoderStatus < 0) {
- throw new RuntimeException("unexpected result from encoder.dequeueOutputBuffer: " + encoderStatus);
- } else {
- ByteBuffer encodedData;
- if (Build.VERSION.SDK_INT < 21) {
- encodedData = encoderOutputBuffers[encoderStatus];
- } else {
- encodedData = encoder.getOutputBuffer(encoderStatus);
- }
- if (encodedData == null) {
- throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
- }
- if (info.size > 1) {
- if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- if (mediaMuxer.writeSampleData(videoTrackIndex, encodedData, info, false)) {
- didWriteData(false, false);
- }
- } else if (videoTrackIndex == -5) {
- byte[] csd = new byte[info.size];
- encodedData.limit(info.offset + info.size);
- encodedData.position(info.offset);
- encodedData.get(csd);
- ByteBuffer sps = null;
- ByteBuffer pps = null;
- for (int a = info.size - 1; a >= 0; a--) {
- if (a > 3) {
- if (csd[a] == 1 && csd[a - 1] == 0 && csd[a - 2] == 0 && csd[a - 3] == 0) {
- sps = ByteBuffer.allocate(a - 3);
- pps = ByteBuffer.allocate(info.size - (a - 3));
- sps.put(csd, 0, a - 3).position(0);
- pps.put(csd, a - 3, info.size - (a - 3)).position(0);
- break;
- }
- } else {
- break;
- }
- }
-
- MediaFormat newFormat = MediaFormat.createVideoFormat(MIME_TYPE, resultWidth, resultHeight);
- if (sps != null && pps != null) {
- newFormat.setByteBuffer("csd-0", sps);
- newFormat.setByteBuffer("csd-1", pps);
- }
- videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
- }
- }
- outputDone = (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;
- encoder.releaseOutputBuffer(encoderStatus, false);
- }
- if (encoderStatus != MediaCodec.INFO_TRY_AGAIN_LATER) {
- continue;
- }
-
- if (!decoderDone) {
- int decoderStatus = decoder.dequeueOutputBuffer(info, TIMEOUT_USEC);
- if (decoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
- decoderOutputAvailable = false;
- } else if (decoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-
- } else if (decoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- MediaFormat newFormat = decoder.getOutputFormat();
- Log.d(Config.LOGTAG, "newFormat = " + newFormat);
- } else if (decoderStatus < 0) {
- throw new RuntimeException("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
- } else {
- boolean doRender;
- if (Build.VERSION.SDK_INT >= 18) {
- doRender = info.size != 0;
- } else {
- doRender = info.size != 0 || info.presentationTimeUs != 0;
- }
- if (endTime > 0 && info.presentationTimeUs >= endTime) {
- inputDone = true;
- decoderDone = true;
- doRender = false;
- info.flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
- }
- if (startTime > 0 && videoTime == -1) {
- if (info.presentationTimeUs < startTime) {
- doRender = false;
- Log.d(Config.LOGTAG, "drop frame startTime = " + startTime + " present time = " + info.presentationTimeUs);
- } else {
- videoTime = info.presentationTimeUs;
- }
- }
- decoder.releaseOutputBuffer(decoderStatus, doRender);
- if (doRender) {
- boolean errorWait = false;
- try {
- outputSurface.awaitNewImage();
- } catch (Exception e) {
- errorWait = true;
- Log.d(Config.LOGTAG, e.getMessage());
- }
- if (!errorWait) {
- if (Build.VERSION.SDK_INT >= 18) {
- outputSurface.drawImage(false);
- inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
- inputSurface.swapBuffers();
- } else {
- int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
- if (inputBufIndex >= 0) {
- outputSurface.drawImage(true);
- ByteBuffer rgbBuf = outputSurface.getFrame();
- ByteBuffer yuvBuf = encoderInputBuffers[inputBufIndex];
- yuvBuf.clear();
- convertVideoFrame(rgbBuf, yuvBuf, colorFormat, resultWidth, resultHeight, padding, swapUV);
- encoder.queueInputBuffer(inputBufIndex, 0, bufferSize, info.presentationTimeUs, 0);
- } else {
- Log.d(Config.LOGTAG, "input buffer not available");
- }
- }
- }
- }
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- decoderOutputAvailable = false;
- Log.d(Config.LOGTAG, "decoder stream end");
- if (Build.VERSION.SDK_INT >= 18) {
- encoder.signalEndOfInputStream();
- } else {
- int inputBufIndex = encoder.dequeueInputBuffer(TIMEOUT_USEC);
- if (inputBufIndex >= 0) {
- encoder.queueInputBuffer(inputBufIndex, 0, 1, info.presentationTimeUs, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- }
- }
- }
- }
- }
- }
- }
- if (videoTime != -1) {
- videoStartTime = videoTime;
- }
- } catch (Exception e) {
- Log.d(Config.LOGTAG, e.getMessage());
- error = true;
- }
-
- extractor.unselectTrack(videoIndex);
-
- if (outputSurface != null) {
- outputSurface.release();
- }
- if (inputSurface != null) {
- inputSurface.release();
- }
- if (decoder != null) {
- decoder.stop();
- decoder.release();
- }
- if (encoder != null) {
- encoder.stop();
- encoder.release();
- }
- }
- } else {
- long videoTime = readAndWriteTrack(extractor, mediaMuxer, info, startTime, endTime, cacheFile, false);
- if (videoTime != -1) {
- videoStartTime = videoTime;
- }
- }
- if (!error) {
- readAndWriteTrack(extractor, mediaMuxer, info, videoStartTime, endTime, cacheFile, true);
- }
- } catch (Exception e) {
- error = true;
- Log.d(Config.LOGTAG, e.getMessage());
- } finally {
- if (extractor != null) {
- extractor.release();
- }
- if (mediaMuxer != null) {
- try {
- mediaMuxer.finishMovie(false);
- } catch (Exception e) {
- Log.d(Config.LOGTAG, e.getMessage());
- }
- }
- Log.d(Config.LOGTAG, "time = " + (System.currentTimeMillis() - time));
- }
- } else {
- didWriteData(true, true);
- Log.d(Config.LOGTAG, "Compression failed.");
- return false;
- }
- didWriteData(true, error);
- Log.d(Config.LOGTAG, "Compression succeed. Save compressed video to " + cacheFile.toString());
- //inputFile.delete();
- return true;
- }
-} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java b/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java
deleted file mode 100644
index 4cf206d26..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/Mp4Movie.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * This is the source code of Telegram for Android v. 1.7.x.
- * It is licensed under GNU GPL v. 2 or later.
- * You should have received a copy of the license in this archive (see LICENSE).
- *
- * Copyright Nikolai Kudashov, 2013-2014.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-
-import com.googlecode.mp4parser.util.Matrix;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@TargetApi(16)
-public class Mp4Movie {
- private Matrix matrix = Matrix.ROTATE_0;
- private ArrayList<Track> tracks = new ArrayList<Track>();
- private File cacheFile;
- private int width;
- private int height;
-
- public Matrix getMatrix() {
- return matrix;
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public void setCacheFile(File file) {
- cacheFile = file;
- }
-
- public void setRotation(int angle) {
- if (angle == 0) {
- matrix = Matrix.ROTATE_0;
- } else if (angle == 90) {
- matrix = Matrix.ROTATE_90;
- } else if (angle == 180) {
- matrix = Matrix.ROTATE_180;
- } else if (angle == 270) {
- matrix = Matrix.ROTATE_270;
- }
- }
-
- public void setSize(int w, int h) {
- width = w;
- height = h;
- }
-
- public ArrayList<Track> getTracks() {
- return tracks;
- }
-
- public File getCacheFile() {
- return cacheFile;
- }
-
- public void addSample(int trackIndex, long offset, MediaCodec.BufferInfo bufferInfo) throws Exception {
- if (trackIndex < 0 || trackIndex >= tracks.size()) {
- return;
- }
- Track track = tracks.get(trackIndex);
- track.addSample(offset, bufferInfo);
- }
-
- public int addTrack(MediaFormat mediaFormat, boolean isAudio) throws Exception {
- tracks.add(new Track(tracks.size(), mediaFormat, isAudio));
- return tracks.size() - 1;
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java b/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java
deleted file mode 100644
index 75ceb46ac..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/OutputSurface.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
-import android.view.Surface;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-
-@TargetApi(16)
-public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
-
- private static final int EGL_OPENGL_ES2_BIT = 4;
- private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- private EGL10 mEGL;
- private EGLDisplay mEGLDisplay = null;
- private EGLContext mEGLContext = null;
- private EGLSurface mEGLSurface = null;
- private SurfaceTexture mSurfaceTexture;
- private Surface mSurface;
- private final Object mFrameSyncObject = new Object();
- private boolean mFrameAvailable;
- private TextureRenderer mTextureRender;
- private int mWidth;
- private int mHeight;
- private int rotateRender = 0;
- private ByteBuffer mPixelBuf;
-
- public OutputSurface(int width, int height, int rotate) {
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException();
- }
- mWidth = width;
- mHeight = height;
- rotateRender = rotate;
- mPixelBuf = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
- mPixelBuf.order(ByteOrder.LITTLE_ENDIAN);
- eglSetup(width, height);
- makeCurrent();
- setup();
- }
-
- public OutputSurface() {
- setup();
- }
-
- private void setup() {
- mTextureRender = new TextureRenderer(rotateRender);
- mTextureRender.surfaceCreated();
- mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
- mSurfaceTexture.setOnFrameAvailableListener(this);
- mSurface = new Surface(mSurfaceTexture);
- }
-
- private void eglSetup(int width, int height) {
- mEGL = (EGL10) EGLContext.getEGL();
- mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
- if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) {
- throw new RuntimeException("unable to get EGL10 display");
- }
-
- if (!mEGL.eglInitialize(mEGLDisplay, null)) {
- mEGLDisplay = null;
- throw new RuntimeException("unable to initialize EGL10");
- }
-
- int[] attribList = {
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
- EGL10.EGL_ALPHA_SIZE, 8,
- EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
- EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL10.EGL_NONE
- };
- EGLConfig[] configs = new EGLConfig[1];
- int[] numConfigs = new int[1];
- if (!mEGL.eglChooseConfig(mEGLDisplay, attribList, configs, configs.length, numConfigs)) {
- throw new RuntimeException("unable to find RGB888+pbuffer EGL config");
- }
- int[] attrib_list = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL10.EGL_NONE
- };
- mEGLContext = mEGL.eglCreateContext(mEGLDisplay, configs[0], EGL10.EGL_NO_CONTEXT, attrib_list);
- checkEglError("eglCreateContext");
- if (mEGLContext == null) {
- throw new RuntimeException("null context");
- }
- int[] surfaceAttribs = {
- EGL10.EGL_WIDTH, width,
- EGL10.EGL_HEIGHT, height,
- EGL10.EGL_NONE
- };
- mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs);
- checkEglError("eglCreatePbufferSurface");
- if (mEGLSurface == null) {
- throw new RuntimeException("surface was null");
- }
- }
-
- public void release() {
- if (mEGL != null) {
- if (mEGL.eglGetCurrentContext().equals(mEGLContext)) {
- mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- }
- mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface);
- mEGL.eglDestroyContext(mEGLDisplay, mEGLContext);
- }
- mSurface.release();
- mEGLDisplay = null;
- mEGLContext = null;
- mEGLSurface = null;
- mEGL = null;
- mTextureRender = null;
- mSurface = null;
- mSurfaceTexture = null;
- }
-
- public void makeCurrent() {
- if (mEGL == null) {
- throw new RuntimeException("not configured for makeCurrent");
- }
- checkEglError("before makeCurrent");
- if (!mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
- throw new RuntimeException("eglMakeCurrent failed");
- }
- }
-
- public Surface getSurface() {
- return mSurface;
- }
-
- public void changeFragmentShader(String fragmentShader) {
- mTextureRender.changeFragmentShader(fragmentShader);
- }
-
- public void awaitNewImage() {
- final int TIMEOUT_MS = 5000;
- synchronized (mFrameSyncObject) {
- while (!mFrameAvailable) {
- try {
- mFrameSyncObject.wait(TIMEOUT_MS);
- if (!mFrameAvailable) {
- throw new RuntimeException("Surface frame wait timed out");
- }
- } catch (InterruptedException ie) {
- throw new RuntimeException(ie);
- }
- }
- mFrameAvailable = false;
- }
- mTextureRender.checkGlError("before updateTexImage");
- mSurfaceTexture.updateTexImage();
- }
-
- public void drawImage(boolean invert) {
- mTextureRender.drawFrame(mSurfaceTexture, invert);
- }
-
- @Override
- public void onFrameAvailable(SurfaceTexture st) {
- synchronized (mFrameSyncObject) {
- if (mFrameAvailable) {
- throw new RuntimeException("mFrameAvailable already set, frame could be dropped");
- }
- mFrameAvailable = true;
- mFrameSyncObject.notifyAll();
- }
- }
-
- public ByteBuffer getFrame() {
- mPixelBuf.rewind();
- GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
- return mPixelBuf;
- }
-
- private void checkEglError(String msg) {
- if (mEGL.eglGetError() != EGL10.EGL_SUCCESS) {
- throw new RuntimeException("EGL error encountered (see log)");
- }
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/Sample.java b/src/main/java/de/pixart/messenger/utils/video/Sample.java
deleted file mode 100644
index f00ee5311..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/Sample.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This is the source code of Telegram for Android v. 1.7.x.
- * It is licensed under GNU GPL v. 2 or later.
- * You should have received a copy of the license in this archive (see LICENSE).
- *
- * Copyright Nikolai Kudashov, 2013-2014.
- */
-
-package de.pixart.messenger.utils.video;
-
-public class Sample {
- private long offset = 0;
- private long size = 0;
-
- public Sample(long offset, long size) {
- this.offset = offset;
- this.size = size;
- }
-
- public long getOffset() {
- return offset;
- }
-
- public long getSize() {
- return size;
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java b/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java
deleted file mode 100644
index 3c53941ea..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/TextureRenderer.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.graphics.SurfaceTexture;
-import android.opengl.GLES11Ext;
-import android.opengl.GLES20;
-import android.opengl.Matrix;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-@TargetApi(16)
-public class TextureRenderer {
-
- private static final int FLOAT_SIZE_BYTES = 4;
- private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
- private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
- private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
- private static final float[] mTriangleVerticesData = {
- -1.0f, -1.0f, 0, 0.f, 0.f,
- 1.0f, -1.0f, 0, 1.f, 0.f,
- -1.0f, 1.0f, 0, 0.f, 1.f,
- 1.0f, 1.0f, 0, 1.f, 1.f,
- };
- private FloatBuffer mTriangleVertices;
-
- private static final String VERTEX_SHADER =
- "uniform mat4 uMVPMatrix;\n" +
- "uniform mat4 uSTMatrix;\n" +
- "attribute vec4 aPosition;\n" +
- "attribute vec4 aTextureCoord;\n" +
- "varying vec2 vTextureCoord;\n" +
- "void main() {\n" +
- " gl_Position = uMVPMatrix * aPosition;\n" +
- " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
- "}\n";
-
- private static final String FRAGMENT_SHADER =
- "#extension GL_OES_EGL_image_external : require\n" +
- "precision mediump float;\n" +
- "varying vec2 vTextureCoord;\n" +
- "uniform samplerExternalOES sTexture;\n" +
- "void main() {\n" +
- " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
- "}\n";
-
- private float[] mMVPMatrix = new float[16];
- private float[] mSTMatrix = new float[16];
- private int mProgram;
- private int mTextureID = -12345;
- private int muMVPMatrixHandle;
- private int muSTMatrixHandle;
- private int maPositionHandle;
- private int maTextureHandle;
- private int rotationAngle = 0;
-
- public TextureRenderer(int rotation) {
- rotationAngle = rotation;
- mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
- mTriangleVertices.put(mTriangleVerticesData).position(0);
- Matrix.setIdentityM(mSTMatrix, 0);
- }
-
- public int getTextureId() {
- return mTextureID;
- }
-
- public void drawFrame(SurfaceTexture st, boolean invert) {
- checkGlError("onDrawFrame start");
- st.getTransformMatrix(mSTMatrix);
-
- if (invert) {
- mSTMatrix[5] = -mSTMatrix[5];
- mSTMatrix[13] = 1.0f - mSTMatrix[13];
- }
-
- GLES20.glUseProgram(mProgram);
- checkGlError("glUseProgram");
- GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
- GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
- mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
- GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
- checkGlError("glVertexAttribPointer maPosition");
- GLES20.glEnableVertexAttribArray(maPositionHandle);
- checkGlError("glEnableVertexAttribArray maPositionHandle");
- mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
- GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
- checkGlError("glVertexAttribPointer maTextureHandle");
- GLES20.glEnableVertexAttribArray(maTextureHandle);
- checkGlError("glEnableVertexAttribArray maTextureHandle");
- GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
- GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
- GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
- checkGlError("glDrawArrays");
- GLES20.glFinish();
- }
-
- public void surfaceCreated() {
- mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
- if (mProgram == 0) {
- throw new RuntimeException("failed creating program");
- }
- maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
- checkGlError("glGetAttribLocation aPosition");
- if (maPositionHandle == -1) {
- throw new RuntimeException("Could not get attrib location for aPosition");
- }
- maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
- checkGlError("glGetAttribLocation aTextureCoord");
- if (maTextureHandle == -1) {
- throw new RuntimeException("Could not get attrib location for aTextureCoord");
- }
- muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
- checkGlError("glGetUniformLocation uMVPMatrix");
- if (muMVPMatrixHandle == -1) {
- throw new RuntimeException("Could not get attrib location for uMVPMatrix");
- }
- muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
- checkGlError("glGetUniformLocation uSTMatrix");
- if (muSTMatrixHandle == -1) {
- throw new RuntimeException("Could not get attrib location for uSTMatrix");
- }
- int[] textures = new int[1];
- GLES20.glGenTextures(1, textures, 0);
- mTextureID = textures[0];
- GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
- checkGlError("glBindTexture mTextureID");
- GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
- GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
- GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
- GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
- checkGlError("glTexParameter");
-
- Matrix.setIdentityM(mMVPMatrix, 0);
- if (rotationAngle != 0) {
- Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
- }
- }
-
- public void changeFragmentShader(String fragmentShader) {
- GLES20.glDeleteProgram(mProgram);
- mProgram = createProgram(VERTEX_SHADER, fragmentShader);
- if (mProgram == 0) {
- throw new RuntimeException("failed creating program");
- }
- }
-
- private int loadShader(int shaderType, String source) {
- int shader = GLES20.glCreateShader(shaderType);
- checkGlError("glCreateShader type=" + shaderType);
- GLES20.glShaderSource(shader, source);
- GLES20.glCompileShader(shader);
- int[] compiled = new int[1];
- GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
- if (compiled[0] == 0) {
- GLES20.glDeleteShader(shader);
- shader = 0;
- }
- return shader;
- }
-
- private int createProgram(String vertexSource, String fragmentSource) {
- int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
- if (vertexShader == 0) {
- return 0;
- }
- int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
- if (pixelShader == 0) {
- return 0;
- }
- int program = GLES20.glCreateProgram();
- checkGlError("glCreateProgram");
- if (program == 0) {
- return 0;
- }
- GLES20.glAttachShader(program, vertexShader);
- checkGlError("glAttachShader");
- GLES20.glAttachShader(program, pixelShader);
- checkGlError("glAttachShader");
- GLES20.glLinkProgram(program);
- int[] linkStatus = new int[1];
- GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
- if (linkStatus[0] != GLES20.GL_TRUE) {
- GLES20.glDeleteProgram(program);
- program = 0;
- }
- return program;
- }
-
- public void checkGlError(String op) {
- int error;
- if ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
- throw new RuntimeException(op + ": glError " + error);
- }
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/video/Track.java b/src/main/java/de/pixart/messenger/utils/video/Track.java
deleted file mode 100644
index 18111a675..000000000
--- a/src/main/java/de/pixart/messenger/utils/video/Track.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * This is the source code of Telegram for Android v. 1.7.x.
- * It is licensed under GNU GPL v. 2 or later.
- * You should have received a copy of the license in this archive (see LICENSE).
- *
- * Copyright Nikolai Kudashov, 2013-2014.
- */
-
-package de.pixart.messenger.utils.video;
-
-import android.annotation.TargetApi;
-import android.media.MediaCodec;
-import android.media.MediaFormat;
-
-import com.coremedia.iso.boxes.AbstractMediaHeaderBox;
-import com.coremedia.iso.boxes.SampleDescriptionBox;
-import com.coremedia.iso.boxes.SoundMediaHeaderBox;
-import com.coremedia.iso.boxes.VideoMediaHeaderBox;
-import com.coremedia.iso.boxes.sampleentry.AudioSampleEntry;
-import com.coremedia.iso.boxes.sampleentry.VisualSampleEntry;
-import com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox;
-import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.AudioSpecificConfig;
-import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.DecoderConfigDescriptor;
-import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor;
-import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.SLConfigDescriptor;
-import com.mp4parser.iso14496.part15.AvcConfigurationBox;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-
-@TargetApi(16)
-public class Track {
- private long trackId = 0;
- private ArrayList<Sample> samples = new ArrayList<Sample>();
- private long duration = 0;
- private String handler;
- private AbstractMediaHeaderBox headerBox = null;
- private SampleDescriptionBox sampleDescriptionBox = null;
- private LinkedList<Integer> syncSamples = null;
- private int timeScale;
- private Date creationTime = new Date();
- private int height;
- private int width;
- private float volume = 0;
- private ArrayList<Long> sampleDurations = new ArrayList<Long>();
- private boolean isAudio = false;
- private static Map<Integer, Integer> samplingFrequencyIndexMap = new HashMap<Integer, Integer>();
- private long lastPresentationTimeUs = 0;
- private boolean first = true;
-
- static {
- samplingFrequencyIndexMap.put(96000, 0x0);
- samplingFrequencyIndexMap.put(88200, 0x1);
- samplingFrequencyIndexMap.put(64000, 0x2);
- samplingFrequencyIndexMap.put(48000, 0x3);
- samplingFrequencyIndexMap.put(44100, 0x4);
- samplingFrequencyIndexMap.put(32000, 0x5);
- samplingFrequencyIndexMap.put(24000, 0x6);
- samplingFrequencyIndexMap.put(22050, 0x7);
- samplingFrequencyIndexMap.put(16000, 0x8);
- samplingFrequencyIndexMap.put(12000, 0x9);
- samplingFrequencyIndexMap.put(11025, 0xa);
- samplingFrequencyIndexMap.put(8000, 0xb);
- }
-
- public Track(int id, MediaFormat format, boolean isAudio) throws Exception {
- trackId = id;
- if (!isAudio) {
- sampleDurations.add((long) 3015);
- duration = 3015;
- width = format.getInteger(MediaFormat.KEY_WIDTH);
- height = format.getInteger(MediaFormat.KEY_HEIGHT);
- timeScale = 90000;
- syncSamples = new LinkedList<Integer>();
- handler = "vide";
- headerBox = new VideoMediaHeaderBox();
- sampleDescriptionBox = new SampleDescriptionBox();
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (mime.equals("video/avc")) {
- VisualSampleEntry visualSampleEntry = new VisualSampleEntry("avc1");
- visualSampleEntry.setDataReferenceIndex(1);
- visualSampleEntry.setDepth(24);
- visualSampleEntry.setFrameCount(1);
- visualSampleEntry.setHorizresolution(72);
- visualSampleEntry.setVertresolution(72);
- visualSampleEntry.setWidth(width);
- visualSampleEntry.setHeight(height);
-
- AvcConfigurationBox avcConfigurationBox = new AvcConfigurationBox();
-
- if (format.getByteBuffer("csd-0") != null) {
- ArrayList<byte[]> spsArray = new ArrayList<byte[]>();
- ByteBuffer spsBuff = format.getByteBuffer("csd-0");
- spsBuff.position(4);
- byte[] spsBytes = new byte[spsBuff.remaining()];
- spsBuff.get(spsBytes);
- spsArray.add(spsBytes);
-
- ArrayList<byte[]> ppsArray = new ArrayList<byte[]>();
- ByteBuffer ppsBuff = format.getByteBuffer("csd-1");
- ppsBuff.position(4);
- byte[] ppsBytes = new byte[ppsBuff.remaining()];
- ppsBuff.get(ppsBytes);
- ppsArray.add(ppsBytes);
- avcConfigurationBox.setSequenceParameterSets(spsArray);
- avcConfigurationBox.setPictureParameterSets(ppsArray);
- }
- //ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(spsBytes);
- //SeqParameterSet seqParameterSet = SeqParameterSet.read(byteArrayInputStream);
-
- avcConfigurationBox.setAvcLevelIndication(13);
- avcConfigurationBox.setAvcProfileIndication(100);
- avcConfigurationBox.setBitDepthLumaMinus8(-1);
- avcConfigurationBox.setBitDepthChromaMinus8(-1);
- avcConfigurationBox.setChromaFormat(-1);
- avcConfigurationBox.setConfigurationVersion(1);
- avcConfigurationBox.setLengthSizeMinusOne(3);
- avcConfigurationBox.setProfileCompatibility(0);
-
- visualSampleEntry.addBox(avcConfigurationBox);
- sampleDescriptionBox.addBox(visualSampleEntry);
- } else if (mime.equals("video/mp4v")) {
- VisualSampleEntry visualSampleEntry = new VisualSampleEntry("mp4v");
- visualSampleEntry.setDataReferenceIndex(1);
- visualSampleEntry.setDepth(24);
- visualSampleEntry.setFrameCount(1);
- visualSampleEntry.setHorizresolution(72);
- visualSampleEntry.setVertresolution(72);
- visualSampleEntry.setWidth(width);
- visualSampleEntry.setHeight(height);
-
- sampleDescriptionBox.addBox(visualSampleEntry);
- }
- } else {
- sampleDurations.add((long) 1024);
- duration = 1024;
- isAudio = true;
- volume = 1;
- timeScale = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
- handler = "soun";
- headerBox = new SoundMediaHeaderBox();
- sampleDescriptionBox = new SampleDescriptionBox();
- AudioSampleEntry audioSampleEntry = new AudioSampleEntry("mp4a");
- audioSampleEntry.setChannelCount(format.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
- audioSampleEntry.setSampleRate(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
- audioSampleEntry.setDataReferenceIndex(1);
- audioSampleEntry.setSampleSize(16);
-
- ESDescriptorBox esds = new ESDescriptorBox();
- ESDescriptor descriptor = new ESDescriptor();
- descriptor.setEsId(0);
-
- SLConfigDescriptor slConfigDescriptor = new SLConfigDescriptor();
- slConfigDescriptor.setPredefined(2);
- descriptor.setSlConfigDescriptor(slConfigDescriptor);
-
- DecoderConfigDescriptor decoderConfigDescriptor = new DecoderConfigDescriptor();
- decoderConfigDescriptor.setObjectTypeIndication(0x40);
- decoderConfigDescriptor.setStreamType(5);
- decoderConfigDescriptor.setBufferSizeDB(1536);
- decoderConfigDescriptor.setMaxBitRate(96000);
- decoderConfigDescriptor.setAvgBitRate(96000);
-
- AudioSpecificConfig audioSpecificConfig = new AudioSpecificConfig();
- audioSpecificConfig.setAudioObjectType(2);
- audioSpecificConfig.setSamplingFrequencyIndex(samplingFrequencyIndexMap.get((int) audioSampleEntry.getSampleRate()));
- audioSpecificConfig.setChannelConfiguration(audioSampleEntry.getChannelCount());
- decoderConfigDescriptor.setAudioSpecificInfo(audioSpecificConfig);
-
- descriptor.setDecoderConfigDescriptor(decoderConfigDescriptor);
-
- ByteBuffer data = descriptor.serialize();
- esds.setEsDescriptor(descriptor);
- esds.setData(data);
- audioSampleEntry.addBox(esds);
- sampleDescriptionBox.addBox(audioSampleEntry);
- }
- }
-
- public long getTrackId() {
- return trackId;
- }
-
- public void addSample(long offset, MediaCodec.BufferInfo bufferInfo) {
- boolean isSyncFrame = !isAudio && (bufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0;
- samples.add(new Sample(offset, bufferInfo.size));
- if (syncSamples != null && isSyncFrame) {
- syncSamples.add(samples.size());
- }
-
- long delta = bufferInfo.presentationTimeUs - lastPresentationTimeUs;
- lastPresentationTimeUs = bufferInfo.presentationTimeUs;
- delta = (delta * timeScale + 500000L) / 1000000L;
- if (!first) {
- sampleDurations.add(sampleDurations.size() - 1, delta);
- duration += delta;
- }
- first = false;
- }
-
- public ArrayList<Sample> getSamples() {
- return samples;
- }
-
- public long getDuration() {
- return duration;
- }
-
- public String getHandler() {
- return handler;
- }
-
- public AbstractMediaHeaderBox getMediaHeaderBox() {
- return headerBox;
- }
-
- public SampleDescriptionBox getSampleDescriptionBox() {
- return sampleDescriptionBox;
- }
-
- public long[] getSyncSamples() {
- if (syncSamples == null || syncSamples.isEmpty()) {
- return null;
- }
- long[] returns = new long[syncSamples.size()];
- for (int i = 0; i < syncSamples.size(); i++) {
- returns[i] = syncSamples.get(i);
- }
- return returns;
- }
-
- public int getTimeScale() {
- return timeScale;
- }
-
- public Date getCreationTime() {
- return creationTime;
- }
-
- public int getWidth() {
- return width;
- }
-
- public int getHeight() {
- return height;
- }
-
- public float getVolume() {
- return volume;
- }
-
- public ArrayList<Long> getSampleDurations() {
- return sampleDurations;
- }
-
- public boolean isAudio() {
- return isAudio;
- }
-}
diff --git a/src/main/res/layout/conversation_list_row.xml b/src/main/res/layout/conversation_list_row.xml
index ec4b55363..08d938ffc 100644
--- a/src/main/res/layout/conversation_list_row.xml
+++ b/src/main/res/layout/conversation_list_row.xml
@@ -1,6 +1,5 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
diff --git a/src/main/res/values-de/strings.xml b/src/main/res/values-de/strings.xml
index c75396434..691fcd008 100644
--- a/src/main/res/values-de/strings.xml
+++ b/src/main/res/values-de/strings.xml
@@ -688,5 +688,6 @@
<string name="show_inactive_devices">Zeige inaktive Geräte</string>
<string name="distrust_omemo_key">Gerät misstrauen</string>
<string name="distrust_omemo_key_text">Bist du sicher, dass du die Verifizierung dieses Gerätes misstrauen möchtest? Dieses Gerät und Nachrichten von dem Gerät werden als unverifiziert markiert.</string>
+ <string name="transcoding_video_progress">Video wird komprimiert (%s%% fertiggestellt)</string>
</resources>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index ae18b1c4a..f34a17c9d 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -731,4 +731,5 @@
<string name="hide_inactive_devices">Hide inactive devices</string>
<string name="reply">Reply</string>
<string name="encrypting_message">Encrypting message</string>
+ <string name="transcoding_video_progress">Compressing video (%s%% completed)</string>
</resources>