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

MovPlayer.cpp

Committer:
mtkrtk
Date:
2017-03-12
Revision:
1:3e638b9e91cd
Parent:
0:d0f130e27d32

File content as of revision 1:3e638b9e91cd:

#include "MovPlayer.hpp"

MovPlayer::VideoBuffer MovPlayer::videoBuf[];
MovPlayer::AudioBuffer MovPlayer::audioBuf[];
unsigned char MovPlayer::audioThreadStack[];
MovPlayer MovPlayer::singleton;

static void audioCallback(void MBED_UNUSED *p_data, int32_t result, void MBED_UNUSED *p_app_data) {
    if (result < 0) {
        printf("audio write callback error %ld\n", result);
    }
//    pc.printf("f");
}

MovPlayer::MovPlayer() : audioThread(osPriorityNormal, DEFAULT_STACK_SIZE, audioThreadStack), frameTimer(mbed::Callback<void ()>(this, &MovPlayer::frameTimerCallback), osTimerPeriodic), frameSemaphore(0), mov(nullptr)
{
}

void MovPlayer::frameTimerCallback()
{
    frameSemaphore.release();
}

void MovPlayer::audioProcessor()
{
    VideoBuffer *videoP = videoBuf;
    AudioBuffer *audioP = audioBuf;
    rbsp_data_conf_t audioConf = {&audioCallback, NULL};
    frameTimer.start(1e3 / 30 + 1);
    int index = BufferLength;
    while (1) {
        do {
            if (mov->read(videoP->buf, audioP->buf, &audioP->size)) {
                videoQueue.put(videoP);
                output(audioP->buf, audioP->size, &audioConf);
                ++videoP;
                ++audioP;
            } else {
                queueTimeout = 0;
                __ISB();
                __DSB();
                rtos::Thread::wait(osWaitForever);
            }
        } while (--index);
        videoP = videoBuf;
        audioP = audioBuf;
        index = BufferLength;
    }
}

void MovPlayer::play(MovFile *_mov, LCD *lcd, AudioCallback callback)
{
    mov = _mov;
    output = callback;
    queueTimeout = osWaitForever;
    audioThread.start(mbed::Callback<void ()>(this, &MovPlayer::audioProcessor));
    while (1) {
        osEvent event = videoQueue.get(queueTimeout);
        if (event.status == osEventMessage) {
            VideoBuffer *buf = reinterpret_cast<VideoBuffer *>(event.value.p);
            if (! (buf->buf[0] == 0xFF && buf->buf[1] == 0xD8)) {
                printf("m");
            }
            frameSemaphore.wait();
            lcd->drawImage(reinterpret_cast<graphics_image_t *>(buf->buf));
        } else {
            audioThread.terminate();
            frameTimer.stop();
            while (frameSemaphore.wait(0) > 0) ;
            return;
        }
    }
}