/* * This is the source code of Telegram for Android v. 5.x.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-2018. */ package org.telegram.messenger; import android.graphics.Bitmap; import android.graphics.Canvas; import android.text.TextUtils; import android.view.View; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.Paint.PaintTypeface; import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.Point; import java.util.ArrayList; import java.util.Locale; public class VideoEditedInfo { public long startTime; public long endTime; public long avatarStartTime = -1; public float start; public float end; public int compressQuality; public int rotationValue; public int originalWidth; public int originalHeight; public int originalBitrate; public int resultWidth; public int resultHeight; public int bitrate; public int framerate = 24; public String originalPath; public long estimatedSize; public long estimatedDuration; public boolean roundVideo; public boolean muted; public long originalDuration; public TLRPC.InputFile file; public TLRPC.InputEncryptedFile encryptedFile; public byte[] key; public byte[] iv; public MediaController.SavedFilterState filterState; public String paintPath; public ArrayList mediaEntities; public MediaController.CropState cropState; public boolean isPhoto; public boolean canceled; public boolean videoConvertFirstWrite; public boolean needUpdateProgress = false; public boolean shouldLimitFps = true; public static class EmojiEntity extends TLRPC.TL_messageEntityCustomEmoji { public String documentAbsolutePath; @Override public void readParams(AbstractSerializedData stream, boolean exception) { super.readParams(stream, exception); boolean hasPath = stream.readBool(exception); if (hasPath) { documentAbsolutePath = stream.readString(exception); } if (TextUtils.isEmpty(documentAbsolutePath)) { documentAbsolutePath = null; } } @Override public void serializeToStream(AbstractSerializedData stream) { super.serializeToStream(stream); stream.writeBool(!TextUtils.isEmpty(documentAbsolutePath)); if (!TextUtils.isEmpty(documentAbsolutePath)) { stream.writeString(documentAbsolutePath); } } } public static class MediaEntity { public byte type; public byte subType; public float x; public float y; public float rotation; public float width; public float height; public String text; public ArrayList entities = new ArrayList<>(); public int color; public int fontSize; public PaintTypeface textTypeface; public int textAlign; public int viewWidth; public int viewHeight; public float roundRadius; public float scale; public float textViewWidth; public float textViewHeight; public float textViewX; public float textViewY; public TLRPC.Document document; public Object parentObject; public int[] metadata; public long ptr; public float currentFrame; public float framesPerDraw; public Bitmap bitmap; public View view; public Canvas canvas; public AnimatedFileDrawable animatedFileDrawable; public Canvas roundRadiusCanvas; public MediaEntity() { } private MediaEntity(SerializedData data) { type = data.readByte(false); subType = data.readByte(false); x = data.readFloat(false); y = data.readFloat(false); rotation = data.readFloat(false); width = data.readFloat(false); height = data.readFloat(false); text = data.readString(false); int count = data.readInt32(false); for (int i = 0; i < count; ++i) { EmojiEntity entity = new EmojiEntity(); data.readInt32(false); entity.readParams(data, false); entities.add(entity); } color = data.readInt32(false); fontSize = data.readInt32(false); viewWidth = data.readInt32(false); viewHeight = data.readInt32(false); textAlign = data.readInt32(false); textTypeface = PaintTypeface.find(data.readString(false)); } private void serializeTo(SerializedData data) { data.writeByte(type); data.writeByte(subType); data.writeFloat(x); data.writeFloat(y); data.writeFloat(rotation); data.writeFloat(width); data.writeFloat(height); data.writeString(text); data.writeInt32(entities.size()); for (int i = 0; i < entities.size(); ++i) { entities.get(i).serializeToStream(data); } data.writeInt32(color); data.writeInt32(fontSize); data.writeInt32(viewWidth); data.writeInt32(viewHeight); data.writeInt32(textAlign); data.writeString(textTypeface == null ? "" : textTypeface.getKey()); } public MediaEntity copy() { MediaEntity entity = new MediaEntity(); entity.type = type; entity.subType = subType; entity.x = x; entity.y = y; entity.rotation = rotation; entity.width = width; entity.height = height; entity.text = text; entity.entities.addAll(entities); entity.color = color; entity.fontSize = fontSize; entity.viewWidth = viewWidth; entity.viewHeight = viewHeight; entity.scale = scale; entity.textViewWidth = textViewWidth; entity.textViewHeight = textViewHeight; entity.textViewX = textViewX; entity.textViewY = textViewY; entity.textAlign = textAlign; entity.textTypeface = textTypeface; return entity; } } public String getString() { String filters; if (avatarStartTime != -1 || filterState != null || paintPath != null || mediaEntities != null && !mediaEntities.isEmpty() || cropState != null) { int len = 10; if (filterState != null) { len += 160; } byte[] paintPathBytes; if (paintPath != null) { paintPathBytes = paintPath.getBytes(); len += paintPathBytes.length; } else { paintPathBytes = null; } SerializedData serializedData = new SerializedData(len); serializedData.writeInt32(5); serializedData.writeInt64(avatarStartTime); serializedData.writeInt32(originalBitrate); if (filterState != null) { serializedData.writeByte(1); serializedData.writeFloat(filterState.enhanceValue); serializedData.writeFloat(filterState.softenSkinValue); serializedData.writeFloat(filterState.exposureValue); serializedData.writeFloat(filterState.contrastValue); serializedData.writeFloat(filterState.warmthValue); serializedData.writeFloat(filterState.saturationValue); serializedData.writeFloat(filterState.fadeValue); serializedData.writeInt32(filterState.tintShadowsColor); serializedData.writeInt32(filterState.tintHighlightsColor); serializedData.writeFloat(filterState.highlightsValue); serializedData.writeFloat(filterState.shadowsValue); serializedData.writeFloat(filterState.vignetteValue); serializedData.writeFloat(filterState.grainValue); serializedData.writeInt32(filterState.blurType); serializedData.writeFloat(filterState.sharpenValue); serializedData.writeFloat(filterState.blurExcludeSize); if (filterState.blurExcludePoint != null) { serializedData.writeFloat(filterState.blurExcludePoint.x); serializedData.writeFloat(filterState.blurExcludePoint.y); } else { serializedData.writeFloat(0); serializedData.writeFloat(0); } serializedData.writeFloat(filterState.blurExcludeBlurSize); serializedData.writeFloat(filterState.blurAngle); for (int a = 0; a < 4; a++) { PhotoFilterView.CurvesValue curvesValue; if (a == 0) { curvesValue = filterState.curvesToolValue.luminanceCurve; } else if (a == 1) { curvesValue = filterState.curvesToolValue.redCurve; } else if (a == 2) { curvesValue = filterState.curvesToolValue.greenCurve; } else { curvesValue = filterState.curvesToolValue.blueCurve; } serializedData.writeFloat(curvesValue.blacksLevel); serializedData.writeFloat(curvesValue.shadowsLevel); serializedData.writeFloat(curvesValue.midtonesLevel); serializedData.writeFloat(curvesValue.highlightsLevel); serializedData.writeFloat(curvesValue.whitesLevel); } } else { serializedData.writeByte(0); } if (paintPathBytes != null) { serializedData.writeByte(1); serializedData.writeByteArray(paintPathBytes); } else { serializedData.writeByte(0); } if (mediaEntities != null && !mediaEntities.isEmpty()) { serializedData.writeByte(1); serializedData.writeInt32(mediaEntities.size()); for (int a = 0, N = mediaEntities.size(); a < N; a++) { mediaEntities.get(a).serializeTo(serializedData); } serializedData.writeByte(isPhoto ? 1 : 0); } else { serializedData.writeByte(0); } if (cropState != null) { serializedData.writeByte(1); serializedData.writeFloat(cropState.cropPx); serializedData.writeFloat(cropState.cropPy); serializedData.writeFloat(cropState.cropPw); serializedData.writeFloat(cropState.cropPh); serializedData.writeFloat(cropState.cropScale); serializedData.writeFloat(cropState.cropRotate); serializedData.writeInt32(cropState.transformWidth); serializedData.writeInt32(cropState.transformHeight); serializedData.writeInt32(cropState.transformRotation); serializedData.writeBool(cropState.mirrored); } else { serializedData.writeByte(0); } filters = Utilities.bytesToHex(serializedData.toByteArray()); serializedData.cleanup(); } else { filters = ""; } return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_-%s_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalDuration, framerate, filters, originalPath); } public boolean parseString(String string) { if (string.length() < 6) { return false; } try { String[] args = string.split("_"); if (args.length >= 11) { startTime = Long.parseLong(args[1]); endTime = Long.parseLong(args[2]); rotationValue = Integer.parseInt(args[3]); originalWidth = Integer.parseInt(args[4]); originalHeight = Integer.parseInt(args[5]); bitrate = Integer.parseInt(args[6]); resultWidth = Integer.parseInt(args[7]); resultHeight = Integer.parseInt(args[8]); originalDuration = Long.parseLong(args[9]); framerate = Integer.parseInt(args[10]); muted = bitrate == -1; int start; if (args[11].startsWith("-")) { start = 12; String s = args[11].substring(1); if (s.length() > 0) { SerializedData serializedData = new SerializedData(Utilities.hexToBytes(s)); int version = serializedData.readInt32(false); if (version >= 3) { avatarStartTime = serializedData.readInt64(false); originalBitrate = serializedData.readInt32(false); } byte has = serializedData.readByte(false); if (has != 0) { filterState = new MediaController.SavedFilterState(); filterState.enhanceValue = serializedData.readFloat(false); if (version >= 5) { filterState.softenSkinValue = serializedData.readFloat(false); } filterState.exposureValue = serializedData.readFloat(false); filterState.contrastValue = serializedData.readFloat(false); filterState.warmthValue = serializedData.readFloat(false); filterState.saturationValue = serializedData.readFloat(false); filterState.fadeValue = serializedData.readFloat(false); filterState.tintShadowsColor = serializedData.readInt32(false); filterState.tintHighlightsColor = serializedData.readInt32(false); filterState.highlightsValue = serializedData.readFloat(false); filterState.shadowsValue = serializedData.readFloat(false); filterState.vignetteValue = serializedData.readFloat(false); filterState.grainValue = serializedData.readFloat(false); filterState.blurType = serializedData.readInt32(false); filterState.sharpenValue = serializedData.readFloat(false); filterState.blurExcludeSize = serializedData.readFloat(false); filterState.blurExcludePoint = new Point(serializedData.readFloat(false), serializedData.readFloat(false)); filterState.blurExcludeBlurSize = serializedData.readFloat(false); filterState.blurAngle = serializedData.readFloat(false); for (int a = 0; a < 4; a++) { PhotoFilterView.CurvesValue curvesValue; if (a == 0) { curvesValue = filterState.curvesToolValue.luminanceCurve; } else if (a == 1) { curvesValue = filterState.curvesToolValue.redCurve; } else if (a == 2) { curvesValue = filterState.curvesToolValue.greenCurve; } else { curvesValue = filterState.curvesToolValue.blueCurve; } curvesValue.blacksLevel = serializedData.readFloat(false); curvesValue.shadowsLevel = serializedData.readFloat(false); curvesValue.midtonesLevel = serializedData.readFloat(false); curvesValue.highlightsLevel = serializedData.readFloat(false); curvesValue.whitesLevel = serializedData.readFloat(false); } } has = serializedData.readByte(false); if (has != 0) { byte[] bytes = serializedData.readByteArray(false); paintPath = new String(bytes); } has = serializedData.readByte(false); if (has != 0) { int count = serializedData.readInt32(false); mediaEntities = new ArrayList<>(count); for (int a = 0; a < count; a++) { mediaEntities.add(new MediaEntity(serializedData)); } isPhoto = serializedData.readByte(false) == 1; } if (version >= 2) { has = serializedData.readByte(false); if (has != 0) { cropState = new MediaController.CropState(); cropState.cropPx = serializedData.readFloat(false); cropState.cropPy = serializedData.readFloat(false); cropState.cropPw = serializedData.readFloat(false); cropState.cropPh = serializedData.readFloat(false); cropState.cropScale = serializedData.readFloat(false); cropState.cropRotate = serializedData.readFloat(false); cropState.transformWidth = serializedData.readInt32(false); cropState.transformHeight = serializedData.readInt32(false); cropState.transformRotation = serializedData.readInt32(false); if (version >= 4) { cropState.mirrored = serializedData.readBool(false); } } } serializedData.cleanup(); } } else { start = 11; } for (int a = start; a < args.length; a++) { if (originalPath == null) { originalPath = args[a]; } else { originalPath += "_" + args[a]; } } } return true; } catch (Exception e) { FileLog.e(e); } return false; } public boolean needConvert() { return mediaEntities != null || paintPath != null || filterState != null || cropState != null || !roundVideo || startTime > 0 || endTime != -1 && endTime != estimatedDuration; } public boolean canAutoPlaySourceVideo() { return roundVideo; } }