mp4parser icon indicating copy to clipboard operation
mp4parser copied to clipboard

How can I release the input sources put in `MovieCreator.build()`?

Open nICEnnnnnnnLee opened this issue 4 years ago • 3 comments

I'm doing something like that in MuxMp4SourcesExample.java

String audioEnglish = "audio.mp4";
String video = "video.mp4";

Movie countVideo = MovieCreator.build(video);
Movie countAudioEnglish = MovieCreator.build(audioEnglish);
Track audioTrackEnglish = countAudioEnglish.getTracks().get(0);
audioTrackEnglish.getTrackMetaData().setLanguage("eng");
countVideo.addTrack(audioTrackEnglish);

Container out = new DefaultMp4Builder().build(countVideo);
FileOutputStream fos = new FileOutputStream(new File("output.mp4"));
out.writeContainer(fos.getChannel());
fos.close();

After that, I attempt to delete the audio file but failed.

boolean deleted = new File(audioEnglish).delete();
System.out.println("deleted : " + deleted );  // ---> false

Will it auto release the resources, or how could I mannualy free it?

nICEnnnnnnnLee avatar Jun 20 '20 07:06 nICEnnnnnnnLee

I've noticed that the implementations of Track is instance of Closeable.
for example,

But CencMp4TrackImplImpl, PiffMp4TrackImpl, Mp4TrackImpl in MovieCreator.build() somehow ignores it. Here, in Mp4TrackImpl.java, it does nothing.

It should do sth since a RandomAccessSource is put in the Mp4TrackImpl, am I right?

public Mp4TrackImpl(final long trackId, Container isofile, RandomAccessSource randomAccess, String name)

nICEnnnnnnnLee avatar Jun 20 '20 08:06 nICEnnnnnnnLee

I have the same problem. What should I do?

HadiDortaj avatar Oct 29 '21 19:10 HadiDortaj

I created a custom MovieCreator for this bug and it seems to be working(the code is written in Kotlin). Remeber that you should call movie.tracks.forEach { track -> track.close() } when you are done.

import org.mp4parser.Container
import org.mp4parser.IsoFile
import org.mp4parser.boxes.iso14496.part12.SchemeTypeBox
import org.mp4parser.boxes.iso14496.part12.TrackBox
import org.mp4parser.muxer.*
import org.mp4parser.tools.Path
import java.io.File
import java.io.FileInputStream
import java.io.RandomAccessFile
import java.nio.channels.ReadableByteChannel

class CustomMovieCreator {

companion object {

    fun newMovieInstance(filePath: String): Movie {
        val f = File(filePath)
        val fis = FileInputStream(f)
        val m = newMovieInstance(fis.channel, FileRandomAccessSourceImpl(RandomAccessFile(f, "r")), filePath)
        fis.close()
        return m
    }

    private fun newMovieInstance(readableByteChannel: ReadableByteChannel?, randomAccessSource: RandomAccessSource?, name: String?): Movie {
        val isoFile = IsoFile(readableByteChannel)
        val m = Movie()
        val trackBoxes = isoFile.movieBox.getBoxes(TrackBox::class.java)
        for (trackBox in trackBoxes) {
            val schm = Path.getPath<SchemeTypeBox>(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schm[0]")
            if (schm != null && (schm.schemeType == "cenc" || schm.schemeType == "cbc1")) {
                m.addTrack(
                    CustomCencMp4TrackImplImpl(
                        trackBox.trackHeaderBox.trackId, isoFile,
                        randomAccessSource, name + "[" + trackBox.trackHeaderBox.trackId + "]"
                    )
                )
            } else if (schm != null && schm.schemeType == "piff") {
                m.addTrack(
                    CustomPiffMp4TrackImpl(
                        trackBox.trackHeaderBox.trackId, isoFile,
                        randomAccessSource, name + "[" + trackBox.trackHeaderBox.trackId + "]"
                    )
                )
            } else {
                m.addTrack(
                    CustomMp4TrackImp(
                        trackBox.trackHeaderBox.trackId, isoFile,
                        randomAccessSource, name + "[" + trackBox.trackHeaderBox.trackId + "]"
                    )
                )
            }
        }
        m.matrix = isoFile.movieBox.movieHeaderBox.matrix
        return m
    }

}

private class CustomMp4TrackImp(trackId: Long, isofile: Container?, private val randomAccess: RandomAccessSource?, name: String?) : Mp4TrackImpl(trackId, isofile, randomAccess, name) {

    override fun close() {
        kotlin.runCatching {
            randomAccess?.close()
        }
    }
}

private class CustomPiffMp4TrackImpl(trackId: Long, isofile: Container?, private val randomAccess: RandomAccessSource?, name: String?) : PiffMp4TrackImpl(trackId, isofile, randomAccess, name) {

    override fun close() {
        kotlin.runCatching {
            randomAccess?.close()
        }
    }
}

private class CustomCencMp4TrackImplImpl(trackId: Long, isofile: Container?, private val randomAccess: RandomAccessSource?, name: String?) : CencMp4TrackImplImpl(trackId, isofile, randomAccess, name) {

    override fun close() {
        kotlin.runCatching {
            randomAccess?.close()
        }
    }
}

}

HadiDortaj avatar Oct 30 '21 00:10 HadiDortaj