CNA-BUG-144: VideoPlayer::GetTexture lets the decoder's std::runtime_error escape, undocumented, and leaves the player Playing

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

A decode, packet, resample or I/O error mid-stream is thrown by VideoDecoder::NextFrame as std::runtime_error through GetTexture, whose header documents only ObjectDisposedException, and the player stays Playing so the next call tries again.

Identifier
CNA-BUG-144
Category
Bug
Subsystem
Audio & media
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
VideoPlayer::GetTexture() exceptions and the player state after a mid-stream decode failure

Expected behaviour

VideoPlayer.hpp documents GetTexture as throwing ObjectDisposedException only. Play treats a decoder failure transactionally: OpenDecoder catches, closes the decoder, resets the state to Stopped and rethrows. The frame path should either be documented as throwing, with a defined state afterwards, or report the failure through the state.

Actual behaviour at TARGET

GetTexture in VideoPlayer.cpp loops over decoder_->NextFrame and DrainAndFlushAudioBuffer with no try. NextFrame and ProcessAudioPacket in VideoDecoder.cpp throw std::runtime_error for a video decode error, a rejected or failed packet send, a failed flush, a demux I/O error and audio decode or resample failures (a deliberate change so that corruption is no longer mistaken for end of stream). The exception reaches the caller, usually inside Draw. It is not a System::Exception, so a handler written for that type misses it. The player stays Playing with the decoder open, and every later GetTexture re-enters the decoder.

Source locations

Evidence

Checked by reading at 009d40f5; not executed. The decoder-level throw is pinned by VideoDecoderTest.CorruptedMidStreamDataThrowsRatherThanSilentlyEndingCleanly; what the player does with it follows from GetTexture's code.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

VideoDecoderTests.cpp pins the throw at decoder level with corrupt_test_h264.mp4. VideoPlayerTests.cpp has no case that plays a corrupt file through GetTexture.

Regression test

Play corrupt_test_h264.mp4 through a VideoPlayer and call GetTexture until the corruption is reached; require the documented outcome (for example an exception of a documented type followed by Stopped) and no second throw from the next call.

Blast radius

Builds with the FFmpeg backend playing corrupt or truncated-in-the-middle files. Clean files and trailing truncation of Matroska files (reported as end of stream) are unaffected.

Workaround

Catch std::exception around GetTexture and call Stop() on failure.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index