172 lines
4.9 KiB
C++
172 lines
4.9 KiB
C++
/******************************************************************************
|
|
* Copyright (c) 2018(-2023) STMicroelectronics.
|
|
* All rights reserved.
|
|
*
|
|
* This file is part of the TouchGFX 4.21.2 distribution.
|
|
*
|
|
* This software is licensed under terms that can be found in the LICENSE file in
|
|
* the root directory of this software component.
|
|
* If no LICENSE file comes with this software, it is provided AS-IS.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <touchgfx/Application.hpp>
|
|
#include <touchgfx/Utils.hpp>
|
|
#include <touchgfx/hal/HAL.hpp>
|
|
#include <touchgfx/widgets/VideoWidget.hpp>
|
|
|
|
namespace touchgfx
|
|
{
|
|
VideoWidget::VideoWidget()
|
|
: Widget(),
|
|
movieEndedAction(0), buffer(0), format(Bitmap::RGB888),
|
|
bufferWidth(0), bufferHeight(0), videoWidth(0), videoHeight(0)
|
|
{
|
|
handle = VideoController::getInstance().registerVideoWidget(*this);
|
|
Application::getInstance()->registerTimerWidget(this);
|
|
}
|
|
|
|
VideoWidget::~VideoWidget()
|
|
{
|
|
VideoController::getInstance().unregisterVideoWidget(handle);
|
|
Application::getInstance()->unregisterTimerWidget(this);
|
|
}
|
|
|
|
void VideoWidget::play() const
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::PLAY, 0);
|
|
}
|
|
|
|
void VideoWidget::pause() const
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::PAUSE, 0);
|
|
}
|
|
|
|
void VideoWidget::stop() const
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::STOP, 0);
|
|
}
|
|
|
|
bool VideoWidget::isPlaying() const
|
|
{
|
|
return VideoController::getInstance().getIsPlaying(handle);
|
|
}
|
|
|
|
void VideoWidget::seek(uint32_t frameNumber) const
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::SEEK, frameNumber);
|
|
}
|
|
|
|
void VideoWidget::showFrame(uint32_t frameNumber) const
|
|
{
|
|
if (isPlaying())
|
|
{
|
|
seek(frameNumber);
|
|
}
|
|
else
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::SHOW, frameNumber);
|
|
}
|
|
}
|
|
|
|
void VideoWidget::setRepeat(bool repeat) const
|
|
{
|
|
VideoController::getInstance().setCommand(handle, VideoController::SET_REPEAT, repeat ? 1 : 0);
|
|
}
|
|
|
|
void VideoWidget::handleTickEvent()
|
|
{
|
|
const bool hasMoreFrames = VideoController::getInstance().updateFrame(handle, *this);
|
|
if (!hasMoreFrames)
|
|
{
|
|
// Now showing last frame
|
|
if (movieEndedAction && movieEndedAction->isValid())
|
|
{
|
|
movieEndedAction->execute(*this);
|
|
}
|
|
}
|
|
}
|
|
|
|
Rect VideoWidget::getSolidRect() const
|
|
{
|
|
// For Dedicated or DoubleBuffered video we have a bufferWidth > 0
|
|
// But maybe no buffer yet (only after decoding first frame)
|
|
if (bufferWidth > 0)
|
|
{
|
|
// Solid inside video area if we have a buffer, otherwise transparent
|
|
if (buffer != 0)
|
|
{
|
|
return Rect(0, 0, MIN(videoWidth, bufferWidth), MIN(videoHeight, bufferHeight));
|
|
}
|
|
return Rect();
|
|
}
|
|
|
|
//Direct to framebuffer, solid inside the video area
|
|
return Rect(0, 0, videoWidth, videoHeight);
|
|
}
|
|
|
|
void VideoWidget::draw(const Rect& invalidatedArea) const
|
|
{
|
|
// Only draw the invalidated area inside the video x buffer
|
|
Rect invVideoRect(0, 0, videoWidth, videoHeight);
|
|
invVideoRect &= invalidatedArea;
|
|
|
|
// Inform controller that we are drawing
|
|
VideoController::getInstance().draw(handle, invVideoRect, *this);
|
|
|
|
// If we have a buffer, draw that
|
|
if (buffer != 0)
|
|
{
|
|
// Limit to buffer size
|
|
invVideoRect &= Rect(0, 0, bufferWidth, bufferHeight);
|
|
|
|
// Convert to lcd coordinates. Width is buffer stride.
|
|
Rect absolute = getAbsoluteRect();
|
|
absolute.width = bufferWidth;
|
|
// Copy to LCD, always solid
|
|
HAL::lcd().blitCopy(buffer, format, absolute, invVideoRect, 255, false);
|
|
}
|
|
}
|
|
|
|
uint32_t VideoWidget::getCurrentFrameNumber() const
|
|
{
|
|
return VideoController::getInstance().getCurrentFrameNumber(handle);
|
|
}
|
|
|
|
void VideoWidget::setFrameRate(uint32_t ui_frames, uint32_t video_frames) const
|
|
{
|
|
VideoController::getInstance().setFrameRate(handle, ui_frames, video_frames);
|
|
}
|
|
|
|
void VideoWidget::setVideoData(const uint8_t* movie, const uint32_t length)
|
|
{
|
|
VideoController::getInstance().setVideoData(handle, movie, length);
|
|
|
|
readVideoInformation();
|
|
}
|
|
|
|
void VideoWidget::setVideoData(VideoDataReader& reader)
|
|
{
|
|
VideoController::getInstance().setVideoData(handle, reader);
|
|
|
|
readVideoInformation();
|
|
}
|
|
|
|
void VideoWidget::getVideoInformation(VideoInformation* data) const
|
|
{
|
|
VideoController::getInstance().getVideoInformation(handle, data);
|
|
}
|
|
|
|
void VideoWidget::readVideoInformation()
|
|
{
|
|
// Set frame rate to movie speed (assuming 60 ui frames in a second)
|
|
VideoInformation videoInformation;
|
|
VideoController::getInstance().getVideoInformation(handle, &videoInformation);
|
|
videoWidth = (int16_t)videoInformation.frame_width;
|
|
videoHeight = (int16_t)videoInformation.frame_height;
|
|
uint32_t videoFramesIn1000ms = 1000 / videoInformation.ms_between_frames;
|
|
setFrameRate(60, videoFramesIn1000ms);
|
|
}
|
|
|
|
} // namespace touchgfx
|