2013-02-18 19 views
20

Ich verwende eine Media-Codec-Klasse in Android (Jelly Bean), um PCM-Format zu AAC zu kodieren. Die Datei wurde codiert, aber kein Musikplayer kann diese Datei abspielen. Ich konnte keinen funktionierenden Code oder eine korrekte Dokumentation im Internet finden.Umwandlung von PCM in AAC mit Mediacodec

Dies ist mein Code:

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

Sie sollten die relevanten Teile Ihres Codes veröffentlichen. Sonst ist es für andere Leute mehr oder weniger unmöglich herauszufinden, was Sie falsch machen könnten. – Michael

+0

Codierte Datei hat keine Kopfzeile, es ist nur eine rohe Datei – tikson

+0

Konnten Sie diese Arbeit machen? – Soham

Antwort

9

Sie müssen einen Container dafür auswählen. Ich bevorzuge Adts.

Kopieren Sie die Nutzdaten in ein Array, das groß genug für Ihren Container ist, fügen Sie einfach Ihre Bits hinzu. So, nachdem das Internet für meine Lösung Scheuern arbeitete ich einige Schnipsel in Platz

Methode '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; 

mit so etwas wie

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

in Shoutcast spielen, etc ...