MediaCodec outputBuffer始终是空的

问题描述:

我的outputBuffer在我的onOutputBufferAvailable()回调方法中有问题。每次调用此回调方法时,我使用outputBuffer.hasRemaining方法检查outputBuffer并始终返回falseMediaCodec outputBuffer始终是空的

 codec.setCallback(new MediaCodec.Callback() { 

      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
      @Override 
      public void onInputBufferAvailable(MediaCodec mc, int inputBufferId) { 

       ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId); 
       int rounds = extractor.readSampleData(inputBuffer,0); 

       if(rounds > 0) { 
        long currentT = extractor.getSampleTime(); 
        Log.i("CurrentT", String.valueOf(currentT/(1000*1000))); 
        codec.queueInputBuffer(inputBufferId, 0, rounds, 0, 0); 
        extractor.advance(); 


       } else { 
        // EOS 
        codec.queueInputBuffer(inputBufferId, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); 
        Log.i("EOS","=-1"); 


       } 


      } 

      @Override 
      public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) { 
       Log.i("error", "e"); 
      } 
      @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
      @Override 
      public void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, MediaCodec.BufferInfo info) { 
       ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId); 

       Log.i("has", String.valueOf(outputBuffer.hasRemaining())); 
       if (outputBuffer.hasRemaining()) { 

        b = outputBuffer.get(); 
        Log.i("i", String.valueOf(b)); 
        BAOS.write(b); 
        outputBuffer.clear(); 

       } else { 

        array= BAOS.toByteArray(); 
        codec.stop(); 
        codec.release(); 

       } 
       codec.releaseOutputBuffer(outputBufferId, false); 

      } 


      @Override 
      public void onOutputFormatChanged(MediaCodec mc, MediaFormat format) { 
       // Subsequent data will conform to new format. 
       // Can ignore if using getOutputFormat(outputBufferId) 
       // mOutputFormat = format; // option B 
      } 
     }); 

问题的主要原因是错误的MediaCodec模式;是MediaCodec.createByCodecName(...),应该是codec = MediaCodec.createDecoderByType("audio/mpeg")。在unsuccesfull尝试获取字节使用get()我终于结束了get(byte[] dst)方法。下面的工作代码。

  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 
      @Override 
      public void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, MediaCodec.BufferInfo info) { 
       ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId); 

        byte[] b = new byte[outputBuffer.remaining()]; 
        outputBuffer.get(b); 

        for(i=0;i< b.length;i++) { 
         BAOS.write(b[i]); 
        } 
        outputBuffer.clear(); 

       codec.releaseOutputBuffer(outputBufferId, false); 

       if (info.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM) { 
        array=BAOS.toByteArray(); 
        Log.i("array", String.valueOf(array.length)); 
        FileTools fl = new FileTools(); 
        fl.WriteFile(array); 
        codec.stop(); 
        codec.release(); 
       } 
      } 

位置/上的ByteBuffers限制标志不被MediaCodec更新,你需要检查你必须知道实际的有效载荷数据的位置和长度MediaCodec.BufferInfo对象。

+0

您的意思是'presentationTimeUs()'获取实际位置? – Kristopher

+0

不,我的意思是读取MediaCodec.BufferInfo中的'offset'和'size'字段。然而,'getOutputBuffer()'的文档似乎并没有记录它已经自动设置:“返回的缓冲区的位置和限制被设置为有效的输出数据” – mstorsjo

+0

不知道为什么,但我的信息。偏移量“始终是0.”info.size“是4608. – Kristopher