Plays MJPEG Video using the RGA. THe RGA allows resize of the JPEG file.

Dependencies:   GR-PEACH_video GraphicsFramework LCD_shield_config R_BSP SDBlockDevice_GR_PEACH TLV320_RBSP USBHost_custom

Fork of RGA_HelloWorld by Renesas

Overview

This demo shows how play a MJPEG and WAV file video using the RZA1 hardware RGA, JCU and SSIF. The JCU decodes each MJPEG frame. The SSIF plays the raw WAV file, and the RGA supplies the GUI and resize of the JPEG image.

MJPEG Creation

Requirements

Python Script

SD Card

  • Rename the jpg file to Renesas.jpg and audio file Renesas.wav
  • Download this image file and rename is Background.jpg /media/uploads/zkimike/background.jpg
Revision:
12:9a413bec6673
Parent:
7:8fd684e60d66
Child:
13:0a5bd13f6e7f
--- a/main.cpp	Mon Apr 24 16:40:18 2017 +0900
+++ b/main.cpp	Fri Jan 05 22:41:01 2018 +0000
@@ -22,7 +22,12 @@
 #include "rga_func.h"
 #include "DisplayBace.h"
 #include "rtos.h"
+#include "TLV320_RBSP.h"
 #include "LCD_shield_config_7_1inch.h"
+#include "FATFileSystem.h"
+#include "SDBlockDevice_GR_PEACH.h"
+#include "USBHostMSD.h"
+#include "dec_wav.h"
 
 #define GRAPHICS_FORMAT                     (DisplayBase::GRAPHICS_FORMAT_RGB565)
 #define WR_RD_WRSWA                         (DisplayBase::WR_RD_WRSWA_32_16BIT)
@@ -34,10 +39,29 @@
 
 #define DRAW_RECTANGLE_CNT_MAX              (4)
 
+#define FILE_NAME_LEN          (64)
+#define FLD_PATH               "/usb/"
+#define TEXT_SIZE              (64 + 1) //null-terminated
+
+#define MJPEG_DIV       2
+#define AUDIO_WRITE_BUFF_SIZE  (7056 * MJPEG_DIV)
+#define AUDIO_WRITE_BUFF_NUM   (9)
+
+// Testing
+DigitalOut TestPin0(D0); // Video File Read
+DigitalOut TestPin1(D1); // Audio File Read
+DigitalOut TestPin2(D6); // Update Display
+DigitalOut TestPin3(D7); // Sync
+
 typedef enum {
     RGA_FUNC_NON,
     RGA_FUNC_DRAW_RECTANGLE,
     RGA_FUNC_DRAW_IMAGE,
+    RGA_FUNC_VIDEO_PLAYER,
+    RGA_FUNC_VIDEO_PLAY,
+    RGA_FUNC_VIDEO_STOP,
+    RGA_FUNC_VIDEO_FWD,
+    RGA_FUNC_VIDEO_REV,
     RGA_FUNC_DISSOLVE,
     RGA_FUNC_SCROLL,
     RGA_FUNC_ZOOM,
@@ -73,14 +97,22 @@
 #else
 static uint8_t user_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); /* 32 bytes aligned */
 static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); /* 32 bytes aligned */
+static uint8_t jpeg_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); /* 32 bytes aligned */
+static uint8_t jpeg_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); /* 32 bytes aligned */
+static uint8_t audio_write_buff[AUDIO_WRITE_BUFF_NUM][AUDIO_WRITE_BUFF_SIZE] __attribute((section("NC_BSS"),aligned(4)));
 #endif
 static frame_buffer_t frame_buffer_info;
 static volatile int32_t vsync_count = 0;
 
+// Audio Tag buffers
+static uint8_t title_buf[TEXT_SIZE];
+static uint8_t artist_buf[TEXT_SIZE];
+static uint8_t album_buf[TEXT_SIZE];
+
 static const key_pic_info_t top_screen_key_tbl[] = {
     /*   X       Y     Width   Height   Func code                 */
     {    50,    350,    120,     52,    RGA_FUNC_DRAW_RECTANGLE    },  /* RGA Func1 */
-    {   230,    350,    120,     52,    RGA_FUNC_DRAW_IMAGE        },  /* RGA Func2 */
+    {   230,    350,    120,     52,    RGA_FUNC_VIDEO_PLAYER      },  /* RGA Func2 */
     {   410,    350,    120,     52,    RGA_FUNC_DISSOLVE          },  /* RGA Func3 */
     {    50,    420,    120,     52,    RGA_FUNC_SCROLL            },  /* RGA Func4 */
     {   230,    420,    120,     52,    RGA_FUNC_ZOOM              },  /* RGA Func5 */
@@ -106,6 +138,17 @@
     {     0,      0,      0,      0,    RGA_FUNC_END               }   /* table end */
 };
 
+static const key_pic_info_t video_screen_key_tbl[] = {
+    /*   X       Y     Width   Height   Func code                 */
+    {   640,     10,    150,     84,    RGA_FUNC_RETURN            },  /* Return Top Screen */
+    {   545,     55,    192,     64,    RGA_FUNC_VIDEO_PLAY        },  /* Video Play */
+    {   545,     138,   192,     64,    RGA_FUNC_VIDEO_STOP        },  /* Video Stop */
+    {   654,     241,    89,     60,    RGA_FUNC_VIDEO_FWD         },  /* Video Forward */
+    {   545,     241,    89,     60,    RGA_FUNC_VIDEO_REV         }   /* Video Reverse */
+};
+TLV320_RBSP audio(P10_13, I2C_SDA, I2C_SCL, P4_4, P4_5, P4_7, P4_6,
+                  0x80, (AUDIO_WRITE_BUFF_NUM - 1), 0);
+                  
 /****** LCD ******/
 static void IntCallbackFunc_LoVsync(DisplayBase::int_type_t int_type) {
     /* Interrupt callback function for Vsync interruption */
@@ -185,6 +228,12 @@
         frmbuf_info->draw_buffer_index = 1;
     }
 }
+/****** Audio ******/
+static void callback_audio_write_end(void * p_data, int32_t result, void * p_app_data) {
+    if (result < 0) {
+        printf("audio write callback error %d\n", result);
+    }
+}
 
 /****** Touch ******/
 static func_code_t Scan_Key(const key_pic_info_t * key_tbl, const uint32_t pos_x, const uint32_t pos_y) {
@@ -299,6 +348,157 @@
             }
         }
         break;
+        case RGA_FUNC_VIDEO_PLAYER:
+        case RGA_FUNC_VIDEO_PLAY:
+        case RGA_FUNC_VIDEO_STOP:
+        case RGA_FUNC_VIDEO_FWD:
+        case RGA_FUNC_VIDEO_REV:
+        {
+            // FileSystem
+            FILE * vfp = NULL;
+            FILE * afp = NULL;
+            DIR  * d = NULL;
+            char file_path[sizeof(FLD_PATH) + FILE_NAME_LEN];
+            uint16_t read_bytes = 0;
+            dec_wav wav_file;
+            
+            // Video File
+            int framesize = 0;
+            float framerate = 0.0;
+            uint8_t frame_skip = 2;
+            
+            // Audio File
+            uint16_t buff_index = 0;
+            uint8_t * p_buf = NULL;
+            size_t audio_data_size;
+            rbsp_data_conf_t audio_write_async_ctl = {&callback_audio_write_end, NULL};
+            
+            // Sync
+            uint32_t frame_period_ms = 0;
+            uint32_t audio_sample_size = 0;
+            Timer timer;
+            
+            /*******************************************************************
+            *   Initialize SDHC FileSystem
+            *******************************************************************/
+            FATFileSystem fs("usb");
+            SDBlockDevice_GR_PEACH msd;
+            
+            printf("GR-PEACH SDHC MSD\n");
+            
+            while(!msd.connect()) {
+                Thread::wait(500);
+            }
+            // Now that the MSD device is connected, file system is mounted.
+            fs.mount(&msd);
+            
+            /*******************************************************************
+            *   Initialize Audio
+            *******************************************************************/
+            audio.power(0x02); // mic off
+            audio.inputVolume(0.7, 0.7);
+    
+            /*******************************************************************
+            *   Read background
+            *******************************************************************/
+            strcpy(file_path, FLD_PATH);
+            strcat(file_path, "Background.jpg");
+            printf("File Open: %s\n", file_path);
+            vfp = fopen(file_path, "r");
+            read_bytes = fread(&jpeg_frame_buffer1[0], sizeof(char), 114419, vfp);
+            fclose(vfp);
+            
+            /*******************************************************************
+            *   Open Video File
+            *******************************************************************/
+            strcpy(file_path, FLD_PATH);
+            strcat(file_path, "Renesas.jpg");
+            vfp = fopen(file_path, "r");
+            fread ( &framerate, sizeof(char), 4, vfp);
+            printf( "Video FrameRate : %f\n", framerate );
+            fread ( &framesize, sizeof(char), 4, vfp);
+            fread ( jpeg_frame_buffer2, sizeof(char), framesize, vfp);
+            
+            /*******************************************************************
+            *   Open and Anylize WAV file
+            *******************************************************************/
+            strcpy(file_path, FLD_PATH);
+            strcat(file_path, "Renesas.wav");
+            afp = fopen(file_path, "r");
+            wav_file.AnalyzeHeder(title_buf, artist_buf, album_buf, TEXT_SIZE, afp);
+            if ( false == audio.format(wav_file.GetBlockSize()) ) {
+                printf( "Audio ERROR Setting format : %d\n", wav_file.GetBlockSize());
+                break;
+            }
+            if ( false == audio.frequency(wav_file.GetSamplingRate()) ) {
+                printf( "Audio ERROR Setting frequency : f%Hz\n", wav_file.GetSamplingRate());
+                break;
+            }
+            /*******************************************************************
+            *   Initialize Sync
+            *******************************************************************/
+            frame_period_ms = (int)((1/framerate) * 1000);
+            printf( "Audio Frame Lenght : %dms\n", frame_period_ms);
+            frame_period_ms = frame_period_ms * MJPEG_DIV;
+            printf( "Video Frame Lenght : %dms\n", frame_period_ms);
+            audio_sample_size = (int)((wav_file.GetSamplingRate() * wav_file.GetChannel()
+                                                * (wav_file.GetBlockSize()/8)) / ( framerate )) * MJPEG_DIV;
+            frame_skip = MJPEG_DIV-1;
+            
+            TestPin0 = 0;
+            TestPin1 = 0;
+            TestPin2 = 0;
+            TestPin3 = 0;
+            timer.reset();
+            
+            while (1) {
+                timer.start();
+                
+                // if device disconnected, try to connect again
+                if (!msd.connected()) {
+                    break;
+                }
+                                
+                // Read Next Video Frame
+                TestPin0 = 1;
+                for ( int i = 0; i < frame_skip; i++ ) {
+                    fread ( &framesize, sizeof(char), 4, vfp);
+                    fseek ( vfp, framesize, SEEK_CUR);
+                }
+                fread ( &framesize, sizeof(char), 4, vfp);
+                fread ( jpeg_frame_buffer2, sizeof(char), framesize, vfp);
+                TestPin0 = 0;
+                
+                // Read and play Next Audio Frame
+                TestPin1 = 1;
+                p_buf = audio_write_buff[buff_index];
+                audio_data_size = wav_file.GetNextData(p_buf, AUDIO_WRITE_BUFF_SIZE);
+                if (audio_data_size > 0) {
+                    audio.write(p_buf, audio_data_size, &audio_write_async_ctl);
+                    buff_index++;
+                    if (buff_index >= AUDIO_WRITE_BUFF_NUM) {
+                        buff_index = 0;
+                    }
+                }
+                TestPin1 = 0;
+                                   
+                /* Draw screen */
+                TestPin2 = 1;
+                Swap_FrameBuffer(frmbuf_info);
+                RGA_Func_VideoPlayer(frmbuf_info, jpeg_frame_buffer1, jpeg_frame_buffer2);
+                Update_LCD_Display(frmbuf_info);
+                TestPin2 = 0;
+                buff_index++;
+            
+                // Sync
+                TestPin3 = 1;
+                while( frame_period_ms > timer.read_ms());
+                timer.stop();
+                timer.reset();
+                TestPin3 = 0;               
+            }
+        }
+        break;
         case RGA_FUNC_DISSOLVE:
         {
             float32_t work_alpha = 0.0f;
@@ -458,7 +658,7 @@
     /* Display Top Screen */
     Set_RGAObject(&frame_buffer_info);
     RGA_Func_DrawTopScreen(&frame_buffer_info);
-
+        
     /* Start of LCD */
     Start_LCD_Display(frame_buffer_info.buffer_address[0]);
 
@@ -469,7 +669,7 @@
     /* Reset touch IC */
     TouckKey_LCD_shield touch(P4_0, P2_13, I2C_SDA, I2C_SCL);
     touch.Reset();
-
+    
     while (1) {
         /* Get Coordinates */
         touch_num = touch.GetCoordinates(TOUCH_NUM, touch_pos);
@@ -496,4 +696,4 @@
         }
         Thread::wait(20);
     }
-}
+}
\ No newline at end of file