cataloguing: prevent OOM from parsing larg MP4 sample tables

This commit is contained in:
Thibault Deckers 2022-11-11 22:11:42 +01:00
parent bb758cdb34
commit fe81256276
3 changed files with 23 additions and 6 deletions

View file

@ -41,8 +41,11 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.beyka.tiffbitmapfactory.TiffBitmapFactory import org.beyka.tiffbitmapfactory.TiffBitmapFactory
import org.mp4parser.IsoFile import org.mp4parser.IsoFile
import org.mp4parser.PropertyBoxParserImpl
import org.mp4parser.boxes.iso14496.part12.MediaDataBox
import org.mp4parser.boxes.iso14496.part12.SampleTableBox
import java.io.FileInputStream
import java.io.IOException import java.io.IOException
import java.nio.channels.Channels
class DebugHandler(private val context: Context) : MethodCallHandler { class DebugHandler(private val context: Context) : MethodCallHandler {
private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
@ -335,10 +338,19 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
val sb = StringBuilder() val sb = StringBuilder()
if (mimeType == MimeTypes.MP4) { if (mimeType == MimeTypes.MP4) {
try { try {
StorageUtils.openInputStream(context, uri)?.use { input -> // we can skip uninteresting boxes with a seekable data source
Channels.newChannel(input).use { channel -> val pfd = StorageUtils.openInputFileDescriptor(context, uri) ?: throw Exception("failed to open file descriptor for uri=$uri")
IsoFile(channel).use { isoFile -> pfd.use {
isoFile.dumpBoxes(sb) FileInputStream(it.fileDescriptor).use { stream ->
stream.channel.use { channel ->
val boxParser = PropertyBoxParserImpl().apply {
// parsing `MediaDataBox` can take a long time
// parsing `SampleTableBox` may yield OOM
skippingBoxes(MediaDataBox.TYPE, SampleTableBox.TYPE)
}
IsoFile(channel, boxParser).use { isoFile ->
isoFile.dumpBoxes(sb)
}
} }
} }
} }

View file

@ -22,6 +22,8 @@ object Mp4ParserHelper {
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 {
// parsing `MediaDataBox` can take a long time
// do not skip anything inside `MovieBox` as it will be parsed and rewritten for editing
skippingBoxes(MediaDataBox.TYPE) skippingBoxes(MediaDataBox.TYPE)
} }
// 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`

View file

@ -23,6 +23,7 @@ import org.mp4parser.IsoFile
import org.mp4parser.PropertyBoxParserImpl import org.mp4parser.PropertyBoxParserImpl
import org.mp4parser.boxes.UserBox import org.mp4parser.boxes.UserBox
import org.mp4parser.boxes.iso14496.part12.MediaDataBox import org.mp4parser.boxes.iso14496.part12.MediaDataBox
import org.mp4parser.boxes.iso14496.part12.SampleTableBox
import java.io.FileInputStream import java.io.FileInputStream
import java.util.* import java.util.*
@ -142,7 +143,9 @@ 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(MediaDataBox.TYPE) // parsing `MediaDataBox` can take a long time
// parsing `SampleTableBox` may yield OOM
skippingBoxes(MediaDataBox.TYPE, SampleTableBox.TYPE)
} }
// 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 ->