/* ** AACDecoder - Freeware Advanced Audio (AAC) Decoder for Android ** Copyright (C) 2011 Spolecne s.r.o., http://www.spoledge.com ** ** This file is a part of AACDecoder. ** ** AACDecoder is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.spoledge.aacdecoder; /** * The decoder which calls native implementation(s). */ public class Decoder { /** * Info about the stream. */ public static final class Info { private int sampleRate; private int channels; private int frameMaxBytesConsumed; private int frameSamples; private int roundFrames; private int roundBytesConsumed; private int roundSamples; //////////////////////////////////////////////////////////////////////////// // Public //////////////////////////////////////////////////////////////////////////// /** * Returns the sampling rate in Hz. * @return the sampling rate - always set */ public int getSampleRate() { return sampleRate; } /** * Returns the number of channels (0=unknown yet, 1=mono, 2=stereo). * @return the channels - always set */ public int getChannels() { return channels; } /** * Returns the maximum bytes consumed per ADTS frame. * @return the value - after each decode() round */ public int getFrameMaxBytesConsumed() { return frameMaxBytesConsumed; } /** * Returns the samples produced per ADTS frame. * @return the value - after each decode() round (but should be always the same) */ public int getFrameSamples() { return frameSamples; } /** * Returns the number of ADTS frames decoded. * @return the value - after each decode() round */ public int getRoundFrames() { return roundFrames; } /** * Returns the number of bytes consumed. * @return the value - after each decode() round */ public int getRoundBytesConsumed() { return roundBytesConsumed; } /** * Returns the number of samples decoded. * @return the value - after each decode() round */ public int getRoundSamples() { return roundSamples; } } protected static int STATE_IDLE = 0; protected static int STATE_RUNNING = 1; private static boolean libLoaded = false; //////////////////////////////////////////////////////////////////////////// // Attributes //////////////////////////////////////////////////////////////////////////// /** * The decoder pointer. * This is by default 0 - which means that the OpenCORE aacdec decoder is used. * Otherwise it must be set to a valid C pointer to a AACDDecoder struct. */ protected int decoder; /** * The decoding context pointer. * This is used between calls to C functions to kkep pointer to a C struct. */ protected int aacdw; /** * The state of decoder: idle/running */ protected int state = STATE_IDLE; /** * The information passed between JNI and Java. */ protected Info info; //////////////////////////////////////////////////////////////////////////// // Constructors //////////////////////////////////////////////////////////////////////////// protected Decoder( int decoder ) { this.decoder = decoder; } //////////////////////////////////////////////////////////////////////////// // Public //////////////////////////////////////////////////////////////////////////// /** * Loads the native library. * This method is automatically called when first needed. */ public static synchronized void loadLibrary() { if (!libLoaded) { System.loadLibrary( "aacdecoder" ); libLoaded = true; } } /** * Creates a new default AAC decoder. */ public static Decoder create() { return create( 0 ); } /** * Creates a new decoder by its name. * @return the decoder or null if no such decoder is found */ public static Decoder createByName( String name ) { loadLibrary(); int aacdw = nativeDecoderGetByName( name ); return aacdw != 0 ? create( aacdw ) : null; } /** * Creates a new decoder. * @param decoder the poiter to a C struct AACDDecoder. 0 means that the default OpenCORE aacdec * decoder will be used. */ public static synchronized Decoder create( int decoder ) { loadLibrary(); return new Decoder( decoder ); } /** * Starts decoding stream. */ public Info start( BufferReader reader ) { if (state != STATE_IDLE) throw new IllegalStateException(); info = new Info(); aacdw = nativeStart( decoder, reader, info ); if (aacdw == 0) throw new RuntimeException("Cannot start native decoder"); state = STATE_RUNNING; return info; } /** * Decodes stream. * @return the number of samples produced (totally all channels = the length of the filled array) */ public Info decode( short[] samples, int outLen ) { if (state != STATE_RUNNING) throw new IllegalStateException(); nativeDecode( aacdw, samples, outLen ); return info; } /** * Stops the decoder and releases all resources. */ public void stop() { if (aacdw != 0) { nativeStop( aacdw ); aacdw = 0; } state = STATE_IDLE; } //////////////////////////////////////////////////////////////////////////// // Protected //////////////////////////////////////////////////////////////////////////// @Override protected void finalize() { try { stop(); } catch (Throwable t) { t.printStackTrace(); } } //////////////////////////////////////////////////////////////////////////// // Private //////////////////////////////////////////////////////////////////////////// /** * Actually starts decoding the stream. * Detects the stream type. * @param decoder the pointer to the C struct AACDDecoder or NULL * @return the pointer to the C struct */ protected native int nativeStart( int decoder, BufferReader reader, Info info ); /** * Actually decodes a chunk of data. * Calls back Java method BufferReader.next() when additional input is needed. * @param aacdw the pointer to the C struct */ protected native int nativeDecode( int aacdw, short[] samples, int outLen ); /** * Actually stops decoding - releases all resources. * @param aacdw the pointer to the C struct */ protected native void nativeStop( int aacdw ); /** * Returns the decoder pointer struct or NULL. * @param name the name of the decoder */ protected static native int nativeDecoderGetByName( String name ); }