]> Chaos Git - corbenik/ctrulib.git/commitdiff
Fix freezing on camera image example, add camera video example
authorEric Ahn <wchill1337@gmail.com>
Thu, 22 Oct 2015 17:32:41 +0000 (12:32 -0500)
committerEric Ahn <wchill1337@gmail.com>
Thu, 22 Oct 2015 17:37:12 +0000 (12:37 -0500)
examples/camera/image/Makefile [moved from examples/camera/Makefile with 100% similarity]
examples/camera/image/README.md [moved from examples/camera/README.md with 97% similarity]
examples/camera/image/image.xml [moved from examples/camera/camera.xml with 100% similarity]
examples/camera/image/src/main.c [moved from examples/camera/src/main.c with 80% similarity]
examples/camera/video/Makefile [new file with mode: 0644]
examples/camera/video/README.md [new file with mode: 0644]
examples/camera/video/src/main.c [new file with mode: 0644]
examples/camera/video/video.xml [new file with mode: 0644]

similarity index 97%
rename from examples/camera/README.md
rename to examples/camera/image/README.md
index d0b9ab2527005a8be35f32644ead8f202606b552..5c444a192280d3dc70b606cdaf9fd68837e69186 100644 (file)
@@ -1,4 +1,4 @@
-camera
+image
 =======
 
 Example for using the camera to take 3D pictures with ctrulib. Press the R button to take a picture - it will be displayed on the top screen.
similarity index 80%
rename from examples/camera/src/main.c
rename to examples/camera/image/src/main.c
index 3ca81b42be0ff7d62efb4a49f9bffe81d0dc7500..3f2827dfd64720423bba4836339f6b8c8a56c50c 100644 (file)
@@ -65,35 +65,30 @@ void writePictureToFramebufferRGB565(void *fb, void *img, u16 x, u16 y, u16 widt
 
 // TODO: Figure out how to use CAMU_GetStereoCameraCalibrationData
 void takePicture3D(u8 *buf) {
-
        u32 bufSize;
        printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
-       printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_CAM1, bufSize, WIDTH, HEIGHT));
-       printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_CAM2, bufSize, WIDTH, HEIGHT));
+       printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
 
        printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
 
        Handle camReceiveEvent = 0;
        Handle camReceiveEvent2 = 0;
 
-       printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_CAM1));
-       printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_CAM2));
+       printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
        printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
-       printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
-       printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
-       printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_CAM1));
-       printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_CAM2));
-       printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
-       printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
 
-       // TODO: Figure out why system hangs here sometimes
+       printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
+
        printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
        printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
-       printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
        printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
        printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
-       printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_CAM1));
-       printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_CAM2));
+       printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
+
+       printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
+
+       svcCloseHandle(camReceiveEvent);
+       svcCloseHandle(camReceiveEvent2);
 
        printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
 }
@@ -133,7 +128,7 @@ int main() {
        printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM2, false));
        //printf("CAMU_SetTrimmingParamsCenter: 0x%08X\n", (unsigned int) CAMU_SetTrimmingParamsCenter(PORT_CAM1, 512, 240, 512, 384));
 
-       u8 *buf = malloc(400*240*3*2);
+       u8 *buf = malloc(BUF_SIZE);
        if(!buf) {
                hang("Failed to allocate memory!");
        }
@@ -160,15 +155,13 @@ int main() {
                        break;
                }
 
-               if (kHeld & KEY_R) {
-                       if(!held_R) {
-                               printf("Capturing new image (may hang!)\n");
-                               gfxFlushBuffers();
-                               gspWaitForVBlank();
-                               gfxSwapBuffers();
-                               held_R = true;
-                               takePicture3D(buf);
-                       }
+               if ((kHeld & KEY_R) && !held_R) {
+                       printf("Capturing new image\n");
+                       gfxFlushBuffers();
+                       gspWaitForVBlank();
+                       gfxSwapBuffers();
+                       held_R = true;
+                       takePicture3D(buf);
                } else if (!(kHeld & KEY_R)) {
                        held_R = false;
                }
diff --git a/examples/camera/video/Makefile b/examples/camera/video/Makefile
new file mode 100644 (file)
index 0000000..b50b77f
--- /dev/null
@@ -0,0 +1,172 @@
+#---------------------------------------------------------------------------------\r
+.SUFFIXES:\r
+#---------------------------------------------------------------------------------\r
+\r
+ifeq ($(strip $(DEVKITARM)),)\r
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")\r
+endif\r
+\r
+TOPDIR ?= $(CURDIR)\r
+include $(DEVKITARM)/3ds_rules\r
+\r
+#---------------------------------------------------------------------------------\r
+# TARGET is the name of the output\r
+# BUILD is the directory where object files & intermediate files will be placed\r
+# SOURCES is a list of directories containing source code\r
+# DATA is a list of directories containing data files\r
+# INCLUDES is a list of directories containing header files\r
+#\r
+# NO_SMDH: if set to anything, no SMDH file is generated.\r
+# APP_TITLE is the name of the app stored in the SMDH file (Optional)\r
+# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)\r
+# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)\r
+# ICON is the filename of the icon (.png), relative to the project folder.\r
+#   If not set, it attempts to use one of the following (in this order):\r
+#     - <Project name>.png\r
+#     - icon.png\r
+#     - <libctru folder>/default_icon.png\r
+#---------------------------------------------------------------------------------\r
+TARGET               :=        $(notdir $(CURDIR))\r
+BUILD                  :=      build\r
+SOURCES                      :=        src\r
+DATA                   :=      data\r
+INCLUDES             :=        include\r
+APP_TITLE       :=  3D Camera Example\r
+APP_DESCRIPTION :=  Example application that takes 3D pictures\r
+APP_AUTHOR      :=  wchill\r
+\r
+#---------------------------------------------------------------------------------\r
+# options for code generation\r
+#---------------------------------------------------------------------------------\r
+ARCH   :=      -march=armv6k -mtune=mpcore -mfloat-abi=hard\r
+\r
+CFLAGS :=      -g -Wall -O2 -mword-relocations \\r
+                       -fomit-frame-pointer -ffast-math \\r
+                       $(ARCH)\r
+\r
+CFLAGS +=      $(INCLUDE) -DARM11 -D_3DS\r
+\r
+CXXFLAGS       := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11\r
+\r
+ASFLAGS        :=      -g $(ARCH)\r
+LDFLAGS        =       -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)\r
+\r
+LIBS   := -lctru -lm\r
+\r
+#---------------------------------------------------------------------------------\r
+# list of directories containing libraries, this must be the top level containing\r
+# include and lib\r
+#---------------------------------------------------------------------------------\r
+LIBDIRS        := $(CTRULIB)\r
+\r
+\r
+#---------------------------------------------------------------------------------\r
+# no real need to edit anything past this point unless you need to add additional\r
+# rules for different file extensions\r
+#---------------------------------------------------------------------------------\r
+ifneq ($(BUILD),$(notdir $(CURDIR)))\r
+#---------------------------------------------------------------------------------\r
+\r
+export OUTPUT  :=      $(CURDIR)/$(TARGET)\r
+export TOPDIR  :=      $(CURDIR)\r
+\r
+export VPATH   :=      $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \\r
+                       $(foreach dir,$(DATA),$(CURDIR)/$(dir))\r
+\r
+export DEPSDIR :=      $(CURDIR)/$(BUILD)\r
+\r
+CFILES         :=      $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))\r
+CPPFILES       :=      $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))\r
+SFILES         :=      $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))\r
+BINFILES       :=      $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))\r
+\r
+#---------------------------------------------------------------------------------\r
+# use CXX for linking C++ projects, CC for standard C\r
+#---------------------------------------------------------------------------------\r
+ifeq ($(strip $(CPPFILES)),)\r
+#---------------------------------------------------------------------------------\r
+       export LD       :=      $(CC)\r
+#---------------------------------------------------------------------------------\r
+else\r
+#---------------------------------------------------------------------------------\r
+       export LD       :=      $(CXX)\r
+#---------------------------------------------------------------------------------\r
+endif\r
+#---------------------------------------------------------------------------------\r
+\r
+export OFILES  :=      $(addsuffix .o,$(BINFILES)) \\r
+                       $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)\r
+\r
+export INCLUDE :=      $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \\r
+                       $(foreach dir,$(LIBDIRS),-I$(dir)/include) \\r
+                       -I$(CURDIR)/$(BUILD)\r
+\r
+export LIBPATHS        :=      $(foreach dir,$(LIBDIRS),-L$(dir)/lib)\r
+\r
+ifeq ($(strip $(ICON)),)\r
+       icons := $(wildcard *.png)\r
+       ifneq (,$(findstring $(TARGET).png,$(icons)))\r
+               export APP_ICON := $(TOPDIR)/$(TARGET).png\r
+       else\r
+               ifneq (,$(findstring icon.png,$(icons)))\r
+                       export APP_ICON := $(TOPDIR)/icon.png\r
+               endif\r
+       endif\r
+else\r
+       export APP_ICON := $(TOPDIR)/$(ICON)\r
+endif\r
+\r
+.PHONY: $(BUILD) clean all\r
+\r
+#---------------------------------------------------------------------------------\r
+all: $(BUILD)\r
+\r
+$(BUILD):\r
+       @[ -d $@ ] || mkdir -p $@\r
+       @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile\r
+\r
+#---------------------------------------------------------------------------------\r
+clean:\r
+       @echo clean ...\r
+       @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf\r
+\r
+#---------------------------------------------------------------------------------\r
+else\r
+\r
+DEPENDS        :=      $(OFILES:.o=.d)\r
+\r
+#---------------------------------------------------------------------------------\r
+# main targets\r
+#---------------------------------------------------------------------------------\r
+ifeq ($(strip $(NO_SMDH)),)\r
+.PHONY: all\r
+all    :       $(OUTPUT).3dsx $(OUTPUT).smdh\r
+endif\r
+$(OUTPUT).3dsx :       $(OUTPUT).elf\r
+$(OUTPUT).elf  :       $(OFILES)\r
+\r
+#---------------------------------------------------------------------------------\r
+# you need a rule like this for each extension you use as binary data\r
+#---------------------------------------------------------------------------------\r
+%.bin.o        :       %.bin\r
+#---------------------------------------------------------------------------------\r
+       @echo $(notdir $<)\r
+       @$(bin2o)\r
+\r
+# WARNING: This is not the right way to do this! TODO: Do it right!\r
+#---------------------------------------------------------------------------------\r
+%.vsh.o        :       %.vsh\r
+#---------------------------------------------------------------------------------\r
+       @echo $(notdir $<)\r
+       @python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin\r
+       @bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@\r
+       @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h\r
+       @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h\r
+       @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h\r
+       @rm ../$(notdir $<).shbin\r
+\r
+-include $(DEPENDS)\r
+\r
+#---------------------------------------------------------------------------------------\r
+endif\r
+#---------------------------------------------------------------------------------------\r
diff --git a/examples/camera/video/README.md b/examples/camera/video/README.md
new file mode 100644 (file)
index 0000000..7c1e3c1
--- /dev/null
@@ -0,0 +1,7 @@
+video
+=======
+
+Example for using the camera to capture 3D videos with ctrulib.
+
+Currently this example does not make use of the 3DS camera's calibration data to get a correct 3D effect.
+
diff --git a/examples/camera/video/src/main.c b/examples/camera/video/src/main.c
new file mode 100644 (file)
index 0000000..f083034
--- /dev/null
@@ -0,0 +1,206 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <setjmp.h>
+#include <3ds.h>
+#include <sys/dirent.h>
+#include <sys/errno.h>
+#include <sys/unistd.h>
+#include <stdbool.h>
+
+#define CONFIG_3D_SLIDERSTATE (*(volatile float*)0x1FF81080)
+#define WAIT_TIMEOUT 1000000000ULL
+
+#define WIDTH 400
+#define HEIGHT 240
+#define SCREEN_SIZE WIDTH * HEIGHT * 2
+#define BUF_SIZE SCREEN_SIZE * 2
+
+static jmp_buf exitJmp;
+
+inline void clearScreen(void) {
+       u8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
+       memset(frame, 0, 320 * 240 * 3);
+}
+
+void hang(char *message) {
+       clearScreen();
+       printf("%s", message);
+       printf("Press start to exit");
+
+       while (aptMainLoop()) {
+               hidScanInput();
+
+               u32 kHeld = hidKeysHeld();
+               if (kHeld & KEY_START) longjmp(exitJmp, 1);
+       }
+}
+
+void cleanup() {
+       camExit();
+       gfxExit();
+       acExit();
+}
+
+void writePictureToFramebufferRGB565(void *fb, void *img, u16 x, u16 y, u16 width, u16 height) {
+       u8 *fb_8 = (u8*) fb;
+       u16 *img_16 = (u16*) img;
+       int i, j, draw_x, draw_y;
+       for(j = 0; j < height; j++) {
+               for(i = 0; i < width; i++) {
+                       draw_y = y + height - j;
+                       draw_x = x + i;
+                       u32 v = (draw_y + draw_x * height) * 3;
+                       u16 data = img_16[j * width + i];
+                       uint8_t b = ((data >> 11) & 0x1F) << 3;
+                       uint8_t g = ((data >> 5) & 0x3F) << 2;
+                       uint8_t r = (data & 0x1F) << 3;
+                       fb_8[v] = r;
+                       fb_8[v+1] = g;
+                       fb_8[v+2] = b;
+               }
+       }
+}
+
+// TODO: Figure out how to use CAMU_GetStereoCameraCalibrationData
+void takePicture3D(u8 *buf) {
+       u32 bufSize;
+       printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
+       printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
+
+       printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
+
+       Handle camReceiveEvent = 0;
+       Handle camReceiveEvent2 = 0;
+
+       printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
+       printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
+
+       printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
+
+       printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
+       printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
+       printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
+       printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
+       printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
+
+       printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
+
+       svcCloseHandle(camReceiveEvent);
+       svcCloseHandle(camReceiveEvent2);
+
+       printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
+}
+
+int main() {
+       // Initializations
+       acInit();
+       gfxInitDefault();
+       consoleInit(GFX_BOTTOM, NULL);
+
+       // Enable double buffering to remove screen tearing
+       gfxSetDoubleBuffering(GFX_TOP, true);
+       gfxSetDoubleBuffering(GFX_BOTTOM, false);
+
+       // Save current stack frame for easy exit
+       if(setjmp(exitJmp)) {
+               cleanup();
+               return 0;
+       }
+
+       u32 kDown;
+
+       printf("Initializing camera\n");
+
+       printf("camInit: 0x%08X\n", (unsigned int) camInit());
+
+       printf("CAMU_SetSize: 0x%08X\n", (unsigned int) CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A));
+       printf("CAMU_SetOutputFormat: 0x%08X\n", (unsigned int) CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A));
+
+       // TODO: For some reason frame grabbing times out above 10fps. Figure out why this is.
+       printf("CAMU_SetFrameRate: 0x%08X\n", (unsigned int) CAMU_SetFrameRate(SELECT_OUT1_OUT2, FRAME_RATE_10));
+
+       printf("CAMU_SetNoiseFilter: 0x%08X\n", (unsigned int) CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true));
+       printf("CAMU_SetAutoExposure: 0x%08X\n", (unsigned int) CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true));
+       printf("CAMU_SetAutoWhiteBalance: 0x%08X\n", (unsigned int) CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true));
+       // TODO: Figure out how to use the effects properly.
+       //printf("CAMU_SetEffect: 0x%08X\n", (unsigned int) CAMU_SetEffect(SELECT_OUT1_OUT2, EFFECT_SEPIA, CONTEXT_A));
+
+       printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM1, false));
+       printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM2, false));
+       //printf("CAMU_SetTrimmingParamsCenter: 0x%08X\n", (unsigned int) CAMU_SetTrimmingParamsCenter(PORT_CAM1, 512, 240, 512, 384));
+
+       u8 *buf = malloc(BUF_SIZE);
+       if(!buf) {
+               hang("Failed to allocate memory!");
+       }
+
+       u32 bufSize;
+       printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
+       printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
+
+       printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
+
+       Handle camReceiveEvent = 0;
+       Handle camReceiveEvent2 = 0;
+
+       printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
+       printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
+
+       printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
+       printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_MOVIE));
+
+       gfxFlushBuffers();
+       gspWaitForVBlank();
+       gfxSwapBuffers();
+
+       printf("\nUse slider to enable/disable 3D\n");
+       printf("Press Start to exit to Homebrew Launcher\n");
+
+       // Main loop
+       while (aptMainLoop()) {
+               // Read which buttons are currently pressed or not
+               hidScanInput();
+               kDown = hidKeysDown();
+
+               // If START button is pressed, break loop and quit
+               if (kDown & KEY_START) {
+                       break;
+               }
+
+               printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
+               CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize);
+
+               printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
+               svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT);
+
+               if(CONFIG_3D_SLIDERSTATE > 0.0f) {
+                       gfxSet3D(true);
+                       writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
+                       writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), buf + SCREEN_SIZE, 0, 0, WIDTH, HEIGHT);
+               } else {
+                       gfxSet3D(false);
+                       writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
+               }
+
+               printf("svcCloseHandle: 0x%08X\n", (unsigned int) svcCloseHandle(camReceiveEvent));
+               svcCloseHandle(camReceiveEvent2);
+
+               // Flush and swap framebuffers
+               gfxFlushBuffers();
+               gspWaitForVBlank();
+               gfxSwapBuffers();
+       }
+
+       printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
+
+       printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
+
+       // Exit
+       free(buf);
+       cleanup();
+
+       // Return to hbmenu
+       return 0;
+}
diff --git a/examples/camera/video/video.xml b/examples/camera/video/video.xml
new file mode 100644 (file)
index 0000000..30545b3
--- /dev/null
@@ -0,0 +1,3 @@
+<targets selectable="false">
+    <title mediatype="0">0004001000021400</title>
+</targets>