MP3 Dekódování na Android

hlasů
29

Jsme provádění programu pro telefony se systémem Android, který přehrává audio streamované z internetu. Tady je přibližně to, co děláme:

  1. Stáhnout vlastní zašifrované podobě.
  2. Dešifrovat získat kousky pravidelných MP3 dat.
  3. Dekódování MP3 dat na nezpracovaných dat PCM do vyrovnávací paměti.
  4. Potrubí surového PCM dat na AudioTrack se

Naše cílové zařízení jsou doposud Droid a Nexus One. Všechno funguje skvěle na Nexus One, ale MP3 dekódování je příliš pomalý na Droid. Zvukový záznam začne vynechat když dáme Droid pod zatížením. Není nám dovoleno pro dekódování dat ve formátu MP3 na SD kartu, ale vím, že to není náš problém tak jako tak.

Nechtěli jsme psát naše vlastní MP3 dekodéru, ale používá MPADEC ( http://sourceforge.net/projects/mpadec/ ). Je to zdarma a bylo snadné integrovat s naším programem. My zkompilovat s NDK.

Po důkladném rozboru s různými nástroji profilování, jsme přesvědčeni, že je to dekodér, který zaostává.

Tady jsou možnosti Přemýšlíme o:

  1. Najít jiný MP3 dekodér, který můžeme sestavit s Android NDK. To MP3 dekodér by musel být buď optimalizovány pro běh na mobilních zařízeních ARM nebo možná použít integer pouze matematiku nebo některé další optimalizace ke zvýšení výkonu.

  2. Vzhledem k tomu, vestavěný Android MediaPlayer služba bude mít URL, mohli bychom být schopni realizovat malý HTTP server v našem programu a slouží MediaPlayer s Dešifrovaný MP3. Tímto způsobem můžeme využít vestavěného MP3 dekodéru.

  3. Získat přístup k vestavěným MP3 dekodéru přes NDK. Já nevím, jestli je to možné.

Má někdo nějaké návrhy na to, co můžeme udělat pro urychlení našeho dekódování MP3?

- Rob Sz

Položena 22/03/2010 v 18:48
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
2

Správný způsob, jak to udělat, je vytvořit si vlastní firmware a proveďte dešifrování jako součást vlastního OpenCORE kodeku. To samozřejmě, vás omezovat na zařízení, kde můžete nainstalovat tento firmware.

Mějte na paměti, že zbytek to je poněkud spekulativní. Vlastně jsem potřebu udělat něco podobného, ​​co jste popisoval, ale nemám čas zrušil řešit problém za pár měsíců. Takže budu popisovat to v módě, jak bych přistupovat k problému.

Jedním z možných řešení je ten popsaný v odpovědi TWK je. Nemusíte použít SD kartu, ale pravděpodobně mít světovou čitelné dočasný soubor ve své aplikaci lokální úložiště souborů ( getFilesDir()). Stáhněte si první blok, dešifrovat, zapište ho jako kompletní podobě v souboru MP3 (ale s vhodně obskurní adresáři / cesta), a předat ji do A MediaPlayerpomocí setDataSource(). I když to hraje stáhnete / dešifrování a zřídit druhou MediaPlayerinstanci, která spustí přehrávání, jakmile první, kdo skončí, tak bezproblémový přechod jak je to možné. Potom obnovit první MediaPlayera znovu ji s vaší třetí blok, ping-ponging mezi těmito dvěma.

S tím souvisí i řešení by bylo v komentáři jleedev je. Je to skoro totéž, kromě toho, že poskytují FileDescriptorPROSTŘEDNICTVÍM ContentProvider. To má možnost nechat použít zásuvku, která může vám umožní vyhnout se dočasný soubor. Nicméně, ContentProviderbude muset být sám o sobě veřejně přístupné, a proto dočasný soubor s obskurní adresář, ve skutečnosti může být více soukromí.

Pokud se obáváte o tom, že tyto věci mohou být čteny jiným způsobem, prosím, na vědomí, že MediaPlayersám o sobě (nebo spíše se OpenCORE subsystému) je v jiném procesu. Také váš navrhovaný HTTP server je čitelný na zařízení stejně. Takže, bezpečnost tím, zapomnění je jedinou schůdnou cestou, pokud se chystáte nechat MediaPlayerprovést dekódování.

Pokud vím je NDK neposkytuje přístup k OpenCORE, i když musím přiznat, jak se mají omezenou NDK zkušenost, takže mohu mýlit. Existují jistě jiné MP3 dekodérů k dispozici ( ffmpeg/ mplayer, atd.), I když, jak snadno by mohly být převedeny do knihovny NDK je nejasný.

Takže je to opravdu scvrkává na který se snažíte bránit. Pokud se snažíte bránit proti uživatele, budete pravděpodobně bude mít dekódovat sami, tak nějak.

Odpovězeno 25/03/2010 v 16:19
zdroj uživatelem

hlasů
1

MAD je celé číslo, aritmetický pouze dekodér knihovna, která se zdá být dobře považovat.

(Nebude dekódování dat na SD kartu zpomalit vlastně je?)

Odpovězeno 26/03/2010 v 00:26
zdroj uživatelem

hlasů
0

Na decrypte zašifrovaný soubor mp3 to předtím hrát. Existují 3 způsoby:

1, pro použití MediaPlayer API:

Po Android verze M:

you can play mp3 data in byte array directly by:

//Read encrypted mp3:
byte[] bytesAudioData =  Utils.readFile(path); // or from a url.

final byte[] bytesAudioDataDecrypted = YourUtils.decryptFileToteArray(bytesAudioData);

                ByteArrayMediaDataSource bds = new ByteArrayMediaDataSource(bytesAudioDataDecrypted) ;
                mediaPlayer.setDataSource(bds);

Před Android verze M:

//Read encrypted mp3:
byte[] bytesAudioData =  Utils.readFile(path); // or from a url.

final byte[] bytesAudioDataDecrypted = YourUtils.decryptFileToteArray(bytesAudioData);

 File file =new File(dirofyouraudio.mp3");

                FileOutputStream fos = new FileOutputStream(file);
                fos.write(bytesAudioDataDecrypted);
                Log.d(TAG, "playSound :: file write to temp :: System. nanoTime() ="+System. nanoTime());
                fos.close();

                FileInputStream fis = new FileInputStream(file);
                mediaPlayer.setDataSource(fis.getFD());

2. Za AudioTrack API, pokud používáte:

  int minBufferSize = AudioTrack.getMinBufferSize(sampleRate,
            AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT);

   AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
            AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, minBufferSize,
            AudioTrack.MODE_STREAM);

    int i = 0;
    byte[] tempMinBufferToRead = new byte[minBufferSize];

    try {

        byte[] bytesAudioData = Utils.readFile( lastRecordedAudiofilePath);

        bytesAudioData = yourUtils.decryptYourFileToByteArray(bytesAudioData);

        try {
            fileInputStremForPlay = new FileInputStream( lastRecordedAudiofilePath);

            dataInputStreamForPlay = new DataInputStream(new ByteArrayInputStream(bytesAudioData));

            track.play();
            while ((i = dataInputStreamForPlay.read(tempMinBufferToRead, 0, minBufferSize)) > -1) {
                Log.d(LOG_TAG, "mThreadExitFlag= " + mThreadExitFlag);

                if ((mThreadExitFlag == true) || (!audioFilePathInThisThread.equals(lastRecordedAudiofilePath))) {

                    m_handler.post(new Runnable() {
                        public void run() {
                            Log.d(LOG_TAG, "startPlaying: break and reset play button ");

                            startPlayBtnInToolbar.setEnabled(true);
                            stopPlayBtnInToolbar.setEnabled(false);
                        }
                    });

                    break;
                }

                track.write(tempMinBufferToRead, 0, i);
            }

            Log.d(LOG_TAG, "===== Playing Audio Completed ===== ");
            track.stop();

            track.release();

            dataInputStreamForPlay.close();

            fileInputStremForPlay.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

3. Pomocí MediaExtractor, MediaCodec s AudioTrack, můžete nastavit zdroj dat s odsávání:

            extractor.setDataSource(this.url);

Nebo

            extractor.setDataSource(this.Mediadatasource);

ps: Třída ByteArrayMediaDataSource:

import android.annotation.TargetApi;
import android.media.MediaDataSource;
import android.os.Build;
import java.io.IOException;



import android.content.res.AssetFileDescriptor;
 import android.media.MediaDataSource;
import android.util.Log;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

@TargetApi(Build.VERSION_CODES.M)
public class ByteArrayMediaDataSource extends MediaDataSource {

    private static final String TAG = ByteArrayMediaDataSource.class.getSimpleName();


    private   byte[] data;

    public ByteArrayMediaDataSource(byte []data) {
//        assert data != null;
        this.data = data;
    }
    @Override
    public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {


        if (position >= data.length) {
            return -1; // -1 indicates EOF
        }
        if (position + size > data.length) {
            size -= (position + size) - data.length;
        }

        Log.d(TAG, "MediaDataSource size = "+size);


        System.arraycopy(data, (int)position, buffer, offset, size);
        return size;

    }



    @Override
    public long getSize() throws IOException {

        Log.d(TAG, "MediaDataSource data.length = "+data.length);

        return data.length;
    }

    @Override
    public void close() throws IOException {
        // Nothing to do here
        data =null;
    }
}
Odpovězeno 23/10/2017 v 15:55
zdroj uživatelem

hlasů
0

Nezkoušel jsem to, ale věřím, že si můžete dát mediálním přehrávačem popisovač souboru:

public void setDataSource (FileDescriptor fd, long offset, long length)

Možná bys mohl napsat dešifrované mp3 do souboru a přehrát jej pomocí popisovač souboru. To by mohlo fungovat i pro streamování za předpokladu, že víte, délku souboru dopředu. Pokud to funguje, bylo by to mnohem jednodušší, než dělat localhost webserver.

Odpovězeno 23/03/2010 v 18:42
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more