AVR Interrupt "Interference"
I see three issues with your code:

Variable volatility and scope

The  variables below will get corrupted due to the fact that you define them only in the ISR. But you clearly want to retain their value between interrupts. Make the following variables volatile and define them globally, not in the ISR: 


uint8_t lastState;
uint32_t startTime[8];


Accurate timing

Run timing critical code as soon a possible after the interrupt occured. Read micros() into a temporary variable at the start of the ISR so the all the conditional code doesn't influence timing. Then assign the temporary variable to startTime[changedPin] once your code decided where to put it.

Simultaneous edges

Notice that your code does not cope with simultaneous pin changes, the highest pin will take precedence. Then when the those pins do not have simultaneous falling edges, the timing for the pin with lowest number will be corrupt.