net.landora.video.mediainfo.MediaInfoParser.java Source code

Java tutorial

Introduction

Here is the source code for net.landora.video.mediainfo.MediaInfoParser.java

Source

/**
 * Copyright (C) 2012-2014 Blake Dickie
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package net.landora.video.mediainfo;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.landora.video.programs.CommonPrograms;
import net.landora.video.programs.ProgramsAddon;
import net.landora.video.properties.AudioFormat;
import net.landora.video.properties.AudioStream;
import net.landora.video.properties.Chapter;
import net.landora.video.properties.NamedChapter;
import net.landora.video.properties.SubtitleFormat;
import net.landora.video.properties.SubtitleStream;
import net.landora.video.properties.Video;
import net.landora.video.properties.VideoFormat;
import net.landora.video.properties.VideoStream;
import org.apache.commons.io.IOUtils;

/**
 *
 * @author bdickie
 */
public class MediaInfoParser {

    public static final Pattern dataPattern = Pattern.compile("([^:]+?)\\s*:\\s*(.*?)\\s*");
    private static final Pattern numberPattern = Pattern.compile("\\d+");
    private static final Pattern chapterStartPattern = Pattern.compile("(\\d+):(\\d+):(\\d+\\.\\d+)\\s*(.*?)");

    public static Video parseFile(File f) {
        return new MediaInfoParser().handleFile(f);
    }

    private State state;
    private Video file;
    private VideoStream curVideo;
    private AudioStream curAudio;
    private SubtitleStream curSubtitle;
    private int audioCount;
    private int subtitleCount;

    public Video handleFile(File f) {

        try {
            //ProcessBuilder process = new ProcessBuilder(Program.MediaInfo.getConfiguredPath(), "-Full", "--Language=raw", f.getAbsolutePath());
            ProcessBuilder process = new ProcessBuilder(
                    ProgramsAddon.getInstance().getConfiguredPath(CommonPrograms.MEDIAINFO), "-Full",
                    "--Language=raw", f.getAbsolutePath());
            process.redirectErrorStream(true);
            Process p = process.start();

            StringWriter buffer = new StringWriter();
            IOUtils.copy(p.getInputStream(), buffer);
            p.waitFor();

            String reply = buffer.toString();
            buffer = null;

            file = new Video();
            file.setFile(f);

            state = State.EmptyLine;

            BufferedReader reader = new BufferedReader(new StringReader(reply));
            String line;
            while ((line = reader.readLine()) != null) {

                Matcher m = dataPattern.matcher(line);
                if (m.matches()) {
                    String field = m.group(1);
                    String value = m.group(2);

                    switch (state) {
                    case General:
                        handleGeneral(field, value);
                        break;

                    case Video:
                        handleVideo(field, value);
                        break;

                    case Audio:
                        handleAudio(field, value);
                        break;

                    case Text:
                        handleSubtitle(field, value);
                        break;

                    case Chapters:
                        handleChapter(field, value);
                        break;
                    }

                } else if (line.trim().isEmpty()) {
                    state = State.EmptyLine;
                } else {
                    line = line.trim();
                    if (line.equals("General")) {
                        state = State.General;
                    } else if (line.equals("Video")) {
                        state = State.Video;
                        curVideo = new VideoStream();
                        file.getVideoStreams().add(curVideo);
                    } else if (line.equals("Audio")) {
                        state = State.Audio;
                        curAudio = new AudioStream();
                        curAudio.setStreamId(++audioCount);
                        file.getAudioStreams().add(curAudio);
                    } else if (line.equals("Text")) {
                        state = State.Text;
                        curSubtitle = new SubtitleStream();
                        curSubtitle.setStreamId(subtitleCount++);
                        file.getSubtitleStreams().add(curSubtitle);
                    } else if (line.equals("Chapters")) {
                        state = State.Chapters;
                    }
                }

            }

            cleanupChapters();

            return file;
        } catch (Exception e) {
            return null;
        }
    }

    private void handleGeneral(String field, String value) {
        if (field.equals("Duration")) {
            long lengthMS = Long.parseLong(value);
            file.setLength(lengthMS / 1000f);
        }
    }

    private void handleVideo(String field, String value) {
        if (field.equals("Format")) {
            curVideo.setFormat(VideoFormat.getFormat(value));
        } else if (field.equals("DisplayAspectRatio/String")) {
            curVideo.setAspect(value);
        } else if (field.equals("Language")) {
            curVideo.setLanguage(value);
        } else if (field.equals("FrameRate")) {
            curVideo.setFps(value);
        } else if (field.equals("Width")) {
            curVideo.setPixelWidth(Integer.parseInt(value));
        } else if (field.equals("Height")) {
            curVideo.setPixelHeight(Integer.parseInt(value));
        }
    }

    private void handleAudio(String field, String value) {
        if (field.equals("Format")) {
            curAudio.setFormat(AudioFormat.getFormat(value));
        } else if (field.equals("Language")) {
            curAudio.setLanguage(value);
        } else if (field.equals("Channel(s)")) {
            curAudio.setChannels(Integer.parseInt(value));
        }
    }

    private void handleSubtitle(String field, String value) {
        if (field.equals("Format")) {
            curSubtitle.setFormat(SubtitleFormat.getFormat(value));
        } else if (field.equals("Language")) {
            curSubtitle.setLanguage(value);
        }
    }

    private void handleChapter(String field, String value) {
        if (!numberPattern.matcher(field).matches()) {
            return;
        }

        int chapterNumber = Integer.parseInt(field);

        Matcher m = chapterStartPattern.matcher(value);
        if (!m.matches()) {
            return;
        }

        NamedChapter chapter = new NamedChapter();
        chapter.setTitle(m.group(4));

        float seconds = Float.parseFloat(m.group(3));
        int mins = Integer.parseInt(m.group(2));
        int hours = Integer.parseInt(m.group(1));
        chapter.setChapterNumber(chapterNumber);
        chapter.setStartTime(seconds + 60 * (mins + 60 * hours));

        file.getChapters().add(chapter);

    }

    private void cleanupChapters() {
        int num = file.getChapters().size();
        for (int i = 0; i < num; i++) {
            Chapter chapter = file.getChapters().get(i);
            float nextChap;
            if (i == num - 1) {
                nextChap = file.getLength();
            } else {
                nextChap = file.getChapters().get(i + 1).getStartTime();
            }
            chapter.setLength(nextChap - chapter.getStartTime());
        }
    }

    public static void main(String[] args) {
        Video v = parseFile(new File(
                "/var/storage/Videos/Anime/To Aru Kagaku no Railgun/To Aru Kagaku no Railgun - 02 - For Working Under the Blazing Sun, Proper Hydration is Required.mkv"));
    }

    private static enum State {

        General, Video, Audio, Text, Chapters, EmptyLine
    }
}