net.urlgrey.mythpodcaster.transcode.TranscodingControllerImpl.java Source code

Java tutorial

Introduction

Here is the source code for net.urlgrey.mythpodcaster.transcode.TranscodingControllerImpl.java

Source

/*
 * TranscodingControllerImpl.java
 * 
 * Created: Feb 19, 2010
 * 
 * Copyright (C) 2010 Scott Kidder
 * 
 * This file is part of MythPodcaster
 * 
 * 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.urlgrey.mythpodcaster.transcode;

import java.io.File;
import java.rmi.server.UID;
import java.util.Calendar;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;

import net.urlgrey.mythpodcaster.jobs.JobHistoryCollectionBean;
import net.urlgrey.mythpodcaster.jobs.JobHistoryItemBean;
import net.urlgrey.mythpodcaster.jobs.JobHistoryItemBean.JobStatus;
import net.urlgrey.mythpodcaster.xml.GenericTranscoderConfigurationItem;
import net.urlgrey.mythpodcaster.xml.TranscodingProfile;

/**
 * @author scottkidder
 * 
 */
public class TranscodingControllerImpl implements TranscodingController {

    private static final Logger LOGGER = Logger.getLogger(TranscodingControllerImpl.class);
    private Transcoder ffmpegTranscoder;
    private Transcoder segmentedVodTranscoder;
    private Transcoder userDefinedTranscoder;
    private Transcoder symbolicLinkTranscoder;
    private JobHistoryCollectionBean jobHistory;

    @Override
    public void transcode(TranscodingProfile profile, String programKey, String seriesTitle, String programTitle,
            File inputFile, File outputFile) throws Exception {

        // construct a new Job History Item bean to represent the active job
        final JobHistoryItemBean jobHistoryItem = new JobHistoryItemBean();
        jobHistoryItem.setStartedAt(Calendar.getInstance());
        jobHistoryItem.setStatus(JobStatus.TRANSCODING);
        jobHistoryItem.setTranscodingProfileName(profile.getDisplayName());
        jobHistoryItem.setTranscodingProgramKey(programKey);
        jobHistoryItem.setTranscodingSeriesTitle(seriesTitle);
        jobHistoryItem.setTranscodingProgramName(programTitle);
        this.jobHistory.addJobHistoryItemBean(jobHistoryItem);

        try {
            switch (profile.getMode()) {
            case ONE_PASS:
                encodeOnePass(profile, inputFile, outputFile);
                break;
            case TWO_PASS:
                encodeTwoPass(profile, inputFile, outputFile);
                break;
            case HTTP_SEGMENTED_VOD:
            case ONE_PASS_HTTP_SEGMENTED_VOD:
                encodeOnePassSegmented(profile, inputFile, outputFile);
                break;
            case TWO_PASS_HTTP_SEGMENTED_VOD:
                encodeTwoPassSegmented(profile, inputFile, outputFile);
                break;
            case USER_DEFINED:
                encodeUserDefined(profile, inputFile, outputFile);
                break;
            case SYMBOLIC_LINK:
                encodeSymbolicLink(profile, inputFile, outputFile);
                break;
            default:
                break;
            }

            jobHistoryItem.setStatus(JobStatus.FINISHED);
        } catch (Exception e) {
            jobHistoryItem.setStatus(JobStatus.ERROR);
        } finally {
            jobHistoryItem.setFinishedAt(Calendar.getInstance());
        }
    }

    private void encodeSymbolicLink(TranscodingProfile profile, File inputFile, File outputFile) throws Exception {
        LOGGER.info("Starting symbolic-link encoding: inputFile[" + inputFile.getAbsolutePath() + "]");

        final File workingDirectory = FileOperations.createTempDir();
        final GenericTranscoderConfigurationItem config;
        if (profile.getTranscoderConfigurationItems() == null
                || profile.getTranscoderConfigurationItems().size() == 0) {
            config = new GenericTranscoderConfigurationItem();
            config.setTimeout(60);
        } else {
            config = profile.getTranscoderConfigurationItems().get(0);
        }

        try {
            symbolicLinkTranscoder.transcode(workingDirectory, config, inputFile, outputFile);
        } finally {
            FileOperations.deleteDir(workingDirectory);
        }
    }

    private void encodeUserDefined(TranscodingProfile profile, File inputFile, File outputFile) throws Exception {

        LOGGER.info("Starting user-defined encoding: inputFile[" + inputFile.getAbsolutePath() + "]");
        final File workingDirectory = FileOperations.createTempDir();

        try {
            File tempInputFile = null;
            File tempOutputFile = null;
            final List<GenericTranscoderConfigurationItem> configItems = profile.getTranscoderConfigurationItems();
            for (GenericTranscoderConfigurationItem config : configItems) {
                if (tempOutputFile == null) {
                    // first run, use the original input
                    tempInputFile = inputFile;
                } else {
                    // use the output from the previously executed command
                    tempInputFile = tempOutputFile;
                }

                if (config.equals(configItems.get(configItems.size() - 1))) {
                    tempOutputFile = File.createTempFile(new UID().toString(), profile.getEncodingFileExtension(),
                            workingDirectory);
                } else {
                    tempOutputFile = File.createTempFile(new UID().toString(), "tmp", workingDirectory);
                }
                userDefinedTranscoder.transcode(workingDirectory, config, tempInputFile, tempOutputFile);
            }

            FileOperations.copy(tempOutputFile, outputFile);
        } finally {
            FileOperations.deleteDir(workingDirectory);
        }
    }

    private void encodeOnePass(TranscodingProfile profile, File inputFile, File outputFile) throws Exception {

        LOGGER.info("Starting 1-pass encoding: inputFile[" + inputFile.getAbsolutePath() + "]");
        File workingDirectory = FileOperations.createTempDir();

        try {
            ffmpegTranscoder.transcode(workingDirectory, profile.getTranscoderConfigurationItems().get(0),
                    inputFile, outputFile);
        } finally {
            FileOperations.deleteDir(workingDirectory);
        }
    }

    private void encodeTwoPass(TranscodingProfile profile, File inputFile, File outputFile) throws Exception {

        LOGGER.info("Starting 2-pass encoding: inputFile[" + inputFile.getAbsolutePath() + "]");
        File workingDirectory = FileOperations.createTempDir();
        try {
            final GenericTranscoderConfigurationItem pass1Config = profile.getTranscoderConfigurationItems().get(0);
            ffmpegTranscoder.transcode(workingDirectory, pass1Config, inputFile, outputFile);

            final GenericTranscoderConfigurationItem pass2Config = profile.getTranscoderConfigurationItems().get(1);
            ffmpegTranscoder.transcode(workingDirectory, pass2Config, inputFile, outputFile);
        } finally {
            FileOperations.deleteDir(workingDirectory);
        }
    }

    private void encodeOnePassSegmented(TranscodingProfile profile, File inputFile, File outputFile)
            throws Exception {

        LOGGER.info("Starting one-pass segmented vod encoding: inputFile[" + inputFile.getAbsolutePath() + "]");
        File workingDirectory = FileOperations.createTempDir();
        File tempOutputFile = File.createTempFile(new UID().toString(), "tmp");

        try {
            final GenericTranscoderConfigurationItem pass1Config = profile.getTranscoderConfigurationItems().get(0);
            ffmpegTranscoder.transcode(workingDirectory, pass1Config, inputFile, tempOutputFile);

            final GenericTranscoderConfigurationItem segmentedVodConfig = profile.getTranscoderConfigurationItems()
                    .get(1);
            segmentedVodTranscoder.transcode(workingDirectory, segmentedVodConfig, tempOutputFile, outputFile);
        } catch (Exception e) {
            FileOperations.deleteDir(outputFile.getParentFile());
            throw e;
        } finally {
            FileOperations.deleteDir(workingDirectory);

            if (tempOutputFile.exists()) {
                tempOutputFile.delete();
            }
        }
    }

    private void encodeTwoPassSegmented(TranscodingProfile profile, File inputFile, File outputFile)
            throws Exception {

        LOGGER.info("Starting two-pass segmented vod encoding: inputFile[" + inputFile.getAbsolutePath() + "]");
        File workingDirectory = FileOperations.createTempDir();
        File tempOutputFile = File.createTempFile(new UID().toString(), "tmp");

        try {
            final GenericTranscoderConfigurationItem pass1Config = profile.getTranscoderConfigurationItems().get(0);
            ffmpegTranscoder.transcode(workingDirectory, pass1Config, inputFile, tempOutputFile);

            final GenericTranscoderConfigurationItem pass2Config = profile.getTranscoderConfigurationItems().get(1);
            ffmpegTranscoder.transcode(workingDirectory, pass2Config, inputFile, tempOutputFile);

            final GenericTranscoderConfigurationItem segmentedVodConfig = profile.getTranscoderConfigurationItems()
                    .get(2);
            segmentedVodTranscoder.transcode(workingDirectory, segmentedVodConfig, tempOutputFile, outputFile);
        } catch (Exception e) {
            FileOperations.deleteDir(outputFile.getParentFile());
            throw e;
        } finally {
            FileOperations.deleteDir(workingDirectory);

            if (tempOutputFile.exists()) {
                tempOutputFile.delete();
            }
        }
    }

    @Required
    public void setFfmpegTranscoder(Transcoder ffmpegTranscoder) {
        this.ffmpegTranscoder = ffmpegTranscoder;
    }

    @Required
    public void setSegmentedVodTranscoder(Transcoder segmentedVodTranscoder) {
        this.segmentedVodTranscoder = segmentedVodTranscoder;
    }

    @Required
    public void setUserDefinedTranscoder(Transcoder userDefinedTranscoder) {
        this.userDefinedTranscoder = userDefinedTranscoder;
    }

    @Required
    public void setSymbolicLinkTranscoder(Transcoder symbolicLinkTranscoder) {
        this.symbolicLinkTranscoder = symbolicLinkTranscoder;
    }

    @Required
    public void setJobHistory(JobHistoryCollectionBean jobHistory) {
        this.jobHistory = jobHistory;
    }
}