Program: 32254
Project: 32254
Buggy source:
/** 
 * Extracts all pending data from the encoder <p> If endOfStream is not set, this returns when there is no more data to drain. If it is set, we send EOS to the encoder, and then iterate until we see EOS on the output. Calling this with endOfStream set should be done once, right before stopping the muxer.
 */
public void drainEncoder(boolean endOfStream){
  final int TIMEOUT_USEC=10000;
  if (mEncoder == null || (mOutputStream == null && mOutputListener == null)) {
    return;
  }
  if (endOfStream) {
    mEncoder.signalEndOfInputStream();
  }
  ByteBuffer[] encoderOutputBuffers=mEncoder.getOutputBuffers();
  while (true) {
    int encoderStatus=mEncoder.dequeueOutputBuffer(mBufferInfo,TIMEOUT_USEC);
    if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
      if (!endOfStream) {
        break;
      }
    }
 else     if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
      encoderOutputBuffers=mEncoder.getOutputBuffers();
    }
 else     if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
      if (mH264CodecSpecificData == null) {
        MediaFormat format=mEncoder.getOutputFormat();
        mH264CodecSpecificData=EncoderUtils.getCodecSpecificData(format);
      }
 else {
        Log.w(TAG,"String_Node_Str");
      }
    }
 else     if (encoderStatus < 0) {
    }
 else {
      if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
        if (mH264CodecSpecificData != null) {
          mBufferInfo.size=0;
        }
 else {
          Log.i(TAG,"String_Node_Str");
        }
      }
      if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0 && mBufferInfo.size != 0 && mH264CodecSpecificData != null) {
        try {
          mOutputStream.write(mH264CodecSpecificData,0,mH264CodecSpecificData.length);
        }
 catch (        Exception e) {
        }
      }
      if (mBufferInfo.size != 0) {
        byte[] dataToWrite=new byte[mBufferInfo.size];
        encoderOutputBuffers[encoderStatus].get(dataToWrite,mBufferInfo.offset,mBufferInfo.size);
        try {
          if (mOutputStream != null) {
            mOutputStream.write(dataToWrite,0,mBufferInfo.size);
          }
 else           if (mOutputListener != null) {
            mOutputListener.sendFrame(dataToWrite,0,dataToWrite.length,mBufferInfo.presentationTimeUs);
          }
        }
 catch (        Exception e) {
        }
      }
      mEncoder.releaseOutputBuffer(encoderStatus,false);
      if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
        break;
      }
    }
  }
}

Fixed version (ground truth):
/** 
 * Extracts all pending data from the encoder <p> If endOfStream is not set, this returns when there is no more data to drain. If it is set, we send EOS to the encoder, and then iterate until we see EOS on the output. Calling this with endOfStream set should be done once, right before stopping the muxer.
 */
public void drainEncoder(boolean endOfStream){
  final int TIMEOUT_USEC=10000;
  if (mEncoder == null || (mOutputStream == null && mOutputListener == null)) {
    return;
  }
  if (endOfStream) {
    mEncoder.signalEndOfInputStream();
  }
  ByteBuffer[] encoderOutputBuffers=mEncoder.getOutputBuffers();
  while (true) {
    int encoderStatus=mEncoder.dequeueOutputBuffer(mBufferInfo,TIMEOUT_USEC);
    if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
      if (!endOfStream) {
        break;
      }
    }
 else     if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
      encoderOutputBuffers=mEncoder.getOutputBuffers();
    }
 else     if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
      if (mH264CodecSpecificData == null) {
        MediaFormat format=mEncoder.getOutputFormat();
        mH264CodecSpecificData=EncoderUtils.getCodecSpecificData(format);
      }
 else {
        Log.w(TAG,"String_Node_Str");
      }
    }
 else     if (encoderStatus < 0) {
    }
 else {
      if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
        if (mH264CodecSpecificData != null) {
          mBufferInfo.size=0;
        }
 else {
          Log.i(TAG,"String_Node_Str");
        }
      }
      if (mBufferInfo.size != 0) {
        ByteBuffer encoderOutputBuffer=encoderOutputBuffers[encoderStatus];
        byte[] dataToWrite=null;
        int dataOffset=0;
        if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0 && mH264CodecSpecificData != null) {
          dataToWrite=new byte[mH264CodecSpecificData.length + mBufferInfo.size];
          System.arraycopy(mH264CodecSpecificData,0,dataToWrite,0,mH264CodecSpecificData.length);
          dataOffset=mH264CodecSpecificData.length;
        }
 else {
          dataToWrite=new byte[mBufferInfo.size];
        }
        try {
          encoderOutputBuffer.position(mBufferInfo.offset);
          encoderOutputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
          encoderOutputBuffer.get(dataToWrite,dataOffset,mBufferInfo.size);
          if (mOutputStream != null) {
            mOutputStream.write(dataToWrite,0,mBufferInfo.size);
          }
 else           if (mOutputListener != null) {
            mOutputListener.sendFrame(dataToWrite,0,dataToWrite.length,mBufferInfo.presentationTimeUs);
          }
        }
 catch (        Exception e) {
        }
      }
      mEncoder.releaseOutputBuffer(encoderStatus,false);
      if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
        break;
      }
    }
  }
}