public void close() throws IOException {
        if (r != null) {
            r = null;
            ogg.close();
            ogg = null;
        }
        if (w != null) {
            // First, write the initial packet of each stream
            // Skeleton (if present) goes first, then video, then audio(s)
            OggPacketWriter sw = null;
            if (skeleton != null) {
                sw = ogg.getPacketWriter();
                sw.bufferPacket(skeleton.getFishead().write(), true);
            }

            w.bufferPacket(info.write(), true);

            for (OggAudioStreamHeaders audio : soundtrackWriters.keySet()) {
                OggPacketWriter aw = soundtrackWriters.get(audio);
                aw.bufferPacket(audio.getInfo().write(), true);
            }

            // Next, provide the rest of the skeleton information, to
            //  make it easy to work out what's what
            if (skeleton != null) {
                for (SkeletonFisbone bone : skeleton.getFisbones()) {
                    sw.bufferPacket(bone.write(), true);
                }
                for (SkeletonKeyFramePacket frame : skeleton.getKeyFrames()) {
                    sw.bufferPacket(frame.write(), true);
                }
            }

            // Next is the rest of the Theora headers
            w.bufferPacket(comments.write(), true);
            w.bufferPacket(setup.write(), true);

            // Finish the headers with the soundtrack stream remaining headers
            for (OggAudioStreamHeaders audio : soundtrackWriters.keySet()) {
                OggPacketWriter aw = soundtrackWriters.get(audio);
                aw.bufferPacket(audio.getTags().write(), true);
                if (audio.getSetup() != null) {
                    aw.bufferPacket(audio.getSetup().write(), true);
                }
            }

            // Write the audio visual data, along with their granules
            long lastGranule = 0;
            for (AudioVisualDataAndSid avData : writtenPackets) {
                OggPacketWriter avw = w;
                if (avData.sid != sid) {
                    avw = soundtrackWriters.get(avData.sid);
                }

                // Update the granule position as we go
                // TODO Is this the correct logic for multi-stream writing?
                if(avData.data.getGranulePosition() >= 0 &&
                        lastGranule != avData.data.getGranulePosition()) {
                    avw.flush();
                    lastGranule = avData.data.getGranulePosition();
                    avw.setGranulePosition(lastGranule);
                }

                // Write the data, flushing if needed
                avw.bufferPacket(avData.data.write());
                if(avw.getSizePendingFlush() > 16384) {
                    avw.flush();
                }
            }

            // Close down all our writers
            w.close();
            w = null;

            if (sw != null) {
                sw.close();
                sw = null;
            }
            for (OggPacketWriter aw : soundtrackWriters.values()) {
                aw.close();
            }

            ogg.close();
            ogg = null;
        }
    }
public void close ( ) throws IOException { if ( r != null ) { r = null ; ogg . close ( ) ; ogg = null ; } if ( w != null ) { OggPacketWriter sw = null ; if ( skeleton != null ) { sw = ogg . getPacketWriter ( ) ; sw . bufferPacket ( skeleton . getFishead ( ) . write ( ) , true ) ; } w . bufferPacket ( info . write ( ) , true ) ; for ( OggAudioStreamHeaders audio : soundtrackWriters . keySet ( ) ) { OggPacketWriter aw = soundtrackWriters . get ( audio ) ; aw . bufferPacket ( audio . getInfo ( ) . write ( ) , true ) ; } if ( skeleton != null ) { for ( SkeletonFisbone bone : skeleton . getFisbones ( ) ) { sw . bufferPacket ( bone . write ( ) , true ) ; } for ( SkeletonKeyFramePacket frame : skeleton . getKeyFrames ( ) ) { sw . bufferPacket ( frame . write ( ) , true ) ; } } w . bufferPacket ( comments . write ( ) , true ) ; w . bufferPacket ( setup . write ( ) , true ) ; for ( OggAudioStreamHeaders audio : soundtrackWriters . keySet ( ) ) { OggPacketWriter aw = soundtrackWriters . get ( audio ) ; aw . bufferPacket ( audio . getTags ( ) . write ( ) , true ) ; if ( audio . getSetup ( ) != null ) { aw . bufferPacket ( audio . getSetup ( ) . write ( ) , true ) ; } } long lastGranule = 0 ; for ( AudioVisualDataAndSid avData : writtenPackets ) { OggPacketWriter avw = w ; if ( avData . sid != sid ) { avw = soundtrackWriters . get ( avData . sid ) ; } if ( avData . data . getGranulePosition ( ) >= 0 && lastGranule != avData . data . getGranulePosition ( ) ) { avw . flush ( ) ; lastGranule = avData . data . getGranulePosition ( ) ; avw . setGranulePosition ( lastGranule ) ; } avw . bufferPacket ( avData . data . write ( ) ) ; if ( avw . getSizePendingFlush ( ) > 16384 ) { avw . flush ( ) ; } } w . close ( ) ; w = null ; if ( sw != null ) { sw . close ( ) ; sw = null ; } for ( OggPacketWriter aw : soundtrackWriters . values ( ) ) { aw . close ( ) ; } ogg . close ( ) ; ogg = null ; } }
In Reading mode, will close the underlying ogg
file and free its resources.
In Writing mode, will write out the Info, Comment
Tags objects, and then the video and audio data.