javaandroidmp4mp4parsermp4box

Insert 360° metadata to mp4 file in java


I'm trying to add 360° metadata to a mp4 file with this library : https://github.com/copiousfreetime/mp4parser

after have check the code, i had created this :

public void injectSphericalMetaV2(TrackBox trackBox) throws IOException {
    String sphericalVideoGlobalMetadata = "<rdf:SphericalVideo xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"xmlns:GSpherical=\"http://ns.google.com/videos/1.0/spherical/\"><GSpherical:Spherical>true</GSpherical:Spherical><GSpherical:Stitched>true</GSpherical:Stitched><GSpherical:StitchingSoftware>GIROPTIC 360 CAM</GSpherical:StitchingSoftware><GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType></rdf:SphericalVideo>";
    String UUID_ID = "FFCC8263-F855-4A93-8814-587A02521FDD";
    UserBox sphericalAtom = new UserBox(UUID_ID.getBytes());
    sphericalAtom.setData(sphericalVideoGlobalMetadata.getBytes());
    trackBox.addBox(sphericalAtom);
}

and i execute it here :

protected TrackBox createTrackBox(Track track, Movie movie, Map<Track, int[]> chunks) {

    TrackBox trackBox = new TrackBox();
    TrackHeaderBox tkhd = new TrackHeaderBox();

    tkhd.setEnabled(true);
    tkhd.setInMovie(true);

    tkhd.setMatrix(track.getTrackMetaData().getMatrix());

    tkhd.setAlternateGroup(track.getTrackMetaData().getGroup());
    tkhd.setCreationTime(track.getTrackMetaData().getCreationTime());

    if (track.getEdits() == null || track.getEdits().isEmpty()) {
        tkhd.setDuration(track.getDuration() * getTimescale(movie) / track.getTrackMetaData().getTimescale());
    } else {
        long d = 0;
        for (Edit edit : track.getEdits()) {
            d += (long) edit.getSegmentDuration();
        }
        tkhd.setDuration(d * track.getTrackMetaData().getTimescale());
    }


    tkhd.setHeight(track.getTrackMetaData().getHeight());
    tkhd.setWidth(track.getTrackMetaData().getWidth());
    tkhd.setLayer(track.getTrackMetaData().getLayer());
    tkhd.setModificationTime(new Date());
    tkhd.setTrackId(track.getTrackMetaData().getTrackId());
    tkhd.setVolume(track.getTrackMetaData().getVolume());

    trackBox.addBox(tkhd);

    trackBox.addBox(createEdts(track, movie));

    MediaBox mdia = new MediaBox();
    trackBox.addBox(mdia);
    MediaHeaderBox mdhd = new MediaHeaderBox();
    mdhd.setCreationTime(track.getTrackMetaData().getCreationTime());
    mdhd.setDuration(track.getDuration());
    mdhd.setTimescale(track.getTrackMetaData().getTimescale());
    mdhd.setLanguage(track.getTrackMetaData().getLanguage());
    mdia.addBox(mdhd);
    HandlerBox hdlr = new HandlerBox();
    mdia.addBox(hdlr);

    hdlr.setHandlerType(track.getHandler());

    MediaInformationBox minf = new MediaInformationBox();
    if (track.getHandler().equals("vide")) {
        try {
            injectSphericalMetaV2(trackBox);
        } catch (IOException e) {
            e.printStackTrace();
        }
        minf.addBox(new VideoMediaHeaderBox());
    } else if (track.getHandler().equals("soun")) {
        minf.addBox(new SoundMediaHeaderBox());
    } else if (track.getHandler().equals("text")) {
        minf.addBox(new NullMediaHeaderBox());
    } else if (track.getHandler().equals("subt")) {
        minf.addBox(new SubtitleMediaHeaderBox());
    } else if (track.getHandler().equals("hint")) {
        minf.addBox(new HintMediaHeaderBox());
    } else if (track.getHandler().equals("sbtl")) {
        minf.addBox(new NullMediaHeaderBox());
    }

    // dinf: all these three boxes tell us is that the actual
    // data is in the current file and not somewhere external
    DataInformationBox dinf = new DataInformationBox();
    DataReferenceBox dref = new DataReferenceBox();
    dinf.addBox(dref);
    DataEntryUrlBox url = new DataEntryUrlBox();
    url.setFlags(1);
    dref.addBox(url);
    minf.addBox(dinf);
    Box stbl = createStbl(track, movie, chunks);
    minf.addBox(stbl);
    mdia.addBox(minf);
    LOG.logDebug("done with trak for track_" + track.getTrackMetaData().getTrackId());
    return trackBox;
}

these 2 methods are in my MP4BuilderV2 and i call it here a TrimActivity like this :

Container out = new DefaultMp4BuilderV2().build(movie);
        MovieHeaderBox mvhd = Path.getPath(out, "moov/mvhd");
        mvhd.setMatrix(Matrix.ROTATE_180);

        if (!dst.exists()) {
            dst.createNewFile();
        } else {
            dst.delete();
            dst.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(dst);
        WritableByteChannel fc = fos.getChannel();
        try {
            out.writeContainer(fc);
        }catch (Exception e) {
            Log.e("erreur", e.toString());
        }finally {
            fc.close();
            fos.close();
            file.close();
        }
        file.close();

But in the last try/catch i get this error : java.nio.BufferOverflowException

If someone has the solution thanks in advance


Solution

  • I was with the same problem as you, searching for a solution I found a meta tag insertion implementation that worked for me, maybe it helps you.