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
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;
+}
+