2013-02-18 15 views
20

Używam klasy kodeków mediów w systemie Android (Jelly Bean) do kodowania formatu PCM do formatu AAC. Plik został zakodowany, ale żaden odtwarzacz muzyki nie jest w stanie odtworzyć tego pliku. Nie mogłem znaleźć żadnego działającego kodu lub odpowiedniej dokumentacji w sieci.Konwersja PCM na AAC za pomocą mediacodec

To jest mój kod:

public void doConvert() 
{ 

    new AsyncTask<Void, Void, Void>() 
    { 

     @Override 
     protected Void doInBackground(Void... params) 
     { 
      try 
      { 
       int codecCount = MediaCodecList.getCodecCount(); 

       for (int i=0; i < codecCount; i++) 
       { 
        MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); 
        Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, info.getName()); 
        for (String type : info.getSupportedTypes()) 
        { 
         Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, type); 
        } 

       } 

       File inputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/Ghajini27_Mono_8Khz.wav"); 
       //File inputFile = new File(sampleFD.get); 
       Log.e("File", String.valueOf(inputFile.length())); 
       FileInputStream fis = new FileInputStream(inputFile); 
       fis.skip(44);//remove wav header 

       File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/out.m4a"); 
       if (outputFile.exists()) outputFile.delete(); 

       FileOutputStream fos = new FileOutputStream(outputFile); 

       //BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(outputFile)); 
       MediaCodec codec = MediaCodec.createEncoderByType("audio/mp4a-latm"); 
       MediaFormat outputFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 22050, 1); 
       outputFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC); 
      // outputFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_CONFIGURATION_MONO); 
       outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, 22050 ); 
       outputFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); 
       //outputFormat.setLong(MediaFormat.KEY_MAX_INPUT_SIZE, inputFile.length()); 
       double durationInMs = (inputFile.length()/16000)*1000; 
       Log.e("duration",String.valueOf((long)durationInMs)); 
       outputFormat.setLong(MediaFormat.KEY_DURATION, (long)durationInMs); 


       codec.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); 
       codec.start(); 

       ByteBuffer[] inputBuffers = codec.getInputBuffers(); 
       ByteBuffer[] outputBuffer = codec.getOutputBuffers(); 

       boolean hasMoreData = true; 
       MediaCodec.BufferInfo outBuffInfo = new BufferInfo(); 
       byte readBuffer[] = new byte[48000]; 
       byte writeBuffer[] = new byte[48000]; 

       do 
       { 
        int nextBuffer = codec.dequeueInputBuffer(5000); 
        Log.e("NextBuffer","nextInputBuffer = "+nextBuffer); 

        if (nextBuffer >= 0) 
        { 



         ByteBuffer inBuf = inputBuffers[nextBuffer]; 
         inBuf.clear(); 
         int bytesRead = fis.read(readBuffer,0, inBuf.capacity()); 

         Log.e("bytesread","Read = "+bytesRead); 

         if (bytesRead < inBuf.capacity()) 
         { 
          hasMoreData = false; 
         } 

         inBuf.put(readBuffer, 0, bytesRead); 

         codec.queueInputBuffer(nextBuffer, 0, bytesRead, 0, hasMoreData?0:MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
        } 


        int outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo, 3000); 
       /* logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex); 
        logger.log(Level.INFO,"outBuffInfo offset = "+outBuffInfo.offset); 
        logger.log(Level.INFO,"outBuffInfo size = "+outBuffInfo.size); 
        logger.log(Level.INFO,"outBuffInfo flags = "+outBuffInfo.flags);*/ 


        //while (outputBufferIndex > -1) 
        //{ 

         outputBuffer[outputBufferIndex].position(outBuffInfo.offset); 
         outputBuffer[outputBufferIndex].get(writeBuffer,0,outBuffInfo.size); 

         fos.write(writeBuffer,0, outBuffInfo.size); 
         // logger.log(Level.INFO,"Writing = "+outBuffInfo.size+" bytes"); 


         outputBuffer[outputBufferIndex].clear(); 

         codec.releaseOutputBuffer(outputBufferIndex, false); 

         if (outBuffInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) 
         { 
          codec.flush(); 
          codec.stop(); 
          codec.release(); 
          break; 
         } 

         //outputBufferIndex = codec.dequeueOutputBuffer(outBuffInfo, 1000); 
         //logger.log(Level.INFO,"nextOutputBuffer = "+outputBufferIndex); 
        //} 

       } while (outBuffInfo.flags != MediaCodec.BUFFER_FLAG_END_OF_STREAM); 

       fis.close(); 
       fos.flush(); 
       fos.close(); 



      } 
      catch (Exception e) 
      { 
       //Logger.getLogger(MainActivity.class.getSimpleName()).log(Level.INFO, "Codec Error",e); 
      } 

      //logger.log(Level.INFO,"Done"); 

      return null; 
     } 

    }.execute(); 
} 
+0

Powinieneś opublikować odpowiednie części swojego kodu. W przeciwnym razie inne osoby będą w stanie ustalić, co robisz źle. – Michael

+0

Zakodowany plik nie ma nagłówka, jest tylko nieprzetworzonym plikiem. – tikson

+0

Czy udało się to zrobić? – Soham

Odpowiedz

9

Musisz wybrać pojemnik do tego. Preferuję adts.

Skopiuj dane ładunku do ara, które są wystarczająco duże dla Twojego kontenera, po prostu dodaj bity. Tak więc po przejrzeniu internet dla mojego rozwiązania Pracowałem jakiś fragment na miejsce

metoda 'fillInADTSHeader'

profile =(configParams[0]>>3)&0x1f; 

    frequency_index = (this.configParams[0]&0x7) <<1 | (this.configParams[1]>>7) &0x1; 

    channel_config = (this.configParams[1]>>3) &0xf; 

    int finallength = encoded_length + 7;  
    ENCodedByteArray[0] = (byte) 0xff; 
    ENCodedByteArray[1] = (byte) 0xf1; 
    ENCodedByteArray[2] = (byte) (((profile - 1) << 6) + (frequency_index << 2) +(channel_config >> 2)); 
    ENCodedByteArray[3] = (byte) (((channel_config & 0x3) << 6) + (finallength >> 11)); 
    ENCodedByteArray[4] = (byte)((finallength & 0x7ff) >> 3); 
    ENCodedByteArray[5] = (byte) (((finallength & 7) << 5) + 0x1f) ; 
    ENCodedByteArray[6] = (byte) 0xfc; 

Korzystanie coś podobnego

  byte chunkADTS[]=new byte[info.size + 7]; 
      fillInADTSHeader(chunkADTS,info.size); 
      outputBuffers[bR].get(chunkADTS,7,info.size); 
      buffer.pushData(chunkADTS); 

powinna odgrywać w SHOUTcast, etc ...

Powiązane problemy