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)
|
if (avcodec_return != 0)
|
||||||
{
|
{
|
||||||
LOG->Warn(
|
LOG->Trace(
|
||||||
"Frame %i saw nonzero avcodec_receive_frame status: %i",
|
"Frame %i saw nonzero avcodec_receive_frame status: %i, this is likely not fatal.",
|
||||||
static_cast<int>(packet_buffer_.size() - 1),
|
static_cast<int>(packet_buffer_.size() - 1),
|
||||||
avcodec_return);
|
avcodec_return);
|
||||||
|
|
||||||
@@ -446,41 +446,35 @@ int MovieDecoder_FFMpeg::GetFrame(RageSurface* surface_out)
|
|||||||
if (av_sws_context_ == nullptr)
|
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_);
|
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::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);
|
std::lock_guard<std::mutex> lock(frame_buffer_[display_frame_in_buffer]->lock);
|
||||||
|
int scale_status = 0;
|
||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
if (frame_buffer_[display_frame_in_buffer]->packet_num == display_frame_num_) {
|
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(),
|
frame_buffer_[display_frame_in_buffer]->frame->data, frame_buffer_[display_frame_in_buffer]->frame->linesize, 0, GetHeight(),
|
||||||
pict.data, pict.linesize);
|
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 {
|
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);
|
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;
|
frame_buffer_[display_frame_in_buffer]->displayed = true;
|
||||||
|
|
||||||
// Set the end of movie flag if this is the final frame.
|
|
||||||
if (LastFrame()) {
|
if (LastFrame()) {
|
||||||
end_of_movie_ = true;
|
end_of_movie_ = true;
|
||||||
return 0;
|
return scale_status;
|
||||||
}
|
}
|
||||||
end_of_movie_ = false;
|
end_of_movie_ = false;
|
||||||
display_frame_num_++;
|
display_frame_num_++;
|
||||||
return 0;
|
return scale_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RString averr_ssprintf(int err, const char* fmt, ...)
|
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 MovieTexture_Generic::Init()
|
||||||
{
|
{
|
||||||
RString sError = decoder_->Open(GetID().filename);
|
RString err = decoder_->Open(GetID().filename);
|
||||||
if (sError != "")
|
if (err != "") {
|
||||||
return sError;
|
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();
|
CreateTexture();
|
||||||
CreateFrameRects();
|
CreateFrameRects();
|
||||||
@@ -80,10 +82,10 @@ MovieTexture_Generic::~MovieTexture_Generic()
|
|||||||
|
|
||||||
/* sprite_ may reference the texture; delete it before DestroyTexture. */
|
/* sprite_ may reference the texture; delete it before DestroyTexture. */
|
||||||
delete sprite_;
|
delete sprite_;
|
||||||
|
delete decoder_;
|
||||||
|
|
||||||
DestroyTexture();
|
DestroyTexture();
|
||||||
|
|
||||||
delete decoder_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete the surface and texture. The decoding thread must be stopped, and this
|
/* Delete the surface and texture. The decoding thread must be stopped, and this
|
||||||
|
|||||||
Reference in New Issue
Block a user