All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.red5.io.webm.WebmWriter Maven / Gradle / Ivy

There is a newer version: 2.0.17
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package org.red5.io.webm;

import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.red5.io.matroska.ConverterException;
import org.red5.io.matroska.dtd.CompoundTag;
import org.red5.io.matroska.dtd.StringTag;
import org.red5.io.matroska.dtd.Tag;
import org.red5.io.matroska.dtd.TagFactory;
import org.red5.io.matroska.dtd.UnsignedIntegerTag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class able to write webm tags to file
 *
 */
public class WebmWriter implements Closeable, TagConsumer {

    private static Logger log = LoggerFactory.getLogger(WebmWriter.class);

    private boolean append;

    private RandomAccessFile dataFile;

    private File file;

    @SuppressWarnings("unused")
    private volatile long bytesWritten;

    private String filePath;

    /**
     * Constructor
     *
     * @param file
     *            - file the data need to written to
     * @param append
     *            - if false the file will be rewritten, if true data will be appended
     */
    public WebmWriter(File file, boolean append) {
        // the final version of the file will go here
        this.file = file;
        filePath = file.getAbsolutePath();
        try {
            this.append = append;
            if (append) {
                // grab the file we will append to
                if (!file.exists() || !file.canRead() || !file.canWrite()) {
                    throw new FileNotFoundException("File does not exist or cannot be accessed");
                } else {
                    log.trace("File size: {} last modified: {}", file.length(), file.lastModified());
                    // update the bytes written so we write to the correct starting position
                    bytesWritten = file.length();
                }
                this.dataFile = new RandomAccessFile(file, "rws");
            } else {
                // temporary data file for storage of stream data
                File dat = new File(filePath + ".ser");
                if (dat.exists()) {
                    dat.delete();
                    dat.createNewFile();
                }
                this.dataFile = new RandomAccessFile(dat, "rws");
            }
        } catch (Exception e) {
            log.error("Failed to create FLV writer", e);
        }
    }

    /**
     * method to write webm header to the new file
     *
     * @throws IOException
     *             - in case of IO errors
     * @throws ConverterException
     *             - in case of conversion errors
     */
    public void writeHeader() throws IOException, ConverterException {
        if (append) {
            return;
        }
        try {
            CompoundTag ebml = TagFactory. create("EBML").add(TagFactory. create("EBMLVersion").setValue(1)).add(TagFactory. create("EBMLReadVersion").setValue(1)).add(TagFactory. create("EBMLMaxIDLength").setValue(4)).add(TagFactory. create("EBMLMaxSizeLength").setValue(8))
                    .add(TagFactory. create("DocType").setValue("webm")).add(TagFactory. create("DocTypeVersion").setValue(3)).add(TagFactory. create("DocTypeReadVersion").setValue(2));
            byte[] hb = ebml.encode();
            bytesWritten += hb.length;
            dataFile.write(hb);
        } catch (IOException | ConverterException e) {
            log.error("Failed to write header", e);
            throw e;
        }
    }

    /**
     * will write tag bytesWritten counter will be increased by the number of bytes actually written
     *
     * @param tag
     *            - tag to be written
     * @throws IOException
     *             - in case of any IO errors
     */
    public void writeTag(Tag tag) throws IOException {
        byte[] hb = tag.encode();
        bytesWritten += hb.length;
        dataFile.write(hb);
    }

    /**
     * Will close all opened resources and "finalize" the write process
     */
    @Override
    public void close() throws IOException {
        if (dataFile != null) {
            //TODO create separate method for this
            if (!append) {
                dataFile.seek(0);
                try (RandomAccessFile rf = new RandomAccessFile(file, "rw")) {
                    rf.getChannel().transferFrom(dataFile.getChannel(), 0, dataFile.length());
                }
            }
            try {
                dataFile.close();
                dataFile = null;
            } catch (Throwable th) {
                //no-op
            }
        }
    }

    /**
     * @see org.red5.io.webm.TagConsumer#consume(org.red5.io.matroska.dtd.Tag)
     */
    @Override
    public void consume(Tag tag) throws IOException {
        //TODO add mode switch
        writeTag(tag);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy