#1436 search more broadly in Samsung SEFD box for motion photo video
This commit is contained in:
parent
5769593799
commit
f4108c244b
4 changed files with 18 additions and 41 deletions
|
@ -14,7 +14,6 @@ import com.adobe.internal.xmp.options.SerializeOptions
|
|||
import com.adobe.internal.xmp.properties.XMPPropertyInfo
|
||||
import com.drew.lang.KeyValuePair
|
||||
import com.drew.lang.Rational
|
||||
import com.drew.lang.SequentialByteArrayReader
|
||||
import com.drew.metadata.Tag
|
||||
import com.drew.metadata.avi.AviDirectory
|
||||
import com.drew.metadata.exif.ExifDirectoryBase
|
||||
|
@ -475,19 +474,9 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
// and only identify at most one
|
||||
} else if (isHeic(mimeType)) {
|
||||
Mp4ParserHelper.getSamsungSefd(context, uri)?.let { (_, bytes) ->
|
||||
val dir = hashMapOf(
|
||||
metadataMap[Mp4ParserHelper.SAMSUNG_MAKERNOTE_BOX_TYPE] = hashMapOf(
|
||||
"Size" to bytes.size.toString(),
|
||||
)
|
||||
val reader = SequentialByteArrayReader(bytes).apply {
|
||||
isMotorolaByteOrder = false
|
||||
}
|
||||
val start = reader.uInt16
|
||||
val tag = reader.uInt16
|
||||
if (start == 0 && tag == Mp4ParserHelper.SEFD_EMBEDDED_VIDEO_TAG) {
|
||||
val nameSize = reader.uInt32
|
||||
dir["Embedded Video Type"] = reader.getString(nameSize.toInt())
|
||||
}
|
||||
metadataMap[Mp4ParserHelper.SAMSUNG_MAKERNOTE_BOX_TYPE] = dir
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ object Mp4ParserHelper {
|
|||
private const val BOX_SIZE_DANGER_THRESHOLD = 3 * (1 shl 20) // MB
|
||||
|
||||
const val SAMSUNG_MAKERNOTE_BOX_TYPE = "sefd"
|
||||
const val SEFD_EMBEDDED_VIDEO_TAG = 0x0a30
|
||||
const val SEFD_MOTION_PHOTO_NAME = "MotionPhoto_Data"
|
||||
|
||||
private val largerTypeWhitelist = listOf(
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.os.ParcelFileDescriptor
|
|||
import android.util.Log
|
||||
import com.adobe.internal.xmp.XMPMeta
|
||||
import com.drew.imaging.jpeg.JpegSegmentType
|
||||
import com.drew.lang.SequentialByteArrayReader
|
||||
import com.drew.metadata.exif.ExifDirectoryBase
|
||||
import com.drew.metadata.exif.ExifIFD0Directory
|
||||
import com.drew.metadata.xmp.XmpDirectory
|
||||
|
@ -88,19 +87,23 @@ object MultiPage {
|
|||
}
|
||||
|
||||
fun isHeicSefdMotionPhoto(context: Context, uri: Uri): Boolean {
|
||||
Mp4ParserHelper.getSamsungSefd(context, uri)?.let { (_, bytes) ->
|
||||
val reader = SequentialByteArrayReader(bytes).apply {
|
||||
isMotorolaByteOrder = false
|
||||
return getHeicSefdMotionPhotoVideoSizing(context, uri) != null
|
||||
}
|
||||
val start = reader.uInt16
|
||||
val tag = reader.uInt16
|
||||
if (start == 0 && tag == Mp4ParserHelper.SEFD_EMBEDDED_VIDEO_TAG) {
|
||||
val nameSize = reader.uInt32
|
||||
val name = reader.getString(nameSize.toInt())
|
||||
return name == Mp4ParserHelper.SEFD_MOTION_PHOTO_NAME
|
||||
|
||||
private fun getHeicSefdMotionPhotoVideoSizing(context: Context, uri: Uri): Pair<Long, Long>? {
|
||||
Mp4ParserHelper.getSamsungSefd(context, uri)?.let { (sefdOffset, sefdBytes) ->
|
||||
// we could properly parse each tag until we find the "embedded video" tag (0x0a30)
|
||||
// but it seems that decoding the SEFT trailer is necessary for this,
|
||||
// so we simply search for the "MotionPhoto_Data" sequence instead
|
||||
val name = Mp4ParserHelper.SEFD_MOTION_PHOTO_NAME
|
||||
val index = sefdBytes.indexOfBytes(name.toByteArray(Charsets.UTF_8))
|
||||
if (index != -1) {
|
||||
val videoOffset = sefdOffset + index + name.length
|
||||
val videoSize = sefdBytes.size - (videoOffset - sefdOffset)
|
||||
return Pair(videoOffset, videoSize)
|
||||
}
|
||||
}
|
||||
return false
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getJpegMpfPrimaryRotation(context: Context, uri: Uri, sizeBytes: Long): Int {
|
||||
|
@ -392,22 +395,7 @@ object MultiPage {
|
|||
|
||||
if (MimeTypes.isHeic(mimeType)) {
|
||||
// fallback to video within Samsung SEFD box
|
||||
Mp4ParserHelper.getSamsungSefd(context, uri)?.let { (sefdOffset, bytes) ->
|
||||
val reader = SequentialByteArrayReader(bytes).apply {
|
||||
isMotorolaByteOrder = false
|
||||
}
|
||||
val start = reader.uInt16
|
||||
val tag = reader.uInt16
|
||||
if (start == 0 && tag == Mp4ParserHelper.SEFD_EMBEDDED_VIDEO_TAG) {
|
||||
val nameSize = reader.uInt32
|
||||
val name = reader.getString(nameSize.toInt())
|
||||
if (name == Mp4ParserHelper.SEFD_MOTION_PHOTO_NAME) {
|
||||
val videoOffset = sefdOffset + reader.position
|
||||
val videoSize = reader.available().toLong()
|
||||
return Pair(videoOffset, videoSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
return getHeicSefdMotionPhotoVideoSizing(context, uri)
|
||||
}
|
||||
|
||||
return null
|
||||
|
|
|
@ -20,6 +20,7 @@ fun <E> MutableList<E>.compatRemoveIf(filter: (t: E) -> Boolean): Boolean {
|
|||
}
|
||||
|
||||
// Boyer-Moore algorithm for pattern searching
|
||||
// Returns: an index of the first occurrence of the pattern or -1 if none is found.
|
||||
fun ByteArray.indexOfBytes(pattern: ByteArray, start: Int = 0): Int {
|
||||
val n: Int = this.size
|
||||
val m: Int = pattern.size
|
||||
|
|
Loading…
Reference in a new issue