@@ -2,11 +2,12 @@ package org.fossify.gallery.helpers
22
33import android.content.Context
44import android.net.Uri
5+ import androidx.core.net.toUri
56import org.apache.sanselan.common.byteSources.ByteSourceInputStream
67import org.apache.sanselan.formats.jpeg.JpegImageParser
78import java.io.File
89import java.io.RandomAccessFile
9- import androidx.core.net.toUri
10+ import java.nio.ByteBuffer
1011
1112data class MotionPhotoInfo (
1213 val videoOffsetFromStart : Long ,
@@ -16,6 +17,9 @@ data class MotionPhotoInfo(
1617object MotionPhotoHelper {
1718
1819 private const val SCAN_RANGE = 5L * 1024 * 1024
20+ private const val MIN_FILE_SIZE = 12L
21+ private const val MIN_BOX_SIZE = 8
22+ private const val MAX_BOX_SIZE = 64
1923
2024 private val FTYP_MARKER = " ftyp" .toByteArray(Charsets .US_ASCII )
2125
@@ -58,7 +62,7 @@ object MotionPhotoHelper {
5862 private fun findVideoOffsetFromFile (path : String ): MotionPhotoInfo ? {
5963 val file = File (path)
6064 val fileSize = file.length()
61- if (fileSize < 12 ) return null
65+ if (fileSize < MIN_FILE_SIZE ) return null
6266
6367 val scanStart = maxOf(0L , fileSize - SCAN_RANGE )
6468 val scanLength = (fileSize - scanStart).toInt()
@@ -78,7 +82,10 @@ object MotionPhotoHelper {
7882
7983 private fun findVideoOffsetFromContentUri (context : Context , path : String ): MotionPhotoInfo ? {
8084 val uri = path.toUri()
81- val fileSize = context.contentResolver.openFileDescriptor(uri, " r" )?.use { it.statSize }?.takeIf { it >= 12 } ? : return null
85+ val fileSize = context.contentResolver.openFileDescriptor(uri, " r" )
86+ ?.use { it.statSize }
87+ ?.takeIf { it >= MIN_FILE_SIZE }
88+ ? : return null
8289 val scanStart = maxOf(0L , fileSize - SCAN_RANGE )
8390 val scanLength = (fileSize - scanStart).toInt()
8491 val buffer = readBytesFromUri(context, uri, scanStart, scanLength) ? : return null
@@ -109,23 +116,20 @@ object MotionPhotoHelper {
109116 // Search for "ftyp" marker and validate it's an MP4 box header.
110117 // The box structure is: [4 bytes size][4 bytes "ftyp"][4+ bytes brand]
111118 // So we look for "ftyp" at position i, and the box starts at i-4.
112- for (i in 4 until buffer.size - 4 ) {
119+ val markerSize = FTYP_MARKER .size
120+ for (i in markerSize until buffer.size - markerSize) {
113121 if (matchesFtypMarker(buffer, i)) {
114- val boxStart = i - 4
115- val boxSize = ((buffer[boxStart].toInt() and 0xFF ) shl 24 ) or
116- ((buffer[boxStart + 1 ].toInt() and 0xFF ) shl 16 ) or
117- ((buffer[boxStart + 2 ].toInt() and 0xFF ) shl 8 ) or
118- (buffer[boxStart + 3 ].toInt() and 0xFF )
119- if (boxSize in 8 .. 64 ) {
122+ val boxStart = i - markerSize
123+ val boxSize = ByteBuffer .wrap(buffer, boxStart, markerSize).int
124+ if (boxSize in MIN_BOX_SIZE .. MAX_BOX_SIZE ) {
120125 return boxStart
121126 }
122127 }
123128 }
124129 return null
125130 }
126131
127- private fun matchesFtypMarker (buffer : ByteArray , i : Int ): Boolean = buffer[i] == FTYP_MARKER [0 ] &&
128- buffer[i + 1 ] == FTYP_MARKER [1 ] &&
129- buffer[i + 2 ] == FTYP_MARKER [2 ] &&
130- buffer[i + 3 ] == FTYP_MARKER [3 ]
132+ private fun matchesFtypMarker (buffer : ByteArray , offset : Int ): Boolean {
133+ return FTYP_MARKER .indices.all { buffer[offset + it] == FTYP_MARKER [it] }
134+ }
131135}
0 commit comments