Camera in sample for GR-PEACH. This sample works on GR-LYCHEE besides GR-PEACH.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "EasyAttach_CameraAndLCD.h"
00003 #include "SdUsbConnect.h"
00004 #include "JPEG_Converter.h"
00005 #include "dcache-control.h"
00006 
00007 /**** User Selection *********/
00008 #define SAVE_FILE_TYPE         (0)     /* Select  0(Image(.jpg)) or 1(Movie(.avi)) */
00009 /*****************************/
00010 
00011 #define MOUNT_NAME             "storage"
00012 
00013 /*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
00014     in accordance with the frame buffer burst transfer mode. */
00015 #define VIDEO_PIXEL_HW         (640u)  /* VGA */
00016 #define VIDEO_PIXEL_VW         (480u)  /* VGA */
00017 
00018 #define FRAME_BUFFER_STRIDE    (((VIDEO_PIXEL_HW * 2) + 31u) & ~31u)
00019 #define FRAME_BUFFER_HEIGHT    (VIDEO_PIXEL_VW)
00020 
00021 #if defined(__ICCARM__)
00022 #pragma data_alignment=32
00023 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram";
00024 #else
00025 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));
00026 #endif
00027 static int file_name_index = 1;
00028 static volatile int Vfield_Int_Cnt = 0;
00029 /* jpeg convert */
00030 static JPEG_Converter Jcu;
00031 #if defined(__ICCARM__)
00032 #pragma data_alignment=32
00033 static uint8_t JpegBuffer[1024 * 63];
00034 #else
00035 static uint8_t JpegBuffer[1024 * 63]__attribute((aligned(32)));
00036 #endif
00037 
00038 DisplayBase Display;
00039 DigitalIn   button0(USER_BUTTON0);
00040 DigitalOut  led1(LED1);
00041 
00042 static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) {
00043     if (Vfield_Int_Cnt > 0) {
00044         Vfield_Int_Cnt--;
00045     }
00046 }
00047 
00048 static void wait_new_image(void) {
00049     Vfield_Int_Cnt = 1;
00050     while (Vfield_Int_Cnt > 0) {
00051         ThisThread::sleep_for(1);
00052     }
00053 }
00054 
00055 static void Start_Video_Camera(void) {
00056     // Initialize the background to black
00057     for (uint32_t i = 0; i < sizeof(user_frame_buffer0); i += 2) {
00058         user_frame_buffer0[i + 0] = 0x10;
00059         user_frame_buffer0[i + 1] = 0x80;
00060     }
00061 
00062     // Field end signal for recording function in scaler 0
00063     Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VFIELD, 0, IntCallbackFunc_Vfield);
00064 
00065     // Video capture setting (progressive form fixed)
00066     Display.Video_Write_Setting(
00067         DisplayBase::VIDEO_INPUT_CHANNEL_0,
00068         DisplayBase::COL_SYS_NTSC_358,
00069         (void *)user_frame_buffer0,
00070         FRAME_BUFFER_STRIDE,
00071         DisplayBase::VIDEO_FORMAT_YCBCR422,
00072         DisplayBase::WR_RD_WRSWA_32_16BIT,
00073         VIDEO_PIXEL_VW,
00074         VIDEO_PIXEL_HW
00075     );
00076     EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
00077 }
00078 
00079 #if MBED_CONF_APP_LCD
00080 static void Start_LCD_Display(void) {
00081     DisplayBase::rect_t rect;
00082 
00083     rect.vs = 0;
00084     rect.vw = VIDEO_PIXEL_VW;
00085     rect.hs = 0;
00086     rect.hw = VIDEO_PIXEL_HW;
00087     Display.Graphics_Read_Setting(
00088         DisplayBase::GRAPHICS_LAYER_0,
00089         (void *)user_frame_buffer0,
00090         FRAME_BUFFER_STRIDE,
00091         DisplayBase::GRAPHICS_FORMAT_YCBCR422,
00092         DisplayBase::WR_RD_WRSWA_32_16BIT,
00093         &rect
00094     );
00095     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
00096 
00097     ThisThread::sleep_for(50);
00098     EasyAttach_LcdBacklight(true);
00099 }
00100 #endif
00101 
00102 #if (SAVE_FILE_TYPE == 0)
00103 static void save_image_jpg(void) {
00104     size_t jcu_encode_size = 0;
00105     JPEG_Converter::bitmap_buff_info_t bitmap_buff_info;
00106     JPEG_Converter::encode_options_t   encode_options;
00107 
00108     bitmap_buff_info.width              = VIDEO_PIXEL_HW;
00109     bitmap_buff_info.height             = VIDEO_PIXEL_VW;
00110     bitmap_buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00111     bitmap_buff_info.buffer_address     = (void *)user_frame_buffer0;
00112 
00113     encode_options.encode_buff_size     = sizeof(JpegBuffer);
00114     encode_options.p_EncodeCallBackFunc = NULL;
00115     encode_options.input_swapsetting    = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
00116 
00117     dcache_invalid(JpegBuffer, sizeof(JpegBuffer));
00118     if (Jcu.encode(&bitmap_buff_info, JpegBuffer, &jcu_encode_size, &encode_options) == JPEG_Converter::JPEG_CONV_OK) {
00119         char file_name[32];
00120         sprintf(file_name, "/"MOUNT_NAME"/img_%d.jpg", file_name_index++);
00121         FILE * fp = fopen(file_name, "w");
00122         if (fp != NULL) {
00123             setvbuf(fp, NULL, _IONBF, 0); // unbuffered
00124             fwrite(JpegBuffer, sizeof(char), (int)jcu_encode_size, fp);
00125             fclose(fp);
00126         }
00127         printf("Saved file %s\r\n", file_name);
00128     }
00129 }
00130 
00131 int main() {
00132     EasyAttach_Init(Display);
00133     Start_Video_Camera();
00134 #if MBED_CONF_APP_LCD
00135     Start_LCD_Display();
00136 #endif
00137     SdUsbConnect storage(MOUNT_NAME);
00138 
00139     while (1) {
00140         storage.wait_connect();
00141         if (button0 == 0) {
00142             wait_new_image(); // wait for image input
00143             led1 = 1;
00144             save_image_jpg(); // save as jpeg
00145             led1 = 0;
00146         }
00147     }
00148 }
00149 
00150 #else
00151 
00152 #define MAX_FRAME_NUM     1024
00153 #define VIDEO_BUFF_SIZE  (VIDEO_PIXEL_HW * VIDEO_PIXEL_VW * 2)
00154 
00155 static uint32_t mjpg_index[MAX_FRAME_NUM];
00156 static uint32_t mjpg_size[MAX_FRAME_NUM];
00157 static uint8_t work_buf[256];
00158 
00159 static const uint8_t MJpegHeader[224] = {
00160     0x52, 0x49, 0x46, 0x46, // "RIFF"
00161     0xF0, 0xFF, 0xFF, 0x7F, // [Temporary] Total data size (File size - 8)
00162     0x41, 0x56, 0x49, 0x20, // "AVI "
00163     0x4C, 0x49, 0x53, 0x54, // "LIST"
00164     0xC0, 0x00, 0x00, 0x00, // Size of the list
00165     0x68, 0x64, 0x72, 0x6C, // "hdrl"
00166     0x61, 0x76, 0x69, 0x68, // "avih"
00167     0x38, 0x00, 0x00, 0x00, // avih chunk size
00168     0x35, 0x82, 0x00, 0x00, // [Temporary] Frame interval (microseconds)
00169     0x00, 0xCC, 0x00, 0x00, // Approximate maximum data rate
00170     0x00, 0x00, 0x00, 0x00, // Padding unit
00171     0x10, 0x00, 0x00, 0x00, // With index information
00172     0x00, 0x48, 0x00, 0x00, // [Temporary] Total number of frames
00173     0x00, 0x00, 0x00, 0x00, // dummy
00174     0x01, 0x00, 0x00, 0x00, // Number of streams
00175     0x00, 0x00, 0x10, 0x00, // Required buffer size (estimate)
00176     ((VIDEO_PIXEL_HW >> 0) & 0xFF), ((VIDEO_PIXEL_HW >> 8) & 0xFF), ((VIDEO_PIXEL_HW >> 16) & 0xFF), ((VIDEO_PIXEL_HW >> 24) & 0xFF), // width
00177     ((VIDEO_PIXEL_VW >> 0) & 0xFF), ((VIDEO_PIXEL_VW >> 8) & 0xFF), ((VIDEO_PIXEL_VW >> 16) & 0xFF), ((VIDEO_PIXEL_VW >> 24) & 0xFF), // height
00178     0x00, 0x00, 0x00, 0x00, // not use
00179     0x00, 0x00, 0x00, 0x00, // not use
00180     0x00, 0x00, 0x00, 0x00, // not use
00181     0x00, 0x00, 0x00, 0x00, // not use
00182     0x4C, 0x49, 0x53, 0x54, // "LIST"
00183     0x74, 0x00, 0x00, 0x00, // Size of the list
00184     0x73, 0x74, 0x72, 0x6C, // "strl"
00185     0x73, 0x74, 0x72, 0x68, // "strh"
00186     0x38, 0x00, 0x00, 0x00, // strl chunk size
00187     0x76, 0x69, 0x64, 0x73, // "vids"
00188     0x4D, 0x4A, 0x50, 0x47, // "MJPG"
00189     0x00, 0x00, 0x00, 0x00, // Stream handling is normal
00190     0x00, 0x00, 0x00, 0x00, // Stream priority 0, no language setting
00191     0x00, 0x00, 0x00, 0x00, // Audio first frame: None
00192     0x01, 0x00, 0x00, 0x00, // Number of frames per second (denominator)
00193     0x1E, 0x00, 0x00, 0x00, // [Temporary] Number of frames per second (numerator)
00194     0x00, 0x00, 0x00, 0x00, // Stream start size
00195     0x00, 0x48, 0x00, 0x00, // [Temporary] Stream length
00196     0x00, 0x00, 0x00, 0x00, // Buffer size: unknown
00197     0xFF, 0xFF, 0xFF, 0xFF, // Default quality
00198     0x00, 0x00, 0x00, 0x00, // Size per sample (change)
00199     0x00, 0x00, 0x00, 0x00, // Display coordinates (x, y in upper left)
00200     ((VIDEO_PIXEL_HW)& 0xFF), ((VIDEO_PIXEL_HW >> 8) & 0xFF), ((VIDEO_PIXEL_VW)& 0xFF), ((VIDEO_PIXEL_VW >> 8) & 0xFF), //[Temporary] Display coordinates (x, y in lower right)
00201     0x73, 0x74, 0x72, 0x66, // "strf"
00202     0x28, 0x00, 0x00, 0x00, // strf chunk size
00203     0x28, 0x00, 0x00, 0x00, // Chunk body size
00204     ((VIDEO_PIXEL_HW >> 0) & 0xFF), ((VIDEO_PIXEL_HW >> 8) & 0xFF), ((VIDEO_PIXEL_HW >> 16) & 0xFF), ((VIDEO_PIXEL_HW >> 24) & 0xFF), // width
00205     ((VIDEO_PIXEL_VW >> 0) & 0xFF), ((VIDEO_PIXEL_VW >> 8) & 0xFF), ((VIDEO_PIXEL_VW >> 16) & 0xFF), ((VIDEO_PIXEL_VW >> 24) & 0xFF), // height
00206     0x01, 0x00, 0x10, 0x00, // Number of faces and bpp
00207     0x4D, 0x4A, 0x50, 0x47, // "MJPG"
00208     ((VIDEO_BUFF_SIZE >> 0) & 0xFF), ((VIDEO_BUFF_SIZE >> 8) & 0xFF), ((VIDEO_BUFF_SIZE >> 16) & 0xFF), ((VIDEO_BUFF_SIZE >> 24) & 0xFF), // Buffer size (width x height x 2)
00209     0x00, 0x00, 0x00, 0x00, // Horizontal resolution
00210     0x00, 0x00, 0x00, 0x00, // Vertical resolution
00211     0x00, 0x00, 0x00, 0x00, // Number of color index
00212     0x00, 0x00, 0x00, 0x00, // Important color index number
00213     0x4C, 0x49, 0x53, 0x54, // "LIST"
00214     0xF0, 0xFF, 0xFF, 0x7F, // [Temporary] List size (index address - 0xDC)
00215     0x6D, 0x6F, 0x76, 0x69  // "movi"
00216 };
00217 
00218 static void set_data(uint8_t * buf, uint32_t data) {
00219     if (buf != NULL) {
00220         buf[0] = ((data >> 0)  & 0xFF);
00221         buf[1] = ((data >> 8)  & 0xFF);
00222         buf[2] = ((data >> 16) & 0xFF);
00223         buf[3] = ((data >> 24) & 0xFF);
00224     }
00225 }
00226 
00227 int main() {
00228     EasyAttach_Init(Display);
00229     Start_Video_Camera();
00230 #if MBED_CONF_APP_LCD
00231     Start_LCD_Display();
00232 #endif
00233     SdUsbConnect storage(MOUNT_NAME);
00234     FILE * fp;
00235     char file_name[32];
00236     int mjpg_pointer = 0;
00237     int mjpg_frame = 0;
00238     uint32_t fps;
00239     Timer t;
00240 
00241     while (1) {
00242         storage.wait_connect();
00243 
00244         if (led1 == 0) {
00245             if (button0 == 0) {
00246                 led1 = 1;
00247                 sprintf(file_name, "/"MOUNT_NAME"/movie_%d.avi", file_name_index++);
00248                 fp = fopen(file_name, "w");
00249                 if (fp != NULL) {
00250                     setvbuf(fp, NULL, _IONBF, 0); // unbuffered
00251                     mjpg_frame = 0;
00252                     mjpg_pointer = sizeof(MJpegHeader);
00253                     fseek(fp, mjpg_pointer, SEEK_SET);
00254                     t.reset();
00255                     t.start();
00256                 } else {
00257                     led1 = 0;
00258                 }
00259             }
00260         }
00261         if (led1 == 1) {
00262             if ((button0 == 0) && (mjpg_frame < MAX_FRAME_NUM)) {
00263                 size_t jcu_encode_size = 0;
00264                 JPEG_Converter::bitmap_buff_info_t bitmap_buff_info;
00265                 JPEG_Converter::encode_options_t   encode_options;
00266 
00267                 wait_new_image(); // wait for image input
00268 
00269                 bitmap_buff_info.width              = VIDEO_PIXEL_HW;
00270                 bitmap_buff_info.height             = VIDEO_PIXEL_VW;
00271                 bitmap_buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00272                 bitmap_buff_info.buffer_address     = (void *)user_frame_buffer0;
00273 
00274                 encode_options.encode_buff_size     = sizeof(JpegBuffer);
00275                 encode_options.p_EncodeCallBackFunc = NULL;
00276                 encode_options.input_swapsetting    = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
00277 
00278                 dcache_invalid(JpegBuffer, sizeof(JpegBuffer));
00279                 if (Jcu.encode(&bitmap_buff_info, JpegBuffer, &jcu_encode_size, &encode_options) == JPEG_Converter::JPEG_CONV_OK) {
00280                     if ((jcu_encode_size & 0x1) != 0) {
00281                         JpegBuffer[jcu_encode_size] = 0;
00282                         jcu_encode_size++;
00283                     }
00284                     memcpy(&work_buf[0], "00dc", 4);
00285                     set_data(&work_buf[4], jcu_encode_size);
00286                     fwrite(work_buf, sizeof(char), (int)8, fp);
00287                     fwrite(JpegBuffer, sizeof(char), (int)jcu_encode_size, fp);
00288                     mjpg_index[mjpg_frame] = mjpg_pointer + 4 - sizeof(MJpegHeader);
00289                     mjpg_size[mjpg_frame] = jcu_encode_size;
00290                     mjpg_frame++;
00291                     mjpg_pointer += (jcu_encode_size + 8);
00292                 }
00293             } else {
00294                 t.stop();
00295                 fps = mjpg_frame * 1000 / t.read_ms();
00296 
00297                 memcpy(work_buf, MJpegHeader, sizeof(MJpegHeader));
00298                 set_data(&work_buf[4], mjpg_pointer + 16 + (mjpg_frame * 8) - 8);
00299                 set_data(&work_buf[32], 1000000.0 / fps);
00300                 set_data(&work_buf[48], mjpg_frame);
00301                 set_data(&work_buf[132], fps);
00302                 set_data(&work_buf[140], mjpg_frame);
00303                 if (mjpg_pointer > 0xDC){
00304                     set_data(&work_buf[216], mjpg_pointer - 0xDC);
00305                 } else {
00306                     set_data(&work_buf[216],0);
00307                 }
00308                 fseek(fp, 0, SEEK_SET);
00309                 fwrite(work_buf, sizeof(char), sizeof(MJpegHeader), fp);
00310 
00311                 memcpy(&work_buf[0], "idx1", 4);
00312                 set_data(&work_buf[4], mjpg_frame * 16);
00313                 fseek(fp, mjpg_pointer, SEEK_SET);
00314                 fwrite(work_buf, sizeof(char), 8, fp);
00315 
00316                 for (int i = 0; i < mjpg_frame; i++){
00317                     memcpy(&work_buf[0], "00dc", 4);
00318                     set_data(&work_buf[4], 16);
00319                     set_data(&work_buf[8], mjpg_index[i]);
00320                     set_data(&work_buf[12], mjpg_size[i]);
00321                     fwrite(work_buf, sizeof(char), 16, fp);
00322                 }
00323 
00324                 fclose(fp);
00325                 printf("Saved file %s , %dfps\r\n", file_name, fps);
00326                 led1 = 0;
00327             }
00328         }
00329     }
00330 }
00331 #endif