Fix looping logic when the final frame can't display.
Additionally, adjust the destruction order of the movie texture and improve logging.
This commit is contained in:
@@ -388,8 +388,8 @@ int MovieDecoder_FFMpeg::DecodePacketToFrame() {
|
||||
|
||||
if (avcodec_return != 0)
|
||||
{
|
||||
LOG->Warn(
|
||||
"Frame %i saw nonzero avcodec_receive_frame status: %i",
|
||||
LOG->Trace(
|
||||
"Frame %i saw nonzero avcodec_receive_frame status: %i, this is likely not fatal.",
|
||||
static_cast<int>(packet_buffer_.size() - 1),
|
||||
avcodec_return);
|
||||
|
||||
@@ -446,41 +446,35 @@ int MovieDecoder_FFMpeg::GetFrame(RageSurface* surface_out)
|
||||
if (av_sws_context_ == nullptr)
|
||||
{
|
||||
LOG->Warn("Cannot initialize sws conversion context for (%d,%d) %d->%d", GetWidth(), GetHeight(), av_stream_codec_->pix_fmt, av_pixel_format_);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t display_frame_in_buffer = (display_frame_num_ + offset_) % frame_buffer_.size();
|
||||
std::lock_guard<std::mutex> lock(frame_buffer_[display_frame_in_buffer]->lock);
|
||||
int scale_status = 0;
|
||||
|
||||
// Sanity check.
|
||||
if (frame_buffer_[display_frame_in_buffer]->packet_num == display_frame_num_) {
|
||||
int ret = avcodec::sws_scale(av_sws_context_,
|
||||
scale_status = avcodec::sws_scale(av_sws_context_,
|
||||
frame_buffer_[display_frame_in_buffer]->frame->data, frame_buffer_[display_frame_in_buffer]->frame->linesize, 0, GetHeight(),
|
||||
pict.data, pict.linesize);
|
||||
|
||||
// If the texture couldn't scale, then it means there's an issue with the
|
||||
// frame. Return an error status here.
|
||||
if (ret <= 0) {
|
||||
display_frame_num_++;
|
||||
frame_buffer_[display_frame_in_buffer]->displayed = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG->Warn("Unexpected frame trying to display! display_frame_num_ = %zu, packet_num = %zu", display_frame_num_, frame_buffer_[display_frame_in_buffer]->packet_num);
|
||||
}
|
||||
|
||||
// Even if scale_status returns a failure, we mark displayed as true. The
|
||||
// frame won't be displayed, but instead skipped over.
|
||||
frame_buffer_[display_frame_in_buffer]->displayed = true;
|
||||
|
||||
// Set the end of movie flag if this is the final frame.
|
||||
if (LastFrame()) {
|
||||
end_of_movie_ = true;
|
||||
return 0;
|
||||
return scale_status;
|
||||
}
|
||||
end_of_movie_ = false;
|
||||
display_frame_num_++;
|
||||
return 0;
|
||||
return scale_status;
|
||||
}
|
||||
|
||||
static RString averr_ssprintf(int err, const char* fmt, ...)
|
||||
|
||||
@@ -41,9 +41,11 @@ MovieTexture_Generic::MovieTexture_Generic(RageTextureID ID, MovieDecoder* pDeco
|
||||
|
||||
RString MovieTexture_Generic::Init()
|
||||
{
|
||||
RString sError = decoder_->Open(GetID().filename);
|
||||
if (sError != "")
|
||||
return sError;
|
||||
RString err = decoder_->Open(GetID().filename);
|
||||
if (err != "") {
|
||||
LOG->Warn("MovieTexture_Generic::Init: failed to open decoder for file: %s, with error:\n%s", GetID().filename.c_str(), err.c_str());
|
||||
return err;
|
||||
}
|
||||
|
||||
CreateTexture();
|
||||
CreateFrameRects();
|
||||
@@ -80,10 +82,10 @@ MovieTexture_Generic::~MovieTexture_Generic()
|
||||
|
||||
/* sprite_ may reference the texture; delete it before DestroyTexture. */
|
||||
delete sprite_;
|
||||
delete decoder_;
|
||||
|
||||
DestroyTexture();
|
||||
|
||||
delete decoder_;
|
||||
}
|
||||
|
||||
/* Delete the surface and texture. The decoding thread must be stopped, and this
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
static EffectMode GetEffectMode( MovieDecoderPixelFormatYCbCr fmt );
|
||||
|
||||
private:
|
||||
MovieDecoder *decoder_;
|
||||
MovieDecoder* decoder_;
|
||||
|
||||
std::unique_ptr<std::thread> decoding_thread_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user