Rewrite flushing logic
The old flushing logic would simply leave frame threads (and tile threads) running without caring how much latency that might impose in the post-seek time-to-first-frame. This commit adds a 'flush' state that will abort all running frame/tile threads from decoding their current frame, as well as dispose of all frames in the output queue.
Then, we use dav1d_flush() in dav1d_close() to abort running threads on exit, instead of signaling their respective dependents to prevent deadlocks. The advantage of this approach is that we don't signal on objects we don't have ownership over, and thus this should prevent race conditions where the owning thread could dispose of the object just as we're signaling it, which I believe is what causes #193 (closed).
As evidence that this fixes #193 (closed):
Before:
$ for i in `seq 0 1000`; do tests/dav1d_fuzzer_mt /Users/ronaldbultje/Downloads/clusterfuzz-testcase-minimized-dav1d_fuzzer_mt-5700248035393536; done
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
Segmentation fault: 11
$
After:
$ for i in `seq 0 1000`; do tests/dav1d_fuzzer_mt /Users/ronaldbultje/Downloads/clusterfuzz-testcase-minimized-dav1d_fuzzer_mt-5700248035393536; done
$