Fix bug where video dimensions aren't always correct in chat view.

This commit is contained in:
Greyson Parrelli
2026-02-23 15:33:21 -05:00
committed by Cody Henthorne
parent d28fc98cfd
commit 08509f6693
6 changed files with 85 additions and 12 deletions

View File

@@ -2099,12 +2099,15 @@ class AttachmentTable(
val contentValues = contentValuesOf(
DATA_SIZE to newDataFileInfo.length,
CONTENT_TYPE to mediaStream.mimeType,
WIDTH to mediaStream.width,
HEIGHT to mediaStream.height,
DATA_FILE to newDataFileInfo.file.absolutePath,
DATA_RANDOM to newDataFileInfo.random
)
if (mediaStream.width > 0 && mediaStream.height > 0) {
contentValues.put(WIDTH, mediaStream.width)
contentValues.put(HEIGHT, mediaStream.height)
}
val updateCount = db.update(TABLE_NAME)
.values(contentValues)
.where("$ID = ? OR $DATA_FILE = ?", attachmentId.id, existingDataFileInfo.file.absolutePath)

View File

@@ -262,6 +262,8 @@ public class MediaRepository {
if (isImage) {
projection = new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_MODIFIED, Images.Media.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE};
} else if (Build.VERSION.SDK_INT >= 29) {
projection = new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_MODIFIED, MediaStore.MediaColumns.ORIENTATION, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE, Video.Media.DURATION};
} else {
projection = new String[]{Images.Media._ID, Images.Media.MIME_TYPE, Images.Media.DATE_MODIFIED, Images.Media.WIDTH, Images.Media.HEIGHT, Images.Media.SIZE, Video.Media.DURATION};
}
@@ -277,7 +279,13 @@ public class MediaRepository {
Uri uri = ContentUris.withAppendedId(contentUri, rowId);
String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE));
long date = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.DATE_MODIFIED));
int orientation = isImage ? cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION)) : 0;
int orientation;
if (isImage) {
orientation = cursor.getInt(cursor.getColumnIndexOrThrow(Images.Media.ORIENTATION));
} else {
int orientationIdx = cursor.getColumnIndex(MediaStore.MediaColumns.ORIENTATION);
orientation = orientationIdx != -1 ? cursor.getInt(orientationIdx) : 0;
}
int width = cursor.getInt(cursor.getColumnIndexOrThrow(getWidthColumn(orientation)));
int height = cursor.getInt(cursor.getColumnIndexOrThrow(getHeightColumn(orientation)));
long size = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.SIZE));
@@ -386,6 +394,7 @@ public class MediaRepository {
try (Cursor cursor = context.getContentResolver().query(media.getUri(), null, null, null, null)) {
if (cursor != null && cursor.moveToFirst() && cursor.getColumnIndex(OpenableColumns.SIZE) >= 0) {
size = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
} else {
}
}
}

View File

@@ -68,7 +68,8 @@ class MediaSelectionRepository(context: Context) {
return Single.fromCallable {
val populatedMedia = mediaRepository.getPopulatedMedia(context, media)
MediaValidator.filterMedia(context, populatedMedia, mediaConstraints, maxSelection, isStory)
val result = MediaValidator.filterMedia(context, populatedMedia, mediaConstraints, maxSelection, isStory)
result
}.subscribeOn(Schedulers.io())
}

View File

@@ -15,6 +15,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import org.signal.core.models.media.Media
import org.signal.core.models.media.MediaFolder
import org.signal.core.util.logging.Log
import org.signal.mediasend.EditorState
import org.signal.mediasend.MediaFilterError
import org.signal.mediasend.MediaFilterResult
@@ -49,6 +50,7 @@ import kotlin.time.Duration.Companion.seconds
*/
object MediaSendV3Repository : MediaSendRepository {
private val TAG = Log.tag(MediaSendV3Repository::class.java)
private val appContext = AppDependencies.application
private val legacyRepository = MediaSelectionRepository(appContext)
private val mediaRepository = MediaRepository()

View File

@@ -49,8 +49,11 @@ public final class SlideFactory {
} else {
Slide result = getContentResolverSlideInfo(context, mediaType, uri, width, height, transformProperties);
if (result == null) return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height, transformProperties);
else return result;
if (result == null) {
return getManuallyCalculatedSlideInfo(context, mediaType, uri, width, height, transformProperties);
} else {
return result;
}
}
} catch (IOException e) {
Log.w(TAG, e);
@@ -86,6 +89,7 @@ public final class SlideFactory {
Log.d(TAG, "remote slide with size " + fileSize + " took " + (System.currentTimeMillis() - start) + "ms");
return mediaType.createSlide(context, uri, fileName, mimeType, null, fileSize, width, height, false, transformProperties);
} else {
}
}

View File

@@ -244,12 +244,8 @@ public class MediaUtil {
} catch (ExecutionException e) {
Log.w(TAG, "Glide experienced an exception while trying to get GIF dimensions.", e);
}
} else if (MediaUtil.hasVideoThumbnail(context, uri)) {
Bitmap thumbnail = MediaUtil.getVideoThumbnail(context, uri, 1000);
if (thumbnail != null) {
dimens = new Pair<>(thumbnail.getWidth(), thumbnail.getHeight());
}
} else if (MediaUtil.isVideoType(contentType)) {
dimens = getVideoDimensions(context, uri);
} else {
InputStream attachmentStream = null;
try {
@@ -258,6 +254,9 @@ public class MediaUtil {
dimens = BitmapUtil.getExifDimensions(new ExifInterface(attachmentStream));
attachmentStream.close();
attachmentStream = null;
if (dimens != null) {
} else {
}
}
if (dimens == null) {
attachmentStream = PartAuthority.getAttachmentStream(context, uri);
@@ -286,6 +285,61 @@ public class MediaUtil {
return dimens;
}
@WorkerThread
private static @NonNull Pair<Integer, Integer> getVideoDimensions(@NonNull Context context, @NonNull Uri uri) {
try {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
if (BlobProvider.isAuthority(uri) && MediaUtil.isVideo(BlobProvider.getMimeType(uri))) {
MediaDataSource source = BlobProvider.getInstance().getMediaDataSource(context, uri);
retriever.setDataSource(source);
} else if (PartAuthority.isAttachmentUri(uri)) {
MediaDataSource source = SignalDatabase.attachments().mediaDataSourceFor(PartAuthority.requireAttachmentId(uri), false);
if (source == null) {
throw new IOException("No media data source for attachment URI");
}
retriever.setDataSource(source);
} else {
retriever.setDataSource(context, uri);
}
String widthString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
String heightString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
if (widthString == null || heightString == null) {
throw new IOException("Could not extract video dimensions from metadata");
}
int width = Integer.parseInt(widthString);
int height = Integer.parseInt(heightString);
int rotation = rotationString != null ? Integer.parseInt(rotationString) : 0;
if (rotation % 180 == 90) {
//noinspection SuspiciousNameCombination
return new Pair<>(height, width);
} else {
return new Pair<>(width, height);
}
} finally {
retriever.release();
}
} catch (Exception e) {
Log.w(TAG, "Failed to get video dimensions via metadata for URI: " + uri, e);
}
if (MediaUtil.hasVideoThumbnail(context, uri)) {
Bitmap thumbnail = MediaUtil.getVideoThumbnail(context, uri, 1000);
if (thumbnail != null) {
return new Pair<>(thumbnail.getWidth(), thumbnail.getHeight());
}
} else {
}
return new Pair<>(0, 0);
}
public static boolean isMms(String contentType) {
return ContentTypeUtil.isMms(contentType);
}