Search in sources :

Example 1 with QuickTimeWriter

use of ch.randelshofer.media.quicktime.QuickTimeWriter in project processing by processing.

the class MovieMaker method writeVideoAndAudio.

private void writeVideoAndAudio(File movieFile, File[] imgFiles, File audioFile, int width, int height, double fps, QuickTimeWriter.VideoFormat videoFormat, /*boolean passThrough,*/
String streaming) throws IOException {
    File tmpFile = streaming.equals("none") ? movieFile : new File(movieFile.getPath() + ".tmp");
    ProgressMonitor p = new ProgressMonitor(MovieMaker.this, Language.interpolate("movie_maker.progress.creating_file_name", movieFile.getName()), Language.text("movie_maker.progress.creating_output_file"), 0, imgFiles.length);
    AudioInputStream audioIn = null;
    QuickTimeWriter qtOut = null;
    BufferedImage imgBuffer = null;
    Graphics2D g = null;
    try {
        // Determine audio format
        if (audioFile.getName().toLowerCase().endsWith(".mp3")) {
            audioIn = new MP3AudioInputStream(audioFile);
        } else {
            audioIn = AudioSystem.getAudioInputStream(audioFile);
        }
        AudioFormat audioFormat = audioIn.getFormat();
        boolean isVBR = audioFormat.getProperty("vbr") != null && ((Boolean) audioFormat.getProperty("vbr")).booleanValue();
        // Determine duration of a single sample
        int asDuration = (int) (audioFormat.getSampleRate() / audioFormat.getFrameRate());
        int vsDuration = 100;
        // Create writer
        qtOut = new QuickTimeWriter(videoFormat == QuickTimeWriter.VideoFormat.RAW ? movieFile : tmpFile);
        // audio in track 0
        qtOut.addAudioTrack(audioFormat);
        // video in track 1
        qtOut.addVideoTrack(videoFormat, (int) (fps * vsDuration), width, height);
        // Create audio buffer
        int asSize;
        byte[] audioBuffer;
        if (isVBR) {
            // => variable bit rate: create audio buffer for a single frame
            asSize = audioFormat.getFrameSize();
            audioBuffer = new byte[asSize];
        } else {
            // => fixed bit rate: create audio buffer for half a second
            asSize = audioFormat.getChannels() * audioFormat.getSampleSizeInBits() / 8;
            audioBuffer = new byte[(int) (qtOut.getMediaTimeScale(0) / 2 * asSize)];
        }
        //if (!passThrough) {
        if (true) {
            imgBuffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            g = imgBuffer.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        }
        // Main loop
        int movieTime = 0;
        int imgIndex = 0;
        boolean isAudioDone = false;
        while ((imgIndex < imgFiles.length || !isAudioDone) && !p.isCanceled()) {
            // Advance movie time by half a second (we interleave twice per second)
            movieTime += qtOut.getMovieTimeScale() / 2;
            // Advance audio to movie time + 1 second (audio must be ahead of video by 1 second)
            while (!isAudioDone && qtOut.getTrackDuration(0) < movieTime + qtOut.getMovieTimeScale()) {
                int len = audioIn.read(audioBuffer);
                if (len == -1) {
                    isAudioDone = true;
                } else {
                    qtOut.writeSamples(0, len / asSize, audioBuffer, 0, len, asDuration);
                }
                if (isVBR) {
                    // => variable bit rate: format can change at any time
                    audioFormat = audioIn.getFormat();
                    if (audioFormat == null) {
                        break;
                    }
                    asSize = audioFormat.getFrameSize();
                    asDuration = (int) (audioFormat.getSampleRate() / audioFormat.getFrameRate());
                    if (audioBuffer.length < asSize) {
                        audioBuffer = new byte[asSize];
                    }
                }
            }
            // Advance video to movie time
            for (; imgIndex < imgFiles.length && qtOut.getTrackDuration(1) < movieTime; ++imgIndex) {
                // catch up with video time
                p.setProgress(imgIndex);
                File f = imgFiles[imgIndex];
                if (f == null)
                    continue;
                p.setNote(Language.interpolate("movie_maker.progress.processing", f.getName()));
                //if (passThrough) {
                if (false) {
                    qtOut.writeSample(1, f, vsDuration);
                } else {
                    //BufferedImage fImg = ImageIO.read(imgFiles[imgIndex]);
                    BufferedImage fImg = readImage(f);
                    if (fImg == null)
                        continue;
                    g.drawImage(fImg, 0, 0, width, height, null);
                    fImg.flush();
                    qtOut.writeFrame(1, imgBuffer, vsDuration);
                }
            }
        }
        if (streaming.equals("fastStart")) {
            qtOut.toWebOptimizedMovie(movieFile, false);
            tmpFile.delete();
        } else if (streaming.equals("fastStartCompressed")) {
            qtOut.toWebOptimizedMovie(movieFile, true);
            tmpFile.delete();
        }
        qtOut.close();
        qtOut = null;
    } catch (UnsupportedAudioFileException e) {
        IOException ioe = new IOException(e.getMessage());
        ioe.initCause(e);
        throw ioe;
    } finally {
        p.close();
        if (qtOut != null) {
            qtOut.close();
        }
        if (audioIn != null) {
            audioIn.close();
        }
        if (g != null) {
            g.dispose();
        }
        if (imgBuffer != null) {
            imgBuffer.flush();
        }
    }
}
Also used : MP3AudioInputStream(ch.randelshofer.media.mp3.MP3AudioInputStream) QuickTimeWriter(ch.randelshofer.media.quicktime.QuickTimeWriter) MP3AudioInputStream(ch.randelshofer.media.mp3.MP3AudioInputStream)

Example 2 with QuickTimeWriter

use of ch.randelshofer.media.quicktime.QuickTimeWriter in project processing by processing.

the class MovieMaker method writeAudioOnly.

private void writeAudioOnly(File movieFile, File audioFile, String streaming) throws IOException {
    File tmpFile = streaming.equals("none") ? movieFile : new File(movieFile.getPath() + ".tmp");
    // file length is used for a rough progress estimate. This will only work for uncompressed audio.
    int length = (int) Math.min(Integer.MAX_VALUE, audioFile.length());
    ProgressMonitor p = new ProgressMonitor(MovieMaker.this, Language.interpolate("movie_maker.progress.creating_file_name", movieFile.getName()), Language.text("movie_maker.progress.initializing"), 0, length);
    AudioInputStream audioIn = null;
    QuickTimeWriter qtOut = null;
    try {
        qtOut = new QuickTimeWriter(tmpFile);
        if (audioFile.getName().toLowerCase().endsWith(".mp3")) {
            audioIn = new MP3AudioInputStream(audioFile);
        } else {
            audioIn = AudioSystem.getAudioInputStream(audioFile);
        }
        AudioFormat audioFormat = audioIn.getFormat();
        //System.out.println("QuickTimeMovieMakerMain " + audioFormat);
        qtOut.addAudioTrack(audioFormat);
        boolean isVBR = audioFormat.getProperty("vbr") != null && ((Boolean) audioFormat.getProperty("vbr")).booleanValue();
        int asSize = audioFormat.getFrameSize();
        int nbOfFramesInBuffer = isVBR ? 1 : Math.max(1, 1024 / asSize);
        int asDuration = (int) (audioFormat.getSampleRate() / audioFormat.getFrameRate());
        //System.out.println("  frameDuration=" + asDuration);
        long count = 0;
        byte[] audioBuffer = new byte[asSize * nbOfFramesInBuffer];
        for (int bytesRead = audioIn.read(audioBuffer); bytesRead != -1; bytesRead = audioIn.read(audioBuffer)) {
            if (bytesRead != 0) {
                int framesRead = bytesRead / asSize;
                qtOut.writeSamples(0, framesRead, audioBuffer, 0, bytesRead, asDuration);
                count += bytesRead;
                p.setProgress((int) count);
            }
            if (isVBR) {
                audioFormat = audioIn.getFormat();
                if (audioFormat == null) {
                    break;
                }
                asSize = audioFormat.getFrameSize();
                asDuration = (int) (audioFormat.getSampleRate() / audioFormat.getFrameRate());
                if (audioBuffer.length < asSize) {
                    audioBuffer = new byte[asSize];
                }
            }
        }
        audioIn.close();
        audioIn = null;
        if (streaming.equals("fastStart")) {
            qtOut.toWebOptimizedMovie(movieFile, false);
            tmpFile.delete();
        } else if (streaming.equals("fastStartCompressed")) {
            qtOut.toWebOptimizedMovie(movieFile, true);
            tmpFile.delete();
        }
        qtOut.close();
        qtOut = null;
    } catch (UnsupportedAudioFileException e) {
        IOException ioe = new IOException(e.getMessage());
        ioe.initCause(e);
        throw ioe;
    } finally {
        p.close();
        if (audioIn != null) {
            audioIn.close();
        }
        if (qtOut != null) {
            qtOut.close();
        }
    }
}
Also used : MP3AudioInputStream(ch.randelshofer.media.mp3.MP3AudioInputStream) QuickTimeWriter(ch.randelshofer.media.quicktime.QuickTimeWriter) MP3AudioInputStream(ch.randelshofer.media.mp3.MP3AudioInputStream)

Example 3 with QuickTimeWriter

use of ch.randelshofer.media.quicktime.QuickTimeWriter in project processing by processing.

the class MovieMaker method writeVideoOnlyVFR.

/** variable frame rate. */
private void writeVideoOnlyVFR(File movieFile, File[] imgFiles, int width, int height, double fps, QuickTimeWriter.VideoFormat videoFormat, /*boolean passThrough,*/
String streaming) throws IOException {
    File tmpFile = streaming.equals("none") ? movieFile : new File(movieFile.getPath() + ".tmp");
    ProgressMonitor p = new ProgressMonitor(MovieMaker.this, Language.interpolate("movie_maker.progress.creating_file_name", movieFile.getName()), Language.text("movie_maker.progress.creating_output_file"), 0, imgFiles.length);
    Graphics2D g = null;
    BufferedImage img = null;
    BufferedImage prevImg = null;
    int[] data = null;
    int[] prevData = null;
    QuickTimeWriter qtOut = null;
    try {
        int timeScale = (int) (fps * 100.0);
        int duration = 100;
        qtOut = new QuickTimeWriter(videoFormat == QuickTimeWriter.VideoFormat.RAW ? movieFile : tmpFile);
        qtOut.addVideoTrack(videoFormat, timeScale, width, height);
        qtOut.setSyncInterval(0, 30);
        //if (!passThrough) {
        if (true) {
            img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
            prevImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            prevData = ((DataBufferInt) prevImg.getRaster().getDataBuffer()).getData();
            g = img.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        }
        int prevImgDuration = 0;
        for (int i = 0; i < imgFiles.length && !p.isCanceled(); i++) {
            File f = imgFiles[i];
            if (f == null)
                continue;
            p.setNote(Language.interpolate("movie_maker.progress.processing", f.getName()));
            p.setProgress(i);
            //if (passThrough) {
            if (false) {
                qtOut.writeSample(0, f, duration);
            } else {
                //BufferedImage fImg = ImageIO.read(f);
                BufferedImage fImg = readImage(f);
                if (fImg == null)
                    continue;
                g.drawImage(fImg, 0, 0, width, height, null);
                if (i != 0 && Arrays.equals(data, prevData)) {
                    prevImgDuration += duration;
                } else {
                    if (prevImgDuration != 0) {
                        qtOut.writeFrame(0, prevImg, prevImgDuration);
                    }
                    prevImgDuration = duration;
                    System.arraycopy(data, 0, prevData, 0, data.length);
                }
            }
        }
        if (prevImgDuration != 0) {
            qtOut.writeFrame(0, prevImg, prevImgDuration);
        }
        if (streaming.equals("fastStart")) {
            qtOut.toWebOptimizedMovie(movieFile, false);
            tmpFile.delete();
        } else if (streaming.equals("fastStartCompressed")) {
            qtOut.toWebOptimizedMovie(movieFile, true);
            tmpFile.delete();
        }
        qtOut.close();
        qtOut = null;
    } finally {
        p.close();
        if (g != null) {
            g.dispose();
        }
        if (img != null) {
            img.flush();
        }
        if (qtOut != null) {
            qtOut.close();
        }
    }
}
Also used : QuickTimeWriter(ch.randelshofer.media.quicktime.QuickTimeWriter)

Aggregations

QuickTimeWriter (ch.randelshofer.media.quicktime.QuickTimeWriter)3 MP3AudioInputStream (ch.randelshofer.media.mp3.MP3AudioInputStream)2