fixed crash when cataloguing some MP4 files
This commit is contained in:
parent
885a9f3ff9
commit
fdd9e00939
4 changed files with 25 additions and 15 deletions
|
@ -190,8 +190,8 @@ dependencies {
|
||||||
// - https://jitpack.io/p/deckerst/mp4parser
|
// - https://jitpack.io/p/deckerst/mp4parser
|
||||||
// - https://jitpack.io/p/deckerst/pixymeta-android
|
// - https://jitpack.io/p/deckerst/pixymeta-android
|
||||||
implementation 'com.github.deckerst:Android-TiffBitmapFactory:876e53870a'
|
implementation 'com.github.deckerst:Android-TiffBitmapFactory:876e53870a'
|
||||||
implementation 'com.github.deckerst.mp4parser:isoparser:64b571fdfb'
|
implementation 'com.github.deckerst.mp4parser:isoparser:6bfa6c23f7'
|
||||||
implementation 'com.github.deckerst.mp4parser:muxer:64b571fdfb'
|
implementation 'com.github.deckerst.mp4parser:muxer:6bfa6c23f7'
|
||||||
implementation 'com.github.deckerst:pixymeta-android:706bd73d6e'
|
implementation 'com.github.deckerst:pixymeta-android:706bd73d6e'
|
||||||
|
|
||||||
// huawei flavor only
|
// huawei flavor only
|
||||||
|
|
|
@ -15,11 +15,8 @@ import android.util.Log
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.drew.metadata.file.FileTypeDirectory
|
import com.drew.metadata.file.FileTypeDirectory
|
||||||
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
|
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
|
||||||
import deckers.thibault.aves.metadata.ExifInterfaceHelper
|
import deckers.thibault.aves.metadata.*
|
||||||
import deckers.thibault.aves.metadata.MediaMetadataRetrieverHelper
|
|
||||||
import deckers.thibault.aves.metadata.Metadata
|
|
||||||
import deckers.thibault.aves.metadata.Mp4ParserHelper.dumpBoxes
|
import deckers.thibault.aves.metadata.Mp4ParserHelper.dumpBoxes
|
||||||
import deckers.thibault.aves.metadata.PixyMetaHelper
|
|
||||||
import deckers.thibault.aves.metadata.metadataextractor.Helper
|
import deckers.thibault.aves.metadata.metadataextractor.Helper
|
||||||
import deckers.thibault.aves.model.FieldMap
|
import deckers.thibault.aves.model.FieldMap
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
|
@ -345,7 +342,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
FileInputStream(it.fileDescriptor).use { stream ->
|
FileInputStream(it.fileDescriptor).use { stream ->
|
||||||
stream.channel.use { channel ->
|
stream.channel.use { channel ->
|
||||||
val boxParser = PropertyBoxParserImpl().apply {
|
val boxParser = PropertyBoxParserImpl().apply {
|
||||||
skippingBoxes(
|
val skippedTypes = listOf(
|
||||||
// parsing `MediaDataBox` can take a long time
|
// parsing `MediaDataBox` can take a long time
|
||||||
MediaDataBox.TYPE,
|
MediaDataBox.TYPE,
|
||||||
// parsing `SampleTableBox` or `FreeBox` may yield OOM
|
// parsing `SampleTableBox` or `FreeBox` may yield OOM
|
||||||
|
@ -354,6 +351,11 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
// then a large size from following "0000", which may yield OOM
|
// then a large size from following "0000", which may yield OOM
|
||||||
"0000",
|
"0000",
|
||||||
)
|
)
|
||||||
|
setBoxSkipper { type, size ->
|
||||||
|
if (skippedTypes.contains(type)) return@setBoxSkipper true
|
||||||
|
if (size > Mp4ParserHelper.BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large")
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
IsoFile(channel, boxParser).use { isoFile ->
|
IsoFile(channel, boxParser).use { isoFile ->
|
||||||
isoFile.dumpBoxes(sb)
|
isoFile.dumpBoxes(sb)
|
||||||
|
|
|
@ -15,6 +15,9 @@ import java.io.FileInputStream
|
||||||
import java.nio.channels.Channels
|
import java.nio.channels.Channels
|
||||||
|
|
||||||
object Mp4ParserHelper {
|
object Mp4ParserHelper {
|
||||||
|
// arbitrary size to detect boxes that may yield an OOM
|
||||||
|
const val BOX_SIZE_DANGER_THRESHOLD = 3 * (1 shl 20) // MB
|
||||||
|
|
||||||
fun computeEdits(context: Context, uri: Uri, modifier: (isoFile: IsoFile) -> Unit): List<Pair<Long, ByteArray>> {
|
fun computeEdits(context: Context, uri: Uri, modifier: (isoFile: IsoFile) -> Unit): List<Pair<Long, ByteArray>> {
|
||||||
// we can skip uninteresting boxes with a seekable data source
|
// we can skip uninteresting boxes with a seekable data source
|
||||||
val pfd = StorageUtils.openInputFileDescriptor(context, uri) ?: throw Exception("failed to open file descriptor for uri=$uri")
|
val pfd = StorageUtils.openInputFileDescriptor(context, uri) ?: throw Exception("failed to open file descriptor for uri=$uri")
|
||||||
|
@ -23,13 +26,16 @@ object Mp4ParserHelper {
|
||||||
stream.channel.use { channel ->
|
stream.channel.use { channel ->
|
||||||
val boxParser = PropertyBoxParserImpl().apply {
|
val boxParser = PropertyBoxParserImpl().apply {
|
||||||
// do not skip anything inside `MovieBox` as it will be parsed and rewritten for editing
|
// do not skip anything inside `MovieBox` as it will be parsed and rewritten for editing
|
||||||
skippingBoxes(
|
// do not skip weird boxes (like trailing "0000" box), to fail fast if it is large
|
||||||
|
val skippedTypes = listOf(
|
||||||
// parsing `MediaDataBox` can take a long time
|
// parsing `MediaDataBox` can take a long time
|
||||||
MediaDataBox.TYPE,
|
MediaDataBox.TYPE,
|
||||||
// some files are padded with `0` but the parser does not stop, reads type "0000",
|
|
||||||
// then a large size from following "0000", which may yield OOM
|
|
||||||
"0000",
|
|
||||||
)
|
)
|
||||||
|
setBoxSkipper { type, size ->
|
||||||
|
if (skippedTypes.contains(type)) return@setBoxSkipper true
|
||||||
|
if (size > BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large")
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device`
|
// creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device`
|
||||||
IsoFile(channel, boxParser).use { isoFile ->
|
IsoFile(channel, boxParser).use { isoFile ->
|
||||||
|
|
|
@ -145,15 +145,17 @@ object XMP {
|
||||||
FileInputStream(it.fileDescriptor).use { stream ->
|
FileInputStream(it.fileDescriptor).use { stream ->
|
||||||
stream.channel.use { channel ->
|
stream.channel.use { channel ->
|
||||||
val boxParser = PropertyBoxParserImpl().apply {
|
val boxParser = PropertyBoxParserImpl().apply {
|
||||||
skippingBoxes(
|
val skippedTypes = listOf(
|
||||||
// parsing `MediaDataBox` can take a long time
|
// parsing `MediaDataBox` can take a long time
|
||||||
MediaDataBox.TYPE,
|
MediaDataBox.TYPE,
|
||||||
// parsing `SampleTableBox` or `FreeBox` may yield OOM
|
// parsing `SampleTableBox` or `FreeBox` may yield OOM
|
||||||
SampleTableBox.TYPE, FreeBox.TYPE,
|
SampleTableBox.TYPE, FreeBox.TYPE,
|
||||||
// some files are padded with `0` but the parser does not stop, reads type "0000",
|
|
||||||
// then a large size from following "0000", which may yield OOM
|
|
||||||
"0000",
|
|
||||||
)
|
)
|
||||||
|
setBoxSkipper { type, size ->
|
||||||
|
if (skippedTypes.contains(type)) return@setBoxSkipper true
|
||||||
|
if (size > Mp4ParserHelper.BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large")
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device`
|
// creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device`
|
||||||
IsoFile(channel, boxParser).use { isoFile ->
|
IsoFile(channel, boxParser).use { isoFile ->
|
||||||
|
|
Loading…
Reference in a new issue