Main.java :  » Media » jpsxdec » jpsxdec » Java Open Source

Java Open Source » Media » jpsxdec 
jpsxdec » jpsxdec » Main.java
/*
 * jPSXdec: Playstation 1 Media Decoder/Converter in Java
 * Copyright (C) 2007-2008  Michael Sabin
 *
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,   
 * Boston, MA  02110-1301, USA.
 *
 */

/*
 * Main.java
 */

/* TODO:
 * 
 * GAME SPECIFIC:
 * - Soul Reaver 009:TIM is extra wide and saved as jpg looks weird
 * - FF Chronicles has a tim file being saved as blank
 * - That FF7 gold movie has audio and video displacement like no other
 * - Legend of Mana has 000:TIM with 64 palettes! One being saved all transparent?
 * - Super Puzzle Figher 2: First movie, last frame is split because audio sector changes format
 * - Japanese Tekken 3 has subtitles for the english movie? but where is the data for that?
 * - Chrono Chross final movie - need to add handling for it
 * - Castlevania seems to have movies with lots of extra frames at the end?
 * 
 * - Lots of games have some 'almost' TIM files. Test these with PsxMC
 * // Very large audio pop at beginning of jumpingflash2_movie-01.str. Test with other decoders. >> None want to play the dang thing.
 * // FF Chron:Chrono Trigger movies are encoded choppy?? Test with other decoders. -- Seems the same there too
 * - Pop at end of 429:XA (FF Chron?) disc 1. Test with PsxMC
 * 
 * // Linux - VLC claims avi files are broken. Always shows even after repair -- fixed
 * // Linux - mplayer plays MJPG stretched virt and crashes with DIB. Plays vid upside-down + horz stretched after VLC repair >> mplayer sucks
 * - linux totem shows some messy green stuff in MJPG -- learn more about MJPG
 * - Linux (Compiz): Progress gui often appears blank, so there's no way to close it
 * // AVI (both types) can't be played in quicktime
 * 
 * /- Pull the uncompressing and MDEC decoding out of the PSXMedia and put it in
 *   a decoder factory.
 * - Make all types of decoders: 1) Debug uncompress 
 *                               2) Debug MDEC 
 *                               3) Debug YUV
 *                               4) Swift Uncompress+MDEC (->YUV)
 *                               4) Swift Java full decode
 *                               5) Swift Java Uncompress
 *                               6) Swift MDEC->RGB
 *                               7) Native full decode
 * 
 * - Figure out how the heck to REALLY handle variable frame rates (Alice)
 * - No thanks to Puzzle Figher 2, it may finally be time to take PsxMC's decoding approach
 * 
 * - Create a "player" (like a saver) that watches how much time has elapsed
 *   and skips decoding frames as necessary.
 * /- add crazy super fast native decoder
 * - add swift Java decoder
 * - add swift Java uncompressor
 * - Create a separate class for demux and mdec 'image' saving 
 * 
 * - Add abstract protected function "IdentifySector()" in MediaStreaming
 *   to more quickly figure out what type of sectors are read (since it won't
 *   have to go through the whole list of like 10 types).
 * 
 * - Raw CD reading seems fickle and often won't return raw sectors for certain
 *   sector/track types. Figure out how to skip a bulk of such sector types
 *   so raw CD reading isn't so slow.
 * - add the audio channel # to STR serialization (handy reference)
 * - inform user if corrupted data is found while reading sectors
 * - Re-add storing the saving folder to ini file
 * - Figure out how netbeans uses a folder chooser so I can use it too
 * - Add some checking during index file load to stop a 600mb scan of death
 * - Change IndexLineParser to just use regex for parsing
 * - change TIM serialization to include how many palettes it has
 * - change gui to use JFileChooser
 * - clean up main
 * - add the more thorough searching for TIM files to PSXMedia. do it like
 *   XA searching with a static function in PSXMediaTIM
 * /- fix avi saving
 * !! TODO: Give credits for Yuv2Rgb function
 * /! add option to select the IDCT
 * // Find license file mentioned in FileNameExtensionFilter
 * /! Combine all video decoding into one package
 * /! make progress window closable
 * ? make playback listeners more robust by allowing any number of listeners
 * - add volume option to gui
 * /- make IDCT easier to interchange
 * - test test test
 * - in progress gui, setup a timer to only update the display at most every second 
 * - combine IProgressListener and Progress gui interfaces so there is only one
 * // unify the audio/video format handling so i'm not just passing strings around
 * // Figure out why jlist has empty entries at the end
 * // add tim decoding gui
 * // unify CommandLine and SaveOpions classes
 * // Progress gui- when fatal exception occurs, throw the stack trace into the text box
 * 
 * - change media list to be a tree list showing all the files on the disc
 *   and what media belongs to what file. if not a disc image, just show
 *   the file name and the media it contains
 * - visually populate the list as the disc/file is being indexed
 * * use ISO9660 to help name media items
 * - add MediaVideo.DecodeFrame for quick thumbnailing
 * - add best guess for Audio2048 properties so fps calc has a chance to figure it out
 * 
 * - pull yuv writing to its own class, a YuvWriter, and let it accept
 *   PsxYuv images for each frame's input.
 * - Change PsxYuv.write(OutputStream) to only write the header if requested,
 *   so multiple images can be written to the same stream
 * - fix output of YUV images to adjust for yuv4mpeg2 color space
 * 
 * - to pipe to ffmpeg/mencoder (on Linux only), use named pipes and write yuv data to one
 *   and audio data to the other.
 * 
 * /- change CommandLine class to use a tiered architecture, remvoing
 *   elements from the array as we find matching commands and passing the
 *   rest furthur down the stream
 * 
 * // Finish encoder gui.
 * // Test the new games
 * // Add jpeg quality settings to AviWriter MJPG output
 *
 * OPTIMIZE:
 * // All InputStreams: implement read(byte[]) methods for hopefully faster reading.
 * - audio decoding: Str audio write directly to byte array and use ByteArrayInputStream
 *                   Square audio write directy to byte array and use a Byte2DArrayInputStream
 *                   or write to an InterleavedShort2DArrayOutputStream
 * // don't use streams to read headers, just pass the original byte array and read values out of it
 * 
 * /- finish STR format documentation
 * - make code documentation
 * - make manual
 * /- make CREDITS file
 * /- CLEANUP!!
 * // better organize the error reporting/checking
 * - develop a test set
 *
 * OPTIONS:
 * - need to clean up plugin command-line
 * - add option to set 24/16 bit color, or yuv420/yuv422
 * - add option to walk through a file byte by byte to find any compressed mdec data
 * xx add option to ignore checks and just decode whatever it can (probably part of --decode-frame/--decode-audio)
 * /- add option to copy str/xa sectors from image
 * - add --format option to LAPKS
 * - add --nocrop option
 * // add option to save audio to the other formats
 *
 * CONSIDER:
 * ? Make avi saving more robust by writing as much of the header as possible
 *   and updating the frame count, file size, etc in the headers as frames as written,
 *   and maybe even writing the index after each frame, then backing up and
 *   overwriting it with the next frame and then the index again (could really
 *   slow down the writing, maybe provide this as an option?)
 * // get rid of mdec & yuv listener. the demux istener must handle the rest of the decoding.
 * ? Consider making PSXSector just a subclass of CDXASector
 *
 * FUTURE VERSIONS:
 * // Add frame rate calculation
 * - add better stdin/stdout file handling
 * //- add FF9 audio decoding
 * /- add GUI
 * /- add raw CD reading for windows
 * /- add encoding to a video format
 * 
 */

package jpsxdec;


import jpsxdec.cdreaders.CDXASector;
import jpsxdec.media.IProgressListener;
import java.io.*;
import java.util.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import jpsxdec.cdreaders.CDXAIterator;
import jpsxdec.cdreaders.CDSectorReader;
import jpsxdec.cdreaders.iso9660.ISOFile;
import jpsxdec.cdreaders.iso9660.TestISO;
import jpsxdec.cdreaders.iso9660.VolumePrimaryDescriptor;
import jpsxdec.mdec.MDEC;
import jpsxdec.demuxers.*;
import jpsxdec.mdec.PsxYuv;
import jpsxdec.media.*;
import jpsxdec.media.PSXMediaStreaming;
import jpsxdec.media.savers.*;
import jpsxdec.media.savers.Formats.ImgSeqVidFormat;
import jpsxdec.plugins.*;
import jpsxdec.sectortypes.*;
import jpsxdec.videodecoding.CriticalUncompressException;
import jpsxdec.videodecoding.StrFrameUncompressor;
import jpsxdec.util.*;

public class Main {
    
    public static int DebugVerbose = 2;
    public final static String Version = "0.35(beta)";
    public final static String VerString = "jPSXdec: PSX media decoder, v" + Version;
    private static CommandLine m_oMainSettings;

    private static void timsearch() {
        try {
            CDSectorReader oCD = CDSectorReader.Open("..\\..\\disc1.iso");
            
            PSXSectorRangeIterator oIter = new PSXSectorRangeIterator(oCD);
            int iCount = 0;
            while (oIter.hasNext()) {
                
                while (oIter.hasNext())
                {
                    if (oIter.peekNext() instanceof PSXSectorUnknownData)
                        break;
                    else
                        oIter.skipNext();
                }
                if (!oIter.hasNext()) break;

                try {
                    UnknownDataPullDemuxerIS oStrm = new UnknownDataPullDemuxerIS(oIter);
                    while (true) {
                        oStrm.mark(-1);
                        long lng = oStrm.getFilePointer();
                        try {
                            Tim oTim = new Tim(oStrm);
                            System.out.println(iCount + "# "+ lng + " to " + oStrm.getFilePointer());
                            for (int i = 0; i < oTim.getPaletteCount(); i++) {
                                ImageIO.write(oTim.toBufferedImage(i),"png", new File(iCount + "-" + lng + "-" + i + ".png"));
                            }
                            iCount++;
                        } catch (NotThisTypeException ex) {}
                        oStrm.reset();
                        oStrm.skip(4);
                    }
                } catch (EOFException ex) {
                    //ex.printStackTrace();
                }
            }
            
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        System.exit(0);
    }
    
    
    public static void main(String[] args) {
        
        //timsearch(); // test
        
        m_oMainSettings = new CommandLine(args);

        if (m_oMainSettings.gotDebug()) {
            // set verbosity
            int[] aiVerbosityLevels = m_oMainSettings.getDebug();
            Main.DebugVerbose = aiVerbosityLevels[0];
            MediaHandler.DebugVerbose = aiVerbosityLevels[1];
            PSXMedia.DebugVerbose = aiVerbosityLevels[2];
            StrFrameUncompressor.DebugVerbose = aiVerbosityLevels[3];
            MDEC.DebugVerbose = aiVerbosityLevels[4];
        }
        
        if (DebugVerbose >= 3)
            System.err.println(System.getProperty("java.class.path"));
        if (DebugVerbose >= 3)
            System.err.println(System.getProperty("java.library.path"));
        
        if (m_oMainSettings.getMainCommand() == CommandLine.MAIN_CMD_STARTGUI) {
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    new Gui().setVisible(true);
                }
            });

            return;
        }
        
        
                
        if (DebugVerbose > 0)
            System.err.println(VerString);
        
        switch (m_oMainSettings.getMainCommand()) {
            case CommandLine.MAIN_CMD_INDEX:
                System.exit(IndexOnly());
                break;
            case CommandLine.MAIN_CMD_DECODE:
                System.exit(NormalDecode());
                break;
            case CommandLine.MAIN_CMD_SPECIALFILE:
                System.exit(DecodeSpecialFrameFile());
                break;
            case CommandLine.MAIN_CMD_SECTORDUMP:
                System.exit(SectorList());
                break;
            case CommandLine.MAIN_CMD_PLUGIN:
                System.exit(Plugin());
                break;
            case CommandLine.MAIN_CMD_DIR:
            case CommandLine.MAIN_CMD_COPY:
                System.exit(DirCopy());
                break;
            case CommandLine.MAIN_CMD_COPYSECT:
                System.exit(CopySectors());
                break;
        }
        
        return;
    }
    
    //--------------------------------------------------------------------------
    
    private static int CopySectors() {
        //open input file
        CDSectorReader oCD;
        try {
            oCD = CDSectorReader.Open(m_oMainSettings.getInputFile());

            int[] aiSectors = m_oMainSettings.getSectorsToCopy();
            
            CDXAIterator oCDIter = new CDXAIterator(oCD, aiSectors[0], aiSectors[1]);
            
            if (DebugVerbose > 0)
                System.err.println("Copying sectors " + aiSectors[0] + " to " + aiSectors[1]);
            
            FileOutputStream fos = new FileOutputStream(
                    m_oMainSettings.constructOutPath(m_oMainSettings.getInputFileBase()
                    + aiSectors[0] + "-" + aiSectors[1] + ".dat"));
            
            while (oCDIter.hasNext()) {
                CDXASector oSect = oCDIter.next();
                if (oSect == null) {
                    //todo err
                } else {
                    fos.write(oSect.getRawSectorData());
                }
            }
            
            fos.close();
            
            return 0;
            
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
    }
    
    private static int DirCopy() {
        //open input file
        CDSectorReader oCD;
        try {
            oCD = CDSectorReader.Open(m_oMainSettings.getInputFile());
        
            VolumePrimaryDescriptor vpd = 
                    new VolumePrimaryDescriptor(oCD.getSector(16).getSectorDataStream());
            
            ArrayList<ISOFile> oFileList = new ArrayList<ISOFile>();

            try {
                TestISO.getFileList(vpd.root_directory_record, oCD, oFileList, new File(""));
            } catch (IndexOutOfBoundsException ex) {
                // try to read as much of the dir as is available
            }
            
            ISOFile fileToCopy = null;
            
            for (ISOFile ofile : oFileList) {
                if (m_oMainSettings.getMainCommand() == CommandLine.MAIN_CMD_DIR) {
                    System.out.println(ofile.getPath() 
                            + " " + ofile.getStartSector() + "-" + 
                            ofile.getEndSector());
                } else if (m_oMainSettings.getMainCommand() == CommandLine.MAIN_CMD_COPY) {
                    if (ofile.getPath().equals(m_oMainSettings.getFileToCopy())) {
                        fileToCopy = ofile;
                    }
                }
            }
            
            if (m_oMainSettings.getMainCommand() == CommandLine.MAIN_CMD_DIR)
                return 0;
            
            if (!oCD.HasSectorHeader()) {
                if (DebugVerbose > 0) {
                    System.err.println("Copying files out of a CD image without raw headers seems kinda useless?");
                }
                return -1;
            }

            if (fileToCopy != null)
                System.out.println("Going to copy " + fileToCopy.toString());
            else {
                System.out.println("File not found.");
                return -1;
            }
            
            CDXAIterator fileRange = new CDXAIterator(oCD, (int)fileToCopy.getStartSector(), (int)fileToCopy.getEndSector());
            
            FileOutputStream fos = new FileOutputStream(
                    m_oMainSettings.constructOutPath(fileToCopy.getName()));
            
            while (fileRange.hasNext()) {
                CDXASector oSect = fileRange.next();
                if (oSect == null) {
                    //todo err
                } else {
                    fos.write(oSect.getRawSectorData());
                }
            }
            
            fos.close();
            
            return 0;
            
        } catch (NotThisTypeException ex) {
            if (DebugVerbose > 0)
                System.err.println("CD/file does not have directory information.");
            return -1;
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
    }
    
    private static int Plugin() {
        
        String sOutFileBase = "";
        String sOutFolder = "";
        if (m_oMainSettings.gotOutputFile()) {
            sOutFileBase = m_oMainSettings.getOutputFile();
        }
        if (m_oMainSettings.gotOutputFolder()) {
            sOutFolder = m_oMainSettings.getOutputFolder();
        }
        
        String sPath = new File(sOutFolder, sOutFileBase).getAbsolutePath();
        
        if (m_oMainSettings.getPluginCommand().equals("lapks"))
            System.exit(Lain_LAPKS.DecodeLAPKS(m_oMainSettings.getInputFile(), sPath));
        else if (m_oMainSettings.getPluginCommand().equals("site"))
            System.exit(Lain_SITE.DecodeSITE(m_oMainSettings.getInputFile(), sPath));
        
        return 0;
    }
    
    private static int IndexOnly() {
        //open input file
        CDSectorReader oCD;
        try {
            oCD = CDSectorReader.Open(m_oMainSettings.getInputFile());
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
        
        if (!oCD.HasSectorHeader() && DebugVerbose > 0) {
            System.err.println("Warning: Input file does not contain entire raw CD sectors.");
            System.err.println("         Audio cannot be decoded.");
        }
        
        if (DebugVerbose > 0)
            System.err.println("Creating index");
        
        // index the STR file
        MediaHandler oMedias;
        try {
            PrintStream oPrinter;
            if (m_oMainSettings.getIndexFile().equals("-"))
                oPrinter = System.out;
            else
                oPrinter = new PrintStream(m_oMainSettings.getIndexFile());
            oMedias = new MediaHandler(oCD, new IProgressListener.IProgressEventListener() {
                public boolean ProgressUpdate(String sWhatDoing, double dblPercentComplete) {
                    return true;
                }

                public boolean ProgressUpdate(String sEvent) {
                    if (DebugVerbose > 0)
                        System.err.println(sEvent);
                    return false;
                }
            });
            oMedias.SerializeMediaList(oPrinter);
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
        
        return 0;
    }
    
    //--------------------------------------------------------------------------
    
    private static int NormalDecode() {
        //open input file
        CDSectorReader oCD;
        try {
            oCD = CDSectorReader.Open(m_oMainSettings.getInputFile());
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
        
        if (!oCD.HasSectorHeader() && DebugVerbose > 0) {
            System.err.println("Warning: Input file does not contain entire raw CD sectors.");
            System.err.println("         Audio cannot be decoded.");
        }
        
        // index the STR file
        MediaHandler oHandler;
        boolean blnSaveIndexFile = false;
        try {
            String sIndexFile = m_oMainSettings.getIndexFile();
            if (sIndexFile  != null) {
                if (new File(m_oMainSettings.getIndexFile()).exists()) {
                    if (DebugVerbose > 1)
                        System.err.println("Reading file index");
                    oHandler = new MediaHandler(oCD, sIndexFile);
                } else {
                    if (DebugVerbose > 1)
                        System.err.println("Indexing file");
        
                    oHandler = new MediaHandler(oCD);
                    blnSaveIndexFile = true;
                }
            } else {
                if (DebugVerbose > 1)
                    System.err.println("Indexing file");
        
                oHandler = new MediaHandler(oCD);
            }
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }

        // save index file if necessary
        if (blnSaveIndexFile) {
            try {
                PrintStream oPrinter;
                if (m_oMainSettings.getIndexFile().equals("-"))
                    oPrinter = System.out;
                else
                    oPrinter = new PrintStream(m_oMainSettings.getIndexFile());
                oHandler.SerializeMediaList(oPrinter);
            } catch (IOException ex) {
                if (DebugVerbose > 2)
                    ex.printStackTrace();
                else
                    System.err.println(ex.getMessage());
                return -1;
            }
        }
        
        // print the index for confirmation
        if (DebugVerbose > 0) {
            for (PSXMedia oMedia : oHandler) {
                System.err.println(oMedia.toString());
            }
        }

        // decode the desired media item(s)
        try {
            
            if (m_oMainSettings.getDecodeIndex() == CommandLine.DECODE_ALL) {
                
                for (PSXMedia oMedia : oHandler) {
                    System.err.println(oMedia.toString());
                    DecodeMediaItem(oMedia);
                } // for
            
            } else {

                int iIndex = m_oMainSettings.getDecodeIndex();
                if (oHandler.hasIndex(iIndex)) {
                    PSXMedia oMedia = oHandler.getByIndex(iIndex);
                    System.err.println(oMedia.toString());
                    DecodeMediaItem(oMedia);
                } else {
                    System.err.println("Sorry, couldn't find media item " 
                            + iIndex);
                }

            }
        
            if (DebugVerbose > 1)
                System.err.println("Media decoding complete.");
        
        } catch (IOException ex) {
            ex.printStackTrace();
        }
            
        return 0;
    }
    
    
/**<pre>
 *                 video             xa        tim
 *              +---------------|----------|--------|
 *              | +a+v: avi     |          |        |
 *          avi | -a+v: avi     |          |        |
 *              | +a-v: wav     | +a: wav  |        |
 *              |---------------| -a: n/a  |        |
 * img sequence | +a+v: img+wav |          |        |
 *         mdec | -a+v: img     |          | image  |
 *        demux | +a-v: wav     |          |        |
 *              |--------------------------|        |
 *              | +a+v: raw                |        |
 *         raw  | -a+v: raw                |        |
 *    (str, xa) | +a-v: raw                |        |
 *              +-----------------------------------|
 * 
 * if input is tim (not streaming)
 *  ... output image
 * else if (streaming & ) output is raw
 *  ... output raw
 * else if input is xa
 *  ... if decode aud, output wav else do nothing
 * else (if input is video)
 *  ... if decode vid && has vid
 *  ...  ... if avi
 *  ...  ... else (image sequence)
 *  ... else if decode audio
 *  ...  ... 
 *  ... else do nothing
 *</pre>*/
    private static void DecodeMediaItem(PSXMedia oMedia) throws IOException {

        if (oMedia instanceof PSXMediaStreaming) {
            DecodeStreaming((PSXMediaStreaming)oMedia);
        } else if (oMedia instanceof PSXMediaTIM) {
            DecodeTIMMedia((PSXMediaTIM)oMedia);
        }
        
    }
    
    private static void DecodeStreaming(PSXMediaStreaming oMedia) throws IOException {
        
        oMedia.Reset();
        
        IProgressListener oListener = new IProgressListener.IProgressEventErrorListener() {
            public void ProgressUpdate(Exception e) {
                e.printStackTrace(System.err);
            }
            public boolean ProgressUpdate(String sWhatDoing, double dblPercentComplete) {
                System.err.println(sWhatDoing);
                return false;
            }
            public boolean ProgressUpdate(String sEvent) {
                System.err.println(sEvent);
                return false;
            }
        };

        SavingOptions oOptions = new SavingOptions(oMedia);
        oOptions.setDecodeVideo(m_oMainSettings.decodeVideo());
        oOptions.setDecodeAudio(m_oMainSettings.decodeAudio());
        
        if (m_oMainSettings.gotOutputFile()) {
            oOptions.setVideoFilenameBase(m_oMainSettings.getOutputFile());
            oOptions.setAudioFilenameBase(m_oMainSettings.getOutputFile());
        }
        
        if (m_oMainSettings.gotOutputFolder()) 
            oOptions.setFolder(new File(m_oMainSettings.getOutputFolder()));
        
        if (m_oMainSettings.gotVidFormat())
            oOptions.setVideoFormat(m_oMainSettings.getVidFormat());
        
        if (m_oMainSettings.gotAudFormat())
            oOptions.setAudioFormat(m_oMainSettings.getAudFormat());
        
        if (m_oMainSettings.gotFrames()) {
            oOptions.setStartFrame(m_oMainSettings.getStartFrame());
            oOptions.setEndFrame(m_oMainSettings.getEndFrame());
        }
        
        if (m_oMainSettings.gotDecoder())
            oOptions.setDecodeQuality(m_oMainSettings.getDecoder());
        
        if (m_oMainSettings.gotFps())
            oOptions.setFps(m_oMainSettings.getFps());
        
        if (m_oMainSettings.gotJpgQuality())
            oOptions.setJpegQuality(m_oMainSettings.getJpgQuality() / 100.0f);

        oOptions.setDoNotCrop(m_oMainSettings.noCrop());
        
        SaverFactory.DecodeStreaming(oOptions, oListener);
        
    }
    
    private static void DecodeTIMMedia(PSXMediaTIM oMedia) throws IOException {
        String sBaseName;
        
        if (m_oMainSettings.gotOutputFile())
            sBaseName = String.format("%s[%d]",
                    m_oMainSettings.getOutputFile(), oMedia.getIndex());
        else
            sBaseName = oMedia.getSuggestedName();
        
        if (m_oMainSettings.gotOutputFolder())
            sBaseName = new File(m_oMainSettings.getOutputFolder(), sBaseName).toString();
        
        Tim oTim = oMedia.getTIM();
        // make sure output images format is ok
        Formats.ImgSeqVidFormat oFmt;
        if (m_oMainSettings.gotTimFormat())
            oFmt = m_oMainSettings.getTimFormat();
        else if (m_oMainSettings.getVidFormat() instanceof Formats.ImgSeqVidFormat) {
            oFmt = (ImgSeqVidFormat) m_oMainSettings.getVidFormat();
        } else {
            oFmt = Formats.PNG_IMG_SEQ;
        }
        
        for (int i = 0; i < oTim.getPaletteCount(); i++) {
            BufferedImage bi = oTim.toBufferedImage(i);
            ImageIO.write(bi, oFmt.getId(), 
                    new File(String.format(
                    "%s_p%02d.%s",
                    sBaseName, i, oFmt.getExt())));
        }
    }
    
    //--------------------------------------------------------------------------

    private static int DecodeSpecialFrameFile() {
        
        Formats.Format oOutFormat;
        
        /*
         * Valid output formats:
         *  <java image formats>
         *  if demux, then mdec is ok
         *  yuv
         * 
         */
        
        if (m_oMainSettings.gotVidFormat()) {
            oOutFormat = m_oMainSettings.getVidFormat();
            
            if (oOutFormat == Formats.DEMUX) { // demux not allowed
                oOutFormat = Formats.PNG_IMG_SEQ;
            } else if (oOutFormat.equals("mdec")) { // mdec only if input is demux
                if (m_oMainSettings.getSpecialInType().equals("mdec")) 
                    oOutFormat = Formats.PNG_IMG_SEQ;
            } else if (!Formats.getAllJavaImgFormats().contains(oOutFormat)) {
                // otherwise it needs to be one of the valid output formats
                oOutFormat = Formats.PNG_IMG_SEQ;
            }
            
        } else {
            oOutFormat = Formats.PNG_IMG_SEQ;
        }
            
        String sOutFile = m_oMainSettings.constructOutPath(m_oMainSettings.getInputFileBase());
            
        try {
            
            if (DebugVerbose > 0)
                System.err.println("Reading frame file");
            
            final FileInputStream is;
            is = new FileInputStream(m_oMainSettings.getInputFile());
            
            InputStream iis = new IO.InputStreamWithFP(is);
            
            DecodeSpecialFile(
                    sOutFile + "." + oOutFormat.getExt(),
                    m_oMainSettings.getSpecialInType(),
                    oOutFormat.getId(),
                    iis, 
                    m_oMainSettings.getWidth(), 
                    m_oMainSettings.getHeight());
            
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
        
        return 0;
    }

    //--------------------------------------------------------------------------
   
    private static int SectorList() {
        CDSectorReader oCD;
        try {
            oCD = CDSectorReader.Open(m_oMainSettings.getInputFile());
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
        
        if (!oCD.HasSectorHeader() && DebugVerbose > 0) {
            System.err.println("Warning: Input file does not contain entire raw CD sectors.");
            System.err.println("         Audio cannot be decoded.");
        }
        
        if (DebugVerbose > 1)
            System.err.println("Generating sector list");
        
        PrintStream ps;
        try {
            if (m_oMainSettings.getSectorDumpFile().equals("-"))
                ps = System.out;
            else
                ps = new PrintStream(m_oMainSettings.getSectorDumpFile());
            
            PSXSectorRangeIterator oIter = new PSXSectorRangeIterator(oCD);
            while (oIter.hasNext()) {
                PSXSector oSect = oIter.next();
                if (oSect != null) {
                    String s = oSect.toString();
                    if (s != null) ps.println(s);
                } else {
                    ps.println("Error with sector " + (oIter.getIndex() - 1));
                }
            }
            
            ps.flush();
            if (!ps.equals(System.out)) ps.close();
            return 0;
            
        } catch (IOException ex) {
            if (DebugVerbose > 2)
                ex.printStackTrace();
            else if (DebugVerbose > 0)
                System.err.println(ex.getMessage());
            return -1;
        }
    }

    private static void DecodeSpecialFile(
            String sFrameFile,
            String sInputFormat, 
            String sOutputFormat, 
            InputStream str, 
            long lngWidth,
            long lngHeight) 
            throws IOException
    {
        
        if (str instanceof IWidthHeight) {
            lngWidth = ((IWidthHeight)str).getWidth();
            lngHeight = ((IWidthHeight)str).getHeight();
        }
        
        if (sInputFormat.equals("demux")) {

            if (sOutputFormat.equals("demux")) {
                FileOutputStream fos = new FileOutputStream(sFrameFile);
                int ib;
                while ((ib = str.read()) >= 0)
                    fos.write(ib);
                fos.close();
                return;
            }

            
            try {
                str = new StrFrameUncompressor(str, lngWidth, lngHeight).getStream();
            } catch (CriticalUncompressException ex) {
                ex.printStackTrace(System.err);
                return;
            }
            if (sOutputFormat.equals("mdec")) {
                FileOutputStream fos = new FileOutputStream(sFrameFile);
                int ib;
                while ((ib = str.read()) >= 0)
                    fos.write(ib);
                fos.close();
                return;
            }

        }
        
        PsxYuv oYuv;
        oYuv = MDEC.getQualityMdec().DecodeFrame(str, lngWidth, lngHeight);
        if (sOutputFormat.equals("yuv") || sOutputFormat.equals("y4m")) {
            FileOutputStream fos = new FileOutputStream(sFrameFile);
            oYuv.Write(fos, new Fraction(15, 1));
            fos.close();
            return;
        }

        BufferedImage bi = oYuv.toBufferedImage();
        ImageIO.write(bi, sOutputFormat, new File(sFrameFile));
    }
        
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.