Use TouchGFX
This commit is contained in:
29
TouchGFX/generated/simulator/src/mainBase.cpp
Normal file
29
TouchGFX/generated/simulator/src/mainBase.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*********************************************************************************/
|
||||
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
|
||||
/*********************************************************************************/
|
||||
#include <simulator/mainBase.hpp>
|
||||
#include <platform/hal/simulator/sdl2/HALSDL2.hpp>
|
||||
#include <common/TouchGFXInit.hpp>
|
||||
#include <platform/driver/lcd/LCD16bpp.hpp>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define fopen_s(pFile, filename, mode) (((*(pFile)) = fopen((filename), (mode))) == NULL)
|
||||
#endif
|
||||
touchgfx::LCD16bpp lcd;
|
||||
|
||||
void setupSimulator(int argc, char** argv, touchgfx::HAL& hal)
|
||||
{
|
||||
// Simulate hardware running at 60Hz generating a vsync every 16.6667 ms
|
||||
static_cast<touchgfx::HALSDL2&>(hal).setVsyncInterval(16.6667f);
|
||||
static_cast<touchgfx::HALSDL2&>(hal).setWindowTitle("MyApplication");
|
||||
|
||||
// Initialize SDL
|
||||
bool sdl_init_result = static_cast<touchgfx::HALSDL2&>(hal).sdl_init(argc, argv);
|
||||
assert(sdl_init_result && "Error during SDL initialization");
|
||||
}
|
||||
|
||||
touchgfx::LCD& setupLCD()
|
||||
{
|
||||
return lcd;
|
||||
}
|
||||
548
TouchGFX/generated/simulator/src/video/SoftwareMJPEGDecoder.cpp
Normal file
548
TouchGFX/generated/simulator/src/video/SoftwareMJPEGDecoder.cpp
Normal file
@ -0,0 +1,548 @@
|
||||
/*********************************************************************************/
|
||||
/********** THIS FILE IS GENERATED BY TOUCHGFX DESIGNER, DO NOT MODIFY ***********/
|
||||
/*********************************************************************************/
|
||||
#include <jinclude.h>
|
||||
#include <jpeglib.h>
|
||||
#include <string.h>
|
||||
#include <simulator/video/SoftwareMJPEGDecoder.hpp>
|
||||
|
||||
#define VIDEO_DECODE_FORMAT 16
|
||||
|
||||
namespace
|
||||
{
|
||||
struct JPEG_RGB
|
||||
{
|
||||
uint8_t B;
|
||||
uint8_t G;
|
||||
uint8_t R;
|
||||
#if VIDEO_DECODE_FORMAT == 32
|
||||
uint8_t X;
|
||||
#endif
|
||||
};
|
||||
} // namespace
|
||||
|
||||
SoftwareMJPEGDecoder::SoftwareMJPEGDecoder(uint8_t* buffer)
|
||||
: frameNumber(0), currentMovieOffset(0), indexOffset(0), firstFrameOffset(0), lastFrameEnd(0), movieLength(0), movieData(0),
|
||||
reader(0), lineBuffer(buffer), aviBuffer(0), aviBufferLength(0), aviBufferStartOffset(0), lastError(AVI_NO_ERROR)
|
||||
{
|
||||
//clear video info
|
||||
videoInfo.ms_between_frames = 0;
|
||||
videoInfo.number_of_frames = 0;
|
||||
videoInfo.frame_width = 0;
|
||||
videoInfo.frame_height = 0;
|
||||
}
|
||||
|
||||
int SoftwareMJPEGDecoder::compare(const uint32_t offset, const char* str, uint32_t num)
|
||||
{
|
||||
const char* src;
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
src = reinterpret_cast<const char*>(aviBuffer + (offset - aviBufferStartOffset));
|
||||
}
|
||||
else
|
||||
{
|
||||
src = (const char*)movieData + offset;
|
||||
}
|
||||
return strncmp(src, str, num);
|
||||
}
|
||||
|
||||
inline uint32_t SoftwareMJPEGDecoder::getU32(const uint32_t offset)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
const uint32_t index = offset - aviBufferStartOffset;
|
||||
return aviBuffer[index + 0] | (aviBuffer[index + 1] << 8) | (aviBuffer[index + 2] << 16) | (aviBuffer[index + 3] << 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t* const d = movieData + offset;
|
||||
return d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint32_t SoftwareMJPEGDecoder::getU16(const uint32_t offset)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
// Assuming data is in buffer!
|
||||
const uint32_t index = offset - aviBufferStartOffset;
|
||||
return aviBuffer[index + 0] | (aviBuffer[index + 1] << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint8_t* const d = movieData + offset;
|
||||
return d[0] | (d[1] << 8);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* SoftwareMJPEGDecoder::readData(uint32_t offset, uint32_t length)
|
||||
{
|
||||
if (reader != 0)
|
||||
{
|
||||
if (length > aviBufferLength)
|
||||
{
|
||||
lastError = AVI_ERROR_FILE_BUFFER_TO_SMALL;
|
||||
assert(!"Buffer to small");
|
||||
}
|
||||
|
||||
reader->seek(offset);
|
||||
if (!reader->readData(aviBuffer, length))
|
||||
{
|
||||
lastError = AVI_ERROR_EOF_REACHED;
|
||||
}
|
||||
|
||||
aviBufferStartOffset = offset;
|
||||
return aviBuffer;
|
||||
}
|
||||
|
||||
return movieData + offset;
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeNextFrame(uint8_t* buffer, uint16_t buffer_width, uint16_t buffer_height, uint32_t buffer_stride)
|
||||
{
|
||||
assert((frameNumber > 0) && "SoftwareMJPEGDecoder decoding without frame data!");
|
||||
|
||||
//find next frame and decode it
|
||||
readData(currentMovieOffset, 8);
|
||||
uint32_t streamNo = getU16(currentMovieOffset);
|
||||
uint32_t chunkType = getU16(currentMovieOffset + 2);
|
||||
uint32_t chunkSize = getU32(currentMovieOffset + 4);
|
||||
const uint16_t STREAM0 = 0x3030;
|
||||
const uint16_t TYPEDC = 0x6364;
|
||||
|
||||
bool isCurrentFrameLast;
|
||||
//play frame if we have it all
|
||||
if (currentMovieOffset + 8 + chunkSize < movieLength)
|
||||
{
|
||||
if (streamNo == STREAM0 && chunkType == TYPEDC && chunkSize > 0)
|
||||
{
|
||||
currentMovieOffset += 8;
|
||||
//decode frame
|
||||
const uint8_t* chunk = readData(currentMovieOffset, chunkSize);
|
||||
decodeMJPEGFrame(chunk, chunkSize, buffer, buffer_width, buffer_height, buffer_stride);
|
||||
frameNumber++;
|
||||
}
|
||||
|
||||
isCurrentFrameLast = false;
|
||||
|
||||
// Advance to next frame
|
||||
currentMovieOffset += chunkSize;
|
||||
if (chunkSize == 0) // Skip empty frame
|
||||
{
|
||||
currentMovieOffset += 8;
|
||||
}
|
||||
currentMovieOffset = (currentMovieOffset + 1) & 0xFFFFFFFE; //pad to next word
|
||||
|
||||
if (currentMovieOffset == lastFrameEnd)
|
||||
{
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
isCurrentFrameLast = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
isCurrentFrameLast = true;
|
||||
}
|
||||
return !isCurrentFrameLast;
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::gotoNextFrame()
|
||||
{
|
||||
assert((frameNumber > 0) && "SoftwareMJPEGDecoder decoding without frame data!");
|
||||
|
||||
readData(currentMovieOffset, 8);
|
||||
uint32_t chunkSize = getU32(currentMovieOffset + 4);
|
||||
|
||||
//increment until next video frame
|
||||
while (currentMovieOffset + 8 + chunkSize < movieLength)
|
||||
{
|
||||
//increment one frame
|
||||
currentMovieOffset += chunkSize + 8;
|
||||
currentMovieOffset = (currentMovieOffset + 1) & 0xFFFFFFFE; //pad to next word
|
||||
frameNumber++;
|
||||
|
||||
//next chunk
|
||||
readData(currentMovieOffset, 8);
|
||||
//check it is a video frame
|
||||
uint32_t streamNo = getU16(currentMovieOffset);
|
||||
uint32_t chunkType = getU16(currentMovieOffset + 2);
|
||||
chunkSize = getU32(currentMovieOffset + 4);
|
||||
const uint16_t STREAM0 = 0x3030;
|
||||
const uint16_t TYPEDC = 0x6364;
|
||||
|
||||
if (streamNo == STREAM0 && chunkType == TYPEDC && chunkSize > 0)
|
||||
{
|
||||
// Found next frame
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//skip back to first frame
|
||||
frameNumber = 1;
|
||||
currentMovieOffset = firstFrameOffset; //start over
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::setVideoData(const uint8_t* movie, const uint32_t length)
|
||||
{
|
||||
movieData = movie;
|
||||
movieLength = length;
|
||||
reader = 0; //not using reader
|
||||
|
||||
readVideoHeader();
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::setVideoData(touchgfx::VideoDataReader& reader)
|
||||
{
|
||||
this->reader = &reader;
|
||||
movieData = 0;
|
||||
movieLength = reader.getDataLength();
|
||||
|
||||
readVideoHeader();
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::hasVideo()
|
||||
{
|
||||
return (reader != 0) || (movieData != 0);
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::readVideoHeader()
|
||||
{
|
||||
// Start from the start
|
||||
currentMovieOffset = 0;
|
||||
lastError = AVI_NO_ERROR;
|
||||
|
||||
// Make header available in buffer
|
||||
readData(0, 72);
|
||||
|
||||
// Decode the movie header to find first frame
|
||||
// Must be RIFF file
|
||||
if (compare(currentMovieOffset, "RIFF", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_NOT_RIFF;
|
||||
assert(!"RIFF header not found");
|
||||
}
|
||||
|
||||
//skip fourcc and length
|
||||
currentMovieOffset += 8;
|
||||
if (compare(currentMovieOffset, "AVI ", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_HEADER_NOT_FOUND;
|
||||
assert(!"AVI header not found");
|
||||
}
|
||||
|
||||
currentMovieOffset += 4;
|
||||
if (compare(currentMovieOffset, "LIST", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_LIST_NOT_FOUND;
|
||||
assert(!"AVI LIST not found");
|
||||
}
|
||||
|
||||
//save AVI List info
|
||||
const uint32_t aviListSize = getU32(currentMovieOffset + 4);
|
||||
const uint32_t aviListOffset = currentMovieOffset;
|
||||
assert(aviListSize);
|
||||
|
||||
//look into header to find frame rate
|
||||
bool foundFrame = true;
|
||||
uint32_t offset = currentMovieOffset + 8;
|
||||
if (compare(offset, "hdrl", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_HDRL_NOT_FOUND;
|
||||
foundFrame = false;
|
||||
}
|
||||
|
||||
offset += 4;
|
||||
if (compare(offset, "avih", 4))
|
||||
{
|
||||
lastError = AVI_ERROR_AVI_AVIH_NOT_FOUND;
|
||||
foundFrame = false;
|
||||
}
|
||||
|
||||
if (foundFrame)
|
||||
{
|
||||
offset += 8; //skip fourcc and cb in AVIMAINHEADER
|
||||
videoInfo.ms_between_frames = getU32(offset) / 1000;
|
||||
videoInfo.number_of_frames = getU32(offset + 16);
|
||||
videoInfo.frame_width = getU32(offset + 32);
|
||||
videoInfo.frame_height = getU32(offset + 36);
|
||||
}
|
||||
//skip rest of AVI header, start from end of AVI List
|
||||
|
||||
//look for list with 'movi' header
|
||||
uint32_t listOffset = aviListOffset + aviListSize + 8;
|
||||
readData(listOffset, 12);
|
||||
while (compare(listOffset + 8, "movi", 4) && (lastError == AVI_NO_ERROR) && listOffset < movieLength)
|
||||
{
|
||||
const uint32_t listSize = getU32(listOffset + 4) + 8;
|
||||
listOffset += listSize;
|
||||
readData(listOffset, 12);
|
||||
}
|
||||
|
||||
if (lastError != AVI_NO_ERROR)
|
||||
{
|
||||
lastError = AVI_ERROR_MOVI_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
//save first frame and end of last frame
|
||||
currentMovieOffset = listOffset + 8 + 4; //skip LIST and 'movi'
|
||||
lastFrameEnd = listOffset + 8 + getU32(listOffset + 4);
|
||||
|
||||
//find idx
|
||||
const uint32_t listSize = getU32(listOffset + 4) + 8;
|
||||
listOffset += listSize;
|
||||
readData(listOffset, 4);
|
||||
if (!compare(listOffset, "idx1", 4))
|
||||
{
|
||||
indexOffset = listOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastError = AVI_ERROR_IDX1_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
//start on first frame
|
||||
frameNumber = 1; //next frame number is 1
|
||||
firstFrameOffset = currentMovieOffset;
|
||||
}
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == 16 || VIDEO_DECODE_FORMAT == 24 || VIDEO_DECODE_FORMAT == 32
|
||||
void SoftwareMJPEGDecoder::decodeMJPEGFrame(const uint8_t* const mjpgdata, const uint32_t length, uint8_t* outputBuffer, uint16_t bufferWidth, uint16_t bufferHeight, uint32_t bufferStride)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputBuffer && lineBuffer) //only decode if buffers are assigned.
|
||||
{
|
||||
/* This struct contains the JPEG decompression parameters */
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler */
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
JSAMPROW lines[2] = { lineBuffer, 0 }; /* Output row buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
/* Initialize the JPEG decompression object */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
//jpeg_stdio_src (&cinfo, file);
|
||||
jpeg_mem_src(&cinfo, const_cast<uint8_t*>(mjpgdata), length);
|
||||
|
||||
/* Step 3: read image parameters with jpeg_read_header() */
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
cinfo.dct_method = JDCT_FLOAT;
|
||||
|
||||
/* Step 5: start decompressor */
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
//restrict to minimum of movie and output buffer size
|
||||
const uint32_t width = MIN(bufferWidth, cinfo.image_width);
|
||||
const uint32_t height = MIN(bufferHeight, cinfo.output_height);
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == 16
|
||||
uint16_t* lineptr = reinterpret_cast<uint16_t*>(outputBuffer);
|
||||
#elif VIDEO_DECODE_FORMAT == 24
|
||||
uint8_t* lineptr = outputBuffer;
|
||||
#else
|
||||
uint32_t* lineptr = reinterpret_cast<uint32_t*>(outputBuffer);
|
||||
#endif
|
||||
while (cinfo.output_scanline < height)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
#if VIDEO_DECODE_FORMAT == 16
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
JPEG_RGB* const RGB_end = RGB_matrix + width;
|
||||
while (RGB_matrix < RGB_end)
|
||||
{
|
||||
const uint16_t pix = ((RGB_matrix->R & 0xF8) << 8) | ((RGB_matrix->G & 0xFC) << 3) | ((RGB_matrix->B & 0xF8) >> 3);
|
||||
*lineptr++ = pix;
|
||||
RGB_matrix++;
|
||||
}
|
||||
lineptr = (uint16_t*)((uint8_t*)lineptr + bufferStride - width * 2); //move to next line
|
||||
#elif VIDEO_DECODE_FORMAT == 24
|
||||
memcpy(lineptr, lineBuffer, width * 3);
|
||||
lineptr += bufferStride; //move to next line
|
||||
#else
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
JPEG_RGB* const RGB_end = RGB_matrix + width;
|
||||
while (RGB_matrix < RGB_end)
|
||||
{
|
||||
const uint32_t pix = (0xFF << 24) | (RGB_matrix->R << 16) | (RGB_matrix->G << 8) | (RGB_matrix->B);
|
||||
*lineptr++ = pix;
|
||||
RGB_matrix++;
|
||||
}
|
||||
lineptr = (uint32_t*)((uint8_t*)lineptr + bufferStride - width * 4); //move to next line
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SIMULATOR
|
||||
cinfo.output_scanline = cinfo.output_height;
|
||||
#endif
|
||||
/* Step 6: Finish decompression */
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
/* Step 7: Release JPEG decompression object */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
}
|
||||
}
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeFrame(const touchgfx::Rect& area, uint8_t* frameBuffer, uint32_t framebuffer_width)
|
||||
{
|
||||
// Assuming that chunk is available and streamNo and chunkType is correct.
|
||||
// Check by gotoNextFrame
|
||||
|
||||
readData(currentMovieOffset, 8);
|
||||
const uint32_t length = getU32(currentMovieOffset + 4);
|
||||
|
||||
// Ensure whole frame is read
|
||||
const uint8_t* mjpgdata = readData(currentMovieOffset + 8, length);
|
||||
|
||||
assert(lineBuffer && "LineBuffer must be assigned prior to decoding directly to framebuffer");
|
||||
|
||||
/* This struct contains the JPEG decompression parameters */
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler */
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
JSAMPROW lines[2] = { lineBuffer, 0 }; /* Output row buffer */
|
||||
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
|
||||
/* Initialize the JPEG decompression object */
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
//jpeg_stdio_src (&cinfo, file);
|
||||
jpeg_mem_src(&cinfo, const_cast<uint8_t*>(mjpgdata), length);
|
||||
|
||||
/* Step 3: read image parameters with jpeg_read_header() */
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
/* Step 4: set parameters for decompression */
|
||||
cinfo.dct_method = JDCT_FLOAT;
|
||||
|
||||
/* Step 5: start decompressor */
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
//restrict to minimum of movie and output buffer size
|
||||
const uint32_t startY = area.y;
|
||||
|
||||
//scan down to startY
|
||||
while (cinfo.output_scanline < startY)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
}
|
||||
|
||||
const uint32_t startX = area.x;
|
||||
const uint32_t endX = MIN((uint32_t)area.right(), cinfo.image_width);
|
||||
|
||||
#if VIDEO_DECODE_FORMAT == 16
|
||||
uint16_t* lineptr = reinterpret_cast<uint16_t*>(frameBuffer);
|
||||
lineptr += framebuffer_width * startY;
|
||||
#elif VIDEO_DECODE_FORMAT == 24
|
||||
uint8_t* lineptr = frameBuffer;
|
||||
lineptr += framebuffer_width * 3 * startY;
|
||||
#else
|
||||
uint32_t* lineptr = reinterpret_cast<uint32_t*>(frameBuffer);
|
||||
lineptr += framebuffer_width * startY;
|
||||
#endif
|
||||
const uint32_t endY = MIN((uint32_t)area.bottom(), cinfo.output_height);
|
||||
|
||||
//scan relevant part
|
||||
while (cinfo.output_scanline < endY)
|
||||
{
|
||||
(void)jpeg_read_scanlines(&cinfo, lines, 1);
|
||||
#if VIDEO_DECODE_FORMAT == 16
|
||||
JPEG_RGB* RGB_matrix = (JPEG_RGB*)lineBuffer;
|
||||
//loop row RGB888->RGB565 for required line part
|
||||
for (uint32_t counter = startX; counter < endX; counter++)
|
||||
{
|
||||
const uint16_t pix = ((RGB_matrix[counter].R & 0xF8) << 8) | ((RGB_matrix[counter].G & 0xFC) << 3) | ((RGB_matrix[counter].B & 0xF8) >> 3);
|
||||
*(lineptr + counter) = pix;
|
||||
}
|
||||
lineptr += framebuffer_width; //move to next line
|
||||
#elif VIDEO_DECODE_FORMAT == 24
|
||||
memcpy(lineptr + startX * 3, lineBuffer + startX * 3, (endX - startX) * 3);
|
||||
lineptr += framebuffer_width * 3; //move to next line
|
||||
#else
|
||||
memcpy(lineptr + startX, lineBuffer + startX * 4, (endX - startX) * 4);
|
||||
lineptr += framebuffer_width; //move to next line
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SIMULATOR
|
||||
cinfo.output_scanline = cinfo.output_height;
|
||||
#endif
|
||||
|
||||
/* Step 6: Finish decompression */
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
/* Step 7: Release JPEG decompression object */
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
void SoftwareMJPEGDecoder::decodeMJPEGFrame(const uint8_t* const, const uint32_t, uint8_t*, uint16_t, uint16_t, uint32_t)
|
||||
{
|
||||
}
|
||||
bool SoftwareMJPEGDecoder::decodeFrame(const touchgfx::Rect&, uint8_t*, uint32_t)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif // VIDEO_DECODE_FORMAT == 16 || VIDEO_DECODE_FORMAT == 24 || VIDEO_DECODE_FORMAT == 32
|
||||
|
||||
bool SoftwareMJPEGDecoder::decodeThumbnail(uint32_t frameno, uint8_t* buffer, uint16_t width, uint16_t height)
|
||||
{
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::gotoFrame(uint32_t frameNumber)
|
||||
{
|
||||
if (frameNumber == 0)
|
||||
{
|
||||
frameNumber = 1;
|
||||
}
|
||||
|
||||
if (frameNumber > getNumberOfFrames())
|
||||
{
|
||||
frameNumber = getNumberOfFrames();
|
||||
}
|
||||
|
||||
uint32_t offset = indexOffset + 8 + (frameNumber - 1) * 16;
|
||||
|
||||
readData(offset, 16);
|
||||
|
||||
currentMovieOffset = getU32(offset + 8) + firstFrameOffset - 4;
|
||||
this->frameNumber = frameNumber;
|
||||
}
|
||||
|
||||
uint32_t SoftwareMJPEGDecoder::getNumberOfFrames()
|
||||
{
|
||||
return videoInfo.number_of_frames;
|
||||
}
|
||||
|
||||
void SoftwareMJPEGDecoder::getVideoInfo(touchgfx::VideoInformation* data)
|
||||
{
|
||||
*data = videoInfo;
|
||||
// For unsupported decode formats, set video dimension to 0x0, to avoid drawing anything
|
||||
#if VIDEO_DECODE_FORMAT == 16 || VIDEO_DECODE_FORMAT == 24 || VIDEO_DECODE_FORMAT == 32
|
||||
#else
|
||||
data->frame_width = 0;
|
||||
data->frame_height = 0;
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user