This program plays QuickTime movies on GR-Peach
Dependencies: AsciiFont GR-PEACH_video GraphicsFramework LCD_shield_config R_BSP TLV320_RBSP mbed-rtos mbed
Requirements
- GR-Peach
- GR-Peach Audio Camera Shield or I²S compatible audio DAC
- GR-Peach LCD Shield
- USB memory stick
How to play movie files
- Encode movie files
encode movies with ffmpeg
$ ffmpeg -i <input -ar 44100 -acodec pcm_s16le -s 480x270 -vcodec mjpeg -q:v 3 -movflags faststart -threads 4 -vf fps=30 <output>.mov
- Copy movies to the root directory of USB memory
- Build and upload this program
- Run it
Diff: MovFile.cpp
- Revision:
- 0:d0f130e27d32
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MovFile.cpp Fri Mar 10 11:30:02 2017 +0000 @@ -0,0 +1,120 @@ +#include "MovFile.hpp" +#ifdef __MBED__ +#include <cmsis.h> +#else +#include <arpa/inet.h> +#endif + +uint32_t MovFile::frameSizes[]; +uint32_t MovFile::audioSizes[]; +MovFile MovFile::singleton; + +#define FourConstant(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) + +#ifndef htonl +# define htonl(x) __REV(x) +#endif +#ifndef ntohl +# define ntohl(x) __REV(x) +#endif + +MovFile::MovFile() : frameSizesP(frameSizes), audioSizesP(audioSizes), stszAddress(0), stcoAddress(0), lastFrameAddress(0), availableCount(bufSize) +{ +} + +void MovFile::search(uint32_t pattern) +{ + Buffer buf; + uint8_t first = pattern & 0xFF; + buf.value = 0; + while (1) { + size_t size = fread(buf.array, sizeof(int8_t), 1, file); + if (size == 0) { + return; + } + if (buf.array[0] == first) { + fread(&buf.array[1], sizeof(int8_t), 3, file); + if (buf.value == pattern) { + break; + } + } + } +} + +void MovFile::fillCaches() +{ + Buffer buf[bufSize]; + Buffer *bufP = buf; + uint32_t lastFrame = lastFrameAddress; + + fseek(file, stszAddress, SEEK_SET); + fread(frameSizes, sizeof(uint32_t), bufSize, file); + stszAddress += sizeof(uint32_t) * bufSize; + + fseek(file, stcoAddress, SEEK_SET); + stcoAddress += sizeof(uint32_t) * bufSize; + fread(buf, sizeof(Buffer), bufSize, file); + availableCount = bufSize; + frameSizesP = frameSizes; + audioSizesP = audioSizes; + do { + uint32_t frameAddress = htonl(bufP->value); + *frameSizesP = htonl(*frameSizesP); + *audioSizesP++ = frameAddress - lastFrameAddress - *frameSizesP; + lastFrameAddress = frameAddress; + ++frameSizesP; + ++bufP; + } while (--availableCount); + + fseek(file, lastFrame, SEEK_SET); + availableCount = bufSize; + frameSizesP = frameSizes; + audioSizesP = audioSizes; +} + +void MovFile::start(FILE *f) +{ + Buffer buf; + file = f; + frameSizesP = frameSizes; + audioSizesP = audioSizes; + + search(htonl(FourConstant('s', 't', 's', 'z'))); + printf("stsz is at 0x%lX\n", ftell(file) - 4); + fseek(file, 8, SEEK_CUR); + fread(&buf, sizeof(Buffer), 1, file); + numOfFrames = htonl(buf.value); + printf("Number of frames: %lu\n", numOfFrames); + stszAddress = ftell(file); + fread(&buf, sizeof(Buffer), 1, file); + + search(htonl(FourConstant('s', 't', 'c', 'o'))); + printf("stco is at 0x%lX\n", ftell(file) - 4); + fseek(file, 4, SEEK_CUR); + fread(&buf, sizeof(Buffer), 1, file); + if (numOfFrames != htonl(buf.value)) { + printf("Different number of frames\n"); + return; + } + fread(&buf, sizeof(Buffer), 1, file); + stcoAddress = ftell(file); + lastFrameAddress = htonl(buf.value); + printf("First frame is at 0x%lX\n", lastFrameAddress); + + fillCaches(); +} + +bool MovFile::read(char *videoBuf, char *audioBuf, uint32_t *audioSize) +{ + if (numOfFrames) { + uint32_t aSize = *audioSizesP++; + fread(videoBuf, *frameSizesP++, 1, file); + *audioSize = (uint32_t)fread(audioBuf, 1, aSize, file); + if (--availableCount == 0) { + fillCaches(); + } + return numOfFrames--; + } + return false; +} +