mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
AvcDecoder: let ffmpeg say when a frame came out damaged
Nothing on this path ever called InitFFmpeg, so ffmpeg's log callback was never installed and everything it had to say about the bitstream went nowhere. Our own return codes only report that a frame arrived, not what it was built from, so a video could fall apart on screen while the log showed two warnings in two thousand frames. Also report decode_error_flags and AV_FRAME_FLAG_CORRUPT per frame, which covers the other half: a frame that decodes "successfully" out of concealment. Coalesced into one line per run of damage, since a missing reference makes every frame damaged until the next keyframe. Not setting AV_EF_EXPLODE, which would make the decoder fail where it currently conceals - that is a behaviour change, and this is meant to be a reporting one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f293b10fb2
commit
8a343bec57
2 files changed
+31
No files matched your search
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Core/HW/AvcDecoder.h"
|
||||
#include "Core/HW/MediaEngine.h"
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
extern "C" {
|
||||
@@ -40,6 +41,11 @@ AvcDecoder::AvcDecoder() {
|
||||
ERROR_LOG(Log::ME, "AvcDecoder: couldn't allocate a codec context");
|
||||
return;
|
||||
}
|
||||
// Route ffmpeg's own diagnostics into our log. It is the only thing that knows a frame came
|
||||
// out of a damaged bitstream - our return codes say a frame arrived, not whether it was built
|
||||
// out of concealment - and without this they go nowhere on this path.
|
||||
InitFFmpeg();
|
||||
|
||||
// The PSP hands us whole access units, so no parser is needed and no truncation is expected.
|
||||
codecCtx_->flags = 0;
|
||||
codecCtx_->flags2 = 0;
|
||||
@@ -155,6 +161,27 @@ bool AvcDecoder::Decode(const u8 *data, int size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// A frame can arrive with everything above returning success and still be built partly out of
|
||||
// concealment - a reference the decoder never got, or a slice it had to guess at. That only
|
||||
// shows up here, and it is the difference between "the video is decoding" and "the video is
|
||||
// decoding what the game actually sent us".
|
||||
if (frame_->decode_error_flags || (frame_->flags & AV_FRAME_FLAG_CORRUPT)) {
|
||||
concealedFrames_++;
|
||||
// One line per run of trouble rather than per frame: once a reference is missing, every
|
||||
// frame until the next keyframe is damaged, and that would be hundreds of lines.
|
||||
if (!wasConcealing_) {
|
||||
WARN_LOG(Log::ME, "AvcDecoder: frame %d decoded from a damaged bitstream (flags %08x%s) - "
|
||||
"the stream is missing data, not the decoder", frameCount_, frame_->decode_error_flags,
|
||||
(frame_->flags & AV_FRAME_FLAG_CORRUPT) ? ", corrupt" : "");
|
||||
wasConcealing_ = true;
|
||||
}
|
||||
} else if (wasConcealing_) {
|
||||
WARN_LOG(Log::ME, "AvcDecoder: clean again at frame %d, %d frames were concealed",
|
||||
frameCount_, concealedFrames_);
|
||||
wasConcealing_ = false;
|
||||
}
|
||||
frameCount_++;
|
||||
|
||||
// Everything downstream indexes the three planes as 8-bit 4:2:0, which is all the PSP's
|
||||
// encoder produced. Anything else would be read as if it were, so say so and drop the frame
|
||||
// rather than converting garbage.
|
||||
|
||||
Reference in new issue
Block a user